diff options
Diffstat (limited to 'modules/text_server_adv')
-rw-r--r-- | modules/text_server_adv/text_server_adv.cpp | 258 | ||||
-rw-r--r-- | modules/text_server_adv/text_server_adv.h | 4 |
2 files changed, 148 insertions, 114 deletions
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index fa4888f843..66816f32d1 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -1161,7 +1161,7 @@ bool TextServerAdvanced::shaped_text_add_string(RID p_shaped, const String &p_te return true; } -bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align, int p_length) { +bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) { _THREAD_SAFE_METHOD_ ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); ERR_FAIL_COND_V(!sd, false); @@ -1191,7 +1191,7 @@ bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, con return true; } -bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align) { +bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) { _THREAD_SAFE_METHOD_ ShapedTextData *sd = shaped_owner.getornull(p_shaped); ERR_FAIL_COND_V(!sd, false); @@ -1222,34 +1222,10 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, if (sd->orientation == ORIENTATION_HORIZONTAL) { sd->objects[key].rect.position.x = sd->width; sd->width += sd->objects[key].rect.size.x; - switch (sd->objects[key].inline_align) { - case VALIGN_TOP: { - sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y); - } break; - case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, Math::round(sd->objects[key].rect.size.y / 2)); - sd->descent = MAX(sd->descent, Math::round(sd->objects[key].rect.size.y / 2)); - } break; - case VALIGN_BOTTOM: { - sd->descent = MAX(sd->descent, sd->objects[key].rect.size.y); - } break; - } sd->glyphs.write[i].advance = sd->objects[key].rect.size.x; } else { sd->objects[key].rect.position.y = sd->width; sd->width += sd->objects[key].rect.size.y; - switch (sd->objects[key].inline_align) { - case VALIGN_TOP: { - sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x); - } break; - case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, Math::round(sd->objects[key].rect.size.x / 2)); - sd->descent = MAX(sd->descent, Math::round(sd->objects[key].rect.size.x / 2)); - } break; - case VALIGN_BOTTOM: { - sd->descent = MAX(sd->descent, sd->objects[key].rect.size.x); - } break; - } sd->glyphs.write[i].advance = sd->objects[key].rect.size.y; } } else { @@ -1279,35 +1255,71 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, } // Align embedded objects to baseline. + float full_ascent = sd->ascent; + float full_descent = sd->descent; for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { if ((E->get().pos >= sd->start) && (E->get().pos < sd->end)) { if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E->get().inline_align) { - case VALIGN_TOP: { + switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + case INLINE_ALIGN_TO_TOP: { E->get().rect.position.y = -sd->ascent; } break; - case VALIGN_CENTER: { - E->get().rect.position.y = -(E->get().rect.size.y / 2); + case INLINE_ALIGN_TO_CENTER: { + E->get().rect.position.y = (-sd->ascent + sd->descent) / 2; + } break; + case INLINE_ALIGN_TO_BASELINE: { + E->get().rect.position.y = 0; + } break; + case INLINE_ALIGN_TO_BOTTOM: { + E->get().rect.position.y = sd->descent; + } break; + } + switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + case INLINE_ALIGN_BOTTOM_TO: { + E->get().rect.position.y -= E->get().rect.size.y; + } break; + case INLINE_ALIGN_CENTER_TO: { + E->get().rect.position.y -= E->get().rect.size.y / 2; } break; - case VALIGN_BOTTOM: { - E->get().rect.position.y = sd->descent - E->get().rect.size.y; + case INLINE_ALIGN_TOP_TO: { + //NOP } break; } + full_ascent = MAX(full_ascent, -E->get().rect.position.y); + full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y); } else { - switch (E->get().inline_align) { - case VALIGN_TOP: { + switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + case INLINE_ALIGN_TO_TOP: { E->get().rect.position.x = -sd->ascent; } break; - case VALIGN_CENTER: { - E->get().rect.position.x = -(E->get().rect.size.x / 2); + case INLINE_ALIGN_TO_CENTER: { + E->get().rect.position.x = (-sd->ascent + sd->descent) / 2; + } break; + case INLINE_ALIGN_TO_BASELINE: { + E->get().rect.position.x = 0; } break; - case VALIGN_BOTTOM: { - E->get().rect.position.x = sd->descent - E->get().rect.size.x; + case INLINE_ALIGN_TO_BOTTOM: { + E->get().rect.position.x = sd->descent; } break; } + switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + case INLINE_ALIGN_BOTTOM_TO: { + E->get().rect.position.x -= E->get().rect.size.x; + } break; + case INLINE_ALIGN_CENTER_TO: { + E->get().rect.position.x -= E->get().rect.size.x / 2; + } break; + case INLINE_ALIGN_TOP_TO: { + //NOP + } break; + } + full_ascent = MAX(full_ascent, -E->get().rect.position.x); + full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x); } } } + sd->ascent = full_ascent; + sd->descent = full_descent; } return true; } @@ -1404,33 +1416,9 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng if (new_sd->orientation == ORIENTATION_HORIZONTAL) { new_sd->objects[key].rect.position.x = new_sd->width; new_sd->width += new_sd->objects[key].rect.size.x; - switch (new_sd->objects[key].inline_align) { - case VALIGN_TOP: { - new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.y); - } break; - case VALIGN_CENTER: { - new_sd->ascent = MAX(new_sd->ascent, Math::round(new_sd->objects[key].rect.size.y / 2)); - new_sd->descent = MAX(new_sd->descent, Math::round(new_sd->objects[key].rect.size.y / 2)); - } break; - case VALIGN_BOTTOM: { - new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.y); - } break; - } } else { new_sd->objects[key].rect.position.y = new_sd->width; new_sd->width += new_sd->objects[key].rect.size.y; - switch (new_sd->objects[key].inline_align) { - case VALIGN_TOP: { - new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.x); - } break; - case VALIGN_CENTER: { - new_sd->ascent = MAX(new_sd->ascent, Math::round(new_sd->objects[key].rect.size.x / 2)); - new_sd->descent = MAX(new_sd->descent, Math::round(new_sd->objects[key].rect.size.x / 2)); - } break; - case VALIGN_BOTTOM: { - new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.x); - } break; - } } } else { if (prev_rid != gl.font_rid) { @@ -1464,37 +1452,72 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng } // Align embedded objects to baseline. + float full_ascent = new_sd->ascent; + float full_descent = new_sd->descent; for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = new_sd->objects.front(); E; E = E->next()) { if ((E->get().pos >= new_sd->start) && (E->get().pos < new_sd->end)) { if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E->get().inline_align) { - case VALIGN_TOP: { + switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + case INLINE_ALIGN_TO_TOP: { E->get().rect.position.y = -new_sd->ascent; } break; - case VALIGN_CENTER: { - E->get().rect.position.y = -(E->get().rect.size.y / 2); + case INLINE_ALIGN_TO_CENTER: { + E->get().rect.position.y = (-new_sd->ascent + new_sd->descent) / 2; + } break; + case INLINE_ALIGN_TO_BASELINE: { + E->get().rect.position.y = 0; + } break; + case INLINE_ALIGN_TO_BOTTOM: { + E->get().rect.position.y = new_sd->descent; } break; - case VALIGN_BOTTOM: { - E->get().rect.position.y = new_sd->descent - E->get().rect.size.y; + } + switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + case INLINE_ALIGN_BOTTOM_TO: { + E->get().rect.position.y -= E->get().rect.size.y; + } break; + case INLINE_ALIGN_CENTER_TO: { + E->get().rect.position.y -= E->get().rect.size.y / 2; + } break; + case INLINE_ALIGN_TOP_TO: { + //NOP } break; } + full_ascent = MAX(full_ascent, -E->get().rect.position.y); + full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y); } else { - switch (E->get().inline_align) { - case VALIGN_TOP: { + switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + case INLINE_ALIGN_TO_TOP: { E->get().rect.position.x = -new_sd->ascent; } break; - case VALIGN_CENTER: { - E->get().rect.position.x = -(E->get().rect.size.x / 2); + case INLINE_ALIGN_TO_CENTER: { + E->get().rect.position.x = (-new_sd->ascent + new_sd->descent) / 2; } break; - case VALIGN_BOTTOM: { - E->get().rect.position.x = new_sd->descent - E->get().rect.size.x; + case INLINE_ALIGN_TO_BASELINE: { + E->get().rect.position.x = 0; + } break; + case INLINE_ALIGN_TO_BOTTOM: { + E->get().rect.position.x = new_sd->descent; } break; } + switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + case INLINE_ALIGN_BOTTOM_TO: { + E->get().rect.position.x -= E->get().rect.size.x; + } break; + case INLINE_ALIGN_CENTER_TO: { + E->get().rect.position.x -= E->get().rect.size.x / 2; + } break; + case INLINE_ALIGN_TOP_TO: { + //NOP + } break; + } + full_ascent = MAX(full_ascent, -E->get().rect.position.x); + full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x); } } } + new_sd->ascent = full_ascent; + new_sd->descent = full_descent; } - new_sd->valid = true; return shaped_owner.make_rid(new_sd); @@ -2473,33 +2496,9 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { if (sd->orientation == ORIENTATION_HORIZONTAL) { sd->objects[span.embedded_key].rect.position.x = sd->width; sd->width += sd->objects[span.embedded_key].rect.size.x; - switch (sd->objects[span.embedded_key].inline_align) { - case VALIGN_TOP: { - sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y); - } break; - case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, Math::round(sd->objects[span.embedded_key].rect.size.y / 2)); - sd->descent = MAX(sd->descent, Math::round(sd->objects[span.embedded_key].rect.size.y / 2)); - } break; - case VALIGN_BOTTOM: { - sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.y); - } break; - } } else { sd->objects[span.embedded_key].rect.position.y = sd->width; sd->width += sd->objects[span.embedded_key].rect.size.y; - switch (sd->objects[span.embedded_key].inline_align) { - case VALIGN_TOP: { - sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x); - } break; - case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, Math::round(sd->objects[span.embedded_key].rect.size.x / 2)); - sd->descent = MAX(sd->descent, Math::round(sd->objects[span.embedded_key].rect.size.x / 2)); - } break; - case VALIGN_BOTTOM: { - sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.x); - } break; - } } Glyph gl; gl.start = span.start; @@ -2539,34 +2538,69 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { } // Align embedded objects to baseline. + float full_ascent = sd->ascent; + float full_descent = sd->descent; for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E->get().inline_align) { - case VALIGN_TOP: { + switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + case INLINE_ALIGN_TO_TOP: { E->get().rect.position.y = -sd->ascent; } break; - case VALIGN_CENTER: { - E->get().rect.position.y = -(E->get().rect.size.y / 2); + case INLINE_ALIGN_TO_CENTER: { + E->get().rect.position.y = (-sd->ascent + sd->descent) / 2; } break; - case VALIGN_BOTTOM: { - E->get().rect.position.y = sd->descent - E->get().rect.size.y; + case INLINE_ALIGN_TO_BASELINE: { + E->get().rect.position.y = 0; + } break; + case INLINE_ALIGN_TO_BOTTOM: { + E->get().rect.position.y = sd->descent; + } break; + } + switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + case INLINE_ALIGN_BOTTOM_TO: { + E->get().rect.position.y -= E->get().rect.size.y; + } break; + case INLINE_ALIGN_CENTER_TO: { + E->get().rect.position.y -= E->get().rect.size.y / 2; + } break; + case INLINE_ALIGN_TOP_TO: { + //NOP } break; } + full_ascent = MAX(full_ascent, -E->get().rect.position.y); + full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y); } else { - switch (E->get().inline_align) { - case VALIGN_TOP: { + switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + case INLINE_ALIGN_TO_TOP: { E->get().rect.position.x = -sd->ascent; } break; - case VALIGN_CENTER: { - E->get().rect.position.x = -(E->get().rect.size.x / 2); + case INLINE_ALIGN_TO_CENTER: { + E->get().rect.position.x = (-sd->ascent + sd->descent) / 2; + } break; + case INLINE_ALIGN_TO_BASELINE: { + E->get().rect.position.x = 0; } break; - case VALIGN_BOTTOM: { - E->get().rect.position.x = sd->descent - E->get().rect.size.x; + case INLINE_ALIGN_TO_BOTTOM: { + E->get().rect.position.x = sd->descent; } break; } + switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + case INLINE_ALIGN_BOTTOM_TO: { + E->get().rect.position.x -= E->get().rect.size.x; + } break; + case INLINE_ALIGN_CENTER_TO: { + E->get().rect.position.x -= E->get().rect.size.x / 2; + } break; + case INLINE_ALIGN_TOP_TO: { + //NOP + } break; + } + full_ascent = MAX(full_ascent, -E->get().rect.position.x); + full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x); } } - + sd->ascent = full_ascent; + sd->descent = full_descent; sd->valid = true; return sd->valid; } diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 3c4f840bfd..c54686c114 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -216,8 +216,8 @@ public: virtual bool shaped_text_get_preserve_control(RID p_shaped) const override; virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") override; - virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER, int p_length = 1) override; - virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER) override; + virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) override; + virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) override; virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override; virtual RID shaped_text_get_parent(RID p_shaped) const override; |