diff options
Diffstat (limited to 'modules/text_server_adv')
-rw-r--r-- | modules/text_server_adv/icu_data/icudata_stub.cpp | 4 | ||||
-rw-r--r-- | modules/text_server_adv/register_types.cpp | 4 | ||||
-rw-r--r-- | modules/text_server_adv/register_types.h | 4 | ||||
-rw-r--r-- | modules/text_server_adv/script_iterator.cpp | 4 | ||||
-rw-r--r-- | modules/text_server_adv/script_iterator.h | 4 | ||||
-rw-r--r-- | modules/text_server_adv/text_server_adv.cpp | 330 | ||||
-rw-r--r-- | modules/text_server_adv/text_server_adv.h | 9 |
7 files changed, 192 insertions, 167 deletions
diff --git a/modules/text_server_adv/icu_data/icudata_stub.cpp b/modules/text_server_adv/icu_data/icudata_stub.cpp index 187001f33a..47dfa5ce26 100644 --- a/modules/text_server_adv/icu_data/icudata_stub.cpp +++ b/modules/text_server_adv/icu_data/icudata_stub.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/text_server_adv/register_types.cpp b/modules/text_server_adv/register_types.cpp index b711d1561f..d2dbfa045b 100644 --- a/modules/text_server_adv/register_types.cpp +++ b/modules/text_server_adv/register_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/text_server_adv/register_types.h b/modules/text_server_adv/register_types.h index ddd1190f40..d2b49fce6e 100644 --- a/modules/text_server_adv/register_types.h +++ b/modules/text_server_adv/register_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/text_server_adv/script_iterator.cpp b/modules/text_server_adv/script_iterator.cpp index d1e849def8..9e3d9138d0 100644 --- a/modules/text_server_adv/script_iterator.cpp +++ b/modules/text_server_adv/script_iterator.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/text_server_adv/script_iterator.h b/modules/text_server_adv/script_iterator.h index 5efd40f7c4..1e11b51521 100644 --- a/modules/text_server_adv/script_iterator.h +++ b/modules/text_server_adv/script_iterator.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index f480c86088..f1945f62cb 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -942,7 +942,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( FontGlyph chr; chr.found = true; - chr.advance = advance.round(); + chr.advance = advance; if (shape.validate() && shape.contours.size() > 0) { int w = (bounds.r - bounds.l); @@ -1095,12 +1095,12 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma } FontGlyph chr; - chr.advance = (advance * p_data->scale / p_data->oversampling).round(); + chr.advance = advance * p_data->scale / p_data->oversampling; chr.texture_idx = tex_pos.index; chr.found = true; chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h); - chr.rect.position = (Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling).round(); + chr.rect.position = Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling; chr.rect.size = chr.uv_rect.size * p_data->scale / p_data->oversampling; return chr; } @@ -1270,7 +1270,8 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced } FT_Select_Size(fd->face, best_match); } else { - FT_Set_Pixel_Sizes(fd->face, 0, fd->size.x * fd->oversampling); + FT_Set_Pixel_Sizes(fd->face, 0, float(fd->size.x * fd->oversampling)); + fd->scale = ((float)fd->size.x * fd->oversampling) / (float)fd->face->size->metrics.y_ppem; } fd->hb_handle = hb_ft_font_create(fd->face, nullptr); @@ -2670,7 +2671,7 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz Vector2i size = _get_size(fd, p_size); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); if (!_ensure_glyph(fd, size, p_index)) { - return; // // Invalid or non graphicl glyph, do not display errors, nothing to draw. + return; // Invalid or non-graphical glyph, do not display errors, nothing to draw. } const FontGlyph &gl = fd->cache[size]->glyph_map[p_index]; @@ -2692,9 +2693,9 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size; RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range); } else { - Point2i cpos = p_pos; + Point2 cpos = p_pos.floor(); cpos += gl.rect.position; - Size2i csize = gl.rect.size; + Size2 csize = gl.rect.size; RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); } } @@ -2710,7 +2711,7 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i Vector2i size = _get_size_outline(fd, Vector2i(p_size, p_outline_size)); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); if (!_ensure_glyph(fd, size, p_index)) { - return; // // Invalid or non graphicl glyph, do not display errors, nothing to draw. + return; // Invalid or non-graphical glyph, do not display errors, nothing to draw. } const FontGlyph &gl = fd->cache[size]->glyph_map[p_index]; @@ -2732,9 +2733,9 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size; RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range); } else { - Point2i cpos = p_pos; + Point2 cpos = p_pos.floor(); cpos += gl.rect.position; - Size2i csize = gl.rect.size; + Size2 csize = gl.rect.size; RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); } } @@ -3144,7 +3145,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, InlineAlign p_inline_align, int p_length) { +bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length) { _THREAD_SAFE_METHOD_ ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); @@ -3156,7 +3157,7 @@ bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, con } ShapedTextDataAdvanced::Span span; - span.start = sd->text.length(); + span.start = sd->start + sd->text.length(); span.end = span.start + p_length; span.embedded_key = p_key; @@ -3174,7 +3175,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, InlineAlign p_inline_align) { +bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align) { ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); @@ -3242,56 +3243,56 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) { if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { - case INLINE_ALIGN_TO_TOP: { + switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) { + case INLINE_ALIGNMENT_TO_TOP: { E.value.rect.position.y = -sd->ascent; } break; - case INLINE_ALIGN_TO_CENTER: { + case INLINE_ALIGNMENT_TO_CENTER: { E.value.rect.position.y = (-sd->ascent + sd->descent) / 2; } break; - case INLINE_ALIGN_TO_BASELINE: { + case INLINE_ALIGNMENT_TO_BASELINE: { E.value.rect.position.y = 0; } break; - case INLINE_ALIGN_TO_BOTTOM: { + case INLINE_ALIGNMENT_TO_BOTTOM: { E.value.rect.position.y = sd->descent; } break; } - switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { - case INLINE_ALIGN_BOTTOM_TO: { + switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) { + case INLINE_ALIGNMENT_BOTTOM_TO: { E.value.rect.position.y -= E.value.rect.size.y; } break; - case INLINE_ALIGN_CENTER_TO: { + case INLINE_ALIGNMENT_CENTER_TO: { E.value.rect.position.y -= E.value.rect.size.y / 2; } break; - case INLINE_ALIGN_TOP_TO: { + case INLINE_ALIGNMENT_TOP_TO: { // NOP } break; } full_ascent = MAX(full_ascent, -E.value.rect.position.y); full_descent = MAX(full_descent, E.value.rect.position.y + E.value.rect.size.y); } else { - switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { - case INLINE_ALIGN_TO_TOP: { + switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) { + case INLINE_ALIGNMENT_TO_TOP: { E.value.rect.position.x = -sd->ascent; } break; - case INLINE_ALIGN_TO_CENTER: { + case INLINE_ALIGNMENT_TO_CENTER: { E.value.rect.position.x = (-sd->ascent + sd->descent) / 2; } break; - case INLINE_ALIGN_TO_BASELINE: { + case INLINE_ALIGNMENT_TO_BASELINE: { E.value.rect.position.x = 0; } break; - case INLINE_ALIGN_TO_BOTTOM: { + case INLINE_ALIGNMENT_TO_BOTTOM: { E.value.rect.position.x = sd->descent; } break; } - switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { - case INLINE_ALIGN_BOTTOM_TO: { + switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) { + case INLINE_ALIGNMENT_BOTTOM_TO: { E.value.rect.position.x -= E.value.rect.size.x; } break; - case INLINE_ALIGN_CENTER_TO: { + case INLINE_ALIGNMENT_CENTER_TO: { E.value.rect.position.x -= E.value.rect.size.x / 2; } break; - case INLINE_ALIGN_TOP_TO: { + case INLINE_ALIGNMENT_TOP_TO: { // NOP } break; } @@ -3322,60 +3323,72 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng ERR_FAIL_COND_V(sd->end < p_start + p_length, RID()); ShapedTextDataAdvanced *new_sd = memnew(ShapedTextDataAdvanced); - - new_sd->hb_buffer = hb_buffer_create(); new_sd->parent = p_shaped; new_sd->start = p_start; new_sd->end = p_start + p_length; - new_sd->orientation = sd->orientation; new_sd->direction = sd->direction; new_sd->custom_punct = sd->custom_punct; new_sd->para_direction = sd->para_direction; - new_sd->line_breaks_valid = sd->line_breaks_valid; - new_sd->justification_ops_valid = sd->justification_ops_valid; - new_sd->sort_valid = false; - new_sd->upos = sd->upos; - new_sd->uthk = sd->uthk; + + if (!_shape_substr(new_sd, sd, p_start, p_length)) { + memdelete(new_sd); + return RID(); + } + return shaped_owner.make_rid(new_sd); +} + +bool TextServerAdvanced::_shape_substr(ShapedTextDataAdvanced *p_new_sd, const ShapedTextDataAdvanced *p_sd, int p_start, int p_length) const { + if (p_new_sd->valid) { + return true; + } + + p_new_sd->hb_buffer = hb_buffer_create(); + + p_new_sd->line_breaks_valid = p_sd->line_breaks_valid; + p_new_sd->justification_ops_valid = p_sd->justification_ops_valid; + p_new_sd->sort_valid = false; + p_new_sd->upos = p_sd->upos; + p_new_sd->uthk = p_sd->uthk; if (p_length > 0) { - new_sd->text = sd->text.substr(p_start, p_length); - new_sd->utf16 = new_sd->text.utf16(); - new_sd->script_iter = memnew(ScriptIterator(new_sd->text, 0, new_sd->text.length())); + p_new_sd->text = p_sd->text.substr(p_start - p_sd->start, p_length); + p_new_sd->utf16 = p_new_sd->text.utf16(); + p_new_sd->script_iter = memnew(ScriptIterator(p_new_sd->text, 0, p_new_sd->text.length())); - int sd_size = sd->glyphs.size(); - const Glyph *sd_glyphs = sd->glyphs.ptr(); - for (int ov = 0; ov < sd->bidi_override.size(); ov++) { + int sd_size = p_sd->glyphs.size(); + const Glyph *sd_glyphs = p_sd->glyphs.ptr(); + for (int ov = 0; ov < p_sd->bidi_override.size(); ov++) { UErrorCode err = U_ZERO_ERROR; - if (sd->bidi_override[ov].x >= p_start + p_length || sd->bidi_override[ov].y <= p_start) { + if (p_sd->bidi_override[ov].x >= p_start + p_length || p_sd->bidi_override[ov].y <= p_start) { continue; } - int start = _convert_pos_inv(sd, MAX(0, p_start - sd->bidi_override[ov].x)); - int end = _convert_pos_inv(sd, MIN(p_start + p_length, sd->bidi_override[ov].y) - sd->bidi_override[ov].x); + int start = _convert_pos_inv(p_sd, MAX(0, p_start - p_sd->bidi_override[ov].x)); + int end = _convert_pos_inv(p_sd, MIN(p_start + p_length, p_sd->bidi_override[ov].y) - p_sd->bidi_override[ov].x); - ERR_FAIL_COND_V_MSG((start < 0 || end - start > new_sd->utf16.length()), RID(), "Invalid BiDi override range."); + ERR_FAIL_COND_V_MSG((start < 0 || end - start > p_new_sd->utf16.length()), false, "Invalid BiDi override range."); // Create temporary line bidi & shape. UBiDi *bidi_iter = ubidi_openSized(end - start, 0, &err); - ERR_FAIL_COND_V_MSG(U_FAILURE(err), RID(), u_errorName(err)); - ubidi_setLine(sd->bidi_iter[ov], start, end, bidi_iter, &err); + ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err)); + ubidi_setLine(p_sd->bidi_iter[ov], start, end, bidi_iter, &err); if (U_FAILURE(err)) { ubidi_close(bidi_iter); - ERR_FAIL_V_MSG(RID(), u_errorName(err)); + ERR_FAIL_V_MSG(false, u_errorName(err)); } - new_sd->bidi_iter.push_back(bidi_iter); + p_new_sd->bidi_iter.push_back(bidi_iter); err = U_ZERO_ERROR; int bidi_run_count = ubidi_countRuns(bidi_iter, &err); - ERR_FAIL_COND_V_MSG(U_FAILURE(err), RID(), u_errorName(err)); + ERR_FAIL_COND_V_MSG(U_FAILURE(err), false, u_errorName(err)); for (int i = 0; i < bidi_run_count; i++) { int32_t _bidi_run_start = 0; int32_t _bidi_run_length = 0; ubidi_getVisualRun(bidi_iter, i, &_bidi_run_start, &_bidi_run_length); - int32_t bidi_run_start = _convert_pos(sd, sd->bidi_override[ov].x + start + _bidi_run_start); - int32_t bidi_run_end = _convert_pos(sd, sd->bidi_override[ov].x + start + _bidi_run_start + _bidi_run_length); + int32_t bidi_run_start = _convert_pos(p_sd, p_sd->bidi_override[ov].x + start + _bidi_run_start); + int32_t bidi_run_end = _convert_pos(p_sd, p_sd->bidi_override[ov].x + start + _bidi_run_start + _bidi_run_length); for (int j = 0; j < sd_size; j++) { if ((sd_glyphs[j].start >= bidi_run_start) && (sd_glyphs[j].end <= bidi_run_end)) { @@ -3384,105 +3397,105 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng Variant key; bool find_embedded = false; if (gl.count == 1) { - for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { + for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : p_sd->objects) { if (E.value.pos == gl.start) { find_embedded = true; key = E.key; - new_sd->objects[key] = E.value; + p_new_sd->objects[key] = E.value; break; } } } if (find_embedded) { - 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; + if (p_new_sd->orientation == ORIENTATION_HORIZONTAL) { + p_new_sd->objects[key].rect.position.x = p_new_sd->width; + p_new_sd->width += p_new_sd->objects[key].rect.size.x; } else { - new_sd->objects[key].rect.position.y = new_sd->width; - new_sd->width += new_sd->objects[key].rect.size.y; + p_new_sd->objects[key].rect.position.y = p_new_sd->width; + p_new_sd->width += p_new_sd->objects[key].rect.size.y; } } else { if (gl.font_rid.is_valid()) { - if (new_sd->orientation == ORIENTATION_HORIZONTAL) { - new_sd->ascent = MAX(new_sd->ascent, MAX(font_get_ascent(gl.font_rid, gl.font_size), -gl.y_off)); - new_sd->descent = MAX(new_sd->descent, MAX(font_get_descent(gl.font_rid, gl.font_size), gl.y_off)); + if (p_new_sd->orientation == ORIENTATION_HORIZONTAL) { + p_new_sd->ascent = MAX(p_new_sd->ascent, MAX(font_get_ascent(gl.font_rid, gl.font_size), -gl.y_off)); + p_new_sd->descent = MAX(p_new_sd->descent, MAX(font_get_descent(gl.font_rid, gl.font_size), gl.y_off)); } else { - new_sd->ascent = MAX(new_sd->ascent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5)); - new_sd->descent = MAX(new_sd->descent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5)); + p_new_sd->ascent = MAX(p_new_sd->ascent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5)); + p_new_sd->descent = MAX(p_new_sd->descent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5)); } - } else if (new_sd->preserve_invalid || (new_sd->preserve_control && is_control(gl.index))) { + } else if (p_new_sd->preserve_invalid || (p_new_sd->preserve_control && is_control(gl.index))) { // Glyph not found, replace with hex code box. - if (new_sd->orientation == ORIENTATION_HORIZONTAL) { - new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y); + if (p_new_sd->orientation == ORIENTATION_HORIZONTAL) { + p_new_sd->ascent = MAX(p_new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y); } else { - new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); - new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); + p_new_sd->ascent = MAX(p_new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); + p_new_sd->descent = MAX(p_new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); } } - new_sd->width += gl.advance * gl.repeat; + p_new_sd->width += gl.advance * gl.repeat; } - new_sd->glyphs.push_back(gl); + p_new_sd->glyphs.push_back(gl); } } } } // Align embedded objects to baseline. - float full_ascent = new_sd->ascent; - float full_descent = new_sd->descent; - for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) { - if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) { - if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { - case INLINE_ALIGN_TO_TOP: { - E.value.rect.position.y = -new_sd->ascent; + float full_ascent = p_new_sd->ascent; + float full_descent = p_new_sd->descent; + for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : p_new_sd->objects) { + if ((E.value.pos >= p_new_sd->start) && (E.value.pos < p_new_sd->end)) { + if (p_sd->orientation == ORIENTATION_HORIZONTAL) { + switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) { + case INLINE_ALIGNMENT_TO_TOP: { + E.value.rect.position.y = -p_new_sd->ascent; } break; - case INLINE_ALIGN_TO_CENTER: { - E.value.rect.position.y = (-new_sd->ascent + new_sd->descent) / 2; + case INLINE_ALIGNMENT_TO_CENTER: { + E.value.rect.position.y = (-p_new_sd->ascent + p_new_sd->descent) / 2; } break; - case INLINE_ALIGN_TO_BASELINE: { + case INLINE_ALIGNMENT_TO_BASELINE: { E.value.rect.position.y = 0; } break; - case INLINE_ALIGN_TO_BOTTOM: { - E.value.rect.position.y = new_sd->descent; + case INLINE_ALIGNMENT_TO_BOTTOM: { + E.value.rect.position.y = p_new_sd->descent; } break; } - switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { - case INLINE_ALIGN_BOTTOM_TO: { + switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) { + case INLINE_ALIGNMENT_BOTTOM_TO: { E.value.rect.position.y -= E.value.rect.size.y; } break; - case INLINE_ALIGN_CENTER_TO: { + case INLINE_ALIGNMENT_CENTER_TO: { E.value.rect.position.y -= E.value.rect.size.y / 2; } break; - case INLINE_ALIGN_TOP_TO: { + case INLINE_ALIGNMENT_TOP_TO: { // NOP } break; } full_ascent = MAX(full_ascent, -E.value.rect.position.y); full_descent = MAX(full_descent, E.value.rect.position.y + E.value.rect.size.y); } else { - switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { - case INLINE_ALIGN_TO_TOP: { - E.value.rect.position.x = -new_sd->ascent; + switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) { + case INLINE_ALIGNMENT_TO_TOP: { + E.value.rect.position.x = -p_new_sd->ascent; } break; - case INLINE_ALIGN_TO_CENTER: { - E.value.rect.position.x = (-new_sd->ascent + new_sd->descent) / 2; + case INLINE_ALIGNMENT_TO_CENTER: { + E.value.rect.position.x = (-p_new_sd->ascent + p_new_sd->descent) / 2; } break; - case INLINE_ALIGN_TO_BASELINE: { + case INLINE_ALIGNMENT_TO_BASELINE: { E.value.rect.position.x = 0; } break; - case INLINE_ALIGN_TO_BOTTOM: { - E.value.rect.position.x = new_sd->descent; + case INLINE_ALIGNMENT_TO_BOTTOM: { + E.value.rect.position.x = p_new_sd->descent; } break; } - switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { - case INLINE_ALIGN_BOTTOM_TO: { + switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) { + case INLINE_ALIGNMENT_BOTTOM_TO: { E.value.rect.position.x -= E.value.rect.size.x; } break; - case INLINE_ALIGN_CENTER_TO: { + case INLINE_ALIGNMENT_CENTER_TO: { E.value.rect.position.x -= E.value.rect.size.x / 2; } break; - case INLINE_ALIGN_TOP_TO: { + case INLINE_ALIGNMENT_TOP_TO: { // NOP } break; } @@ -3491,12 +3504,12 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng } } } - new_sd->ascent = full_ascent; - new_sd->descent = full_descent; + p_new_sd->ascent = full_ascent; + p_new_sd->descent = full_descent; } - new_sd->valid = true; + p_new_sd->valid = true; - return shaped_owner.make_rid(new_sd); + return true; } RID TextServerAdvanced::shaped_text_get_parent(RID p_shaped) const { @@ -4225,8 +4238,8 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star for (int i = p_start; i < p_end; i++) { if (p_sd->preserve_invalid || (p_sd->preserve_control && is_control(p_sd->text[i]))) { Glyph gl; - gl.start = i; - gl.end = i + 1; + gl.start = i + p_sd->start; + gl.end = i + 1 + p_sd->start; gl.count = 1; gl.index = p_sd->text[i]; gl.font_size = fs; @@ -4252,6 +4265,9 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star RID f = p_fonts[p_fb_index]; hb_font_t *hb_font = _font_get_hb_handle(f, fs); + float scale = font_get_scale(f, fs); + float sp_sp = font_get_spacing(f, fs, SPACING_SPACE); + float sp_gl = font_get_spacing(f, fs, SPACING_GLYPH); ERR_FAIL_COND(hb_font == nullptr); hb_buffer_clear_contents(p_sd->hb_buffer); @@ -4263,7 +4279,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star } hb_buffer_set_script(p_sd->hb_buffer, p_script); - if (p_sd->spans[p_span].language != String()) { + if (!p_sd->spans[p_span].language.is_empty()) { hb_language_t lang = hb_language_from_string(p_sd->spans[p_span].language.ascii().get_data(), -1); hb_buffer_set_language(p_sd->hb_buffer, lang); } @@ -4335,7 +4351,6 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star gl.index = glyph_info[i].codepoint; if (gl.index != 0) { - float scale = font_get_scale(f, fs); if (p_sd->orientation == ORIENTATION_HORIZONTAL) { gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale)); } else { @@ -4344,10 +4359,10 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star gl.x_off = Math::round(glyph_pos[i].x_offset / (64.0 / scale)); gl.y_off = -Math::round(glyph_pos[i].y_offset / (64.0 / scale)); } - if (font_get_spacing(f, fs, SPACING_SPACE) && is_whitespace(p_sd->text[glyph_info[i].cluster])) { - gl.advance += font_get_spacing(f, fs, SPACING_SPACE); + if (sp_sp && is_whitespace(p_sd->text[glyph_info[i].cluster])) { + gl.advance += sp_sp; } else { - gl.advance += font_get_spacing(f, fs, SPACING_GLYPH); + gl.advance += sp_gl; } if (p_sd->preserve_control) { @@ -4385,10 +4400,13 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star p_sd->ascent = MAX(p_sd->ascent, -w[i + j].y_off); p_sd->descent = MAX(p_sd->descent, w[i + j].y_off); } else { - p_sd->ascent = MAX(p_sd->ascent, Math::round(font_get_glyph_advance(f, fs, w[i + j].index).x * 0.5)); - p_sd->descent = MAX(p_sd->descent, Math::round(font_get_glyph_advance(f, fs, w[i + j].index).x * 0.5)); + float gla = Math::round(font_get_glyph_advance(f, fs, w[i + j].index).x * 0.5); + p_sd->ascent = MAX(p_sd->ascent, gla); + p_sd->descent = MAX(p_sd->descent, gla); } p_sd->width += w[i + j].advance; + w[i + j].start += p_sd->start; + w[i + j].end += p_sd->start; p_sd->glyphs.push_back(w[i + j]); } } else { @@ -4421,10 +4439,14 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { return true; } + invalidate(sd); if (sd->parent != RID()) { - full_copy(sd); + shaped_text_shape(sd->parent); + ShapedTextDataAdvanced *parent_sd = shaped_owner.get_or_null(sd->parent); + ERR_FAIL_COND_V(!parent_sd->valid, false); + ERR_FAIL_COND_V(!_shape_substr(sd, parent_sd, sd->start, sd->end - sd->start), false); + return true; } - invalidate(sd); if (sd->text.length() == 0) { sd->valid = true; @@ -4440,15 +4462,17 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { } if (sd->bidi_override.is_empty()) { - sd->bidi_override.push_back(Vector2i(0, sd->end)); + sd->bidi_override.push_back(Vector2i(sd->start, sd->end)); } for (int ov = 0; ov < sd->bidi_override.size(); ov++) { // Create BiDi iterator. - int start = _convert_pos_inv(sd, sd->bidi_override[ov].x); - int end = _convert_pos_inv(sd, sd->bidi_override[ov].y); + int start = _convert_pos_inv(sd, sd->bidi_override[ov].x - sd->start); + int end = _convert_pos_inv(sd, sd->bidi_override[ov].y - sd->start); - ERR_FAIL_COND_V_MSG((start < 0 || end - start > sd->utf16.length()), false, "Invalid BiDi override range."); + if (start < 0 || end - start > sd->utf16.length()) { + continue; + } UErrorCode err = U_ZERO_ERROR; UBiDi *bidi_iter = ubidi_openSized(end, 0, &err); @@ -4502,8 +4526,8 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { } } - int32_t bidi_run_start = _convert_pos(sd, sd->bidi_override[ov].x + _bidi_run_start); - int32_t bidi_run_end = _convert_pos(sd, sd->bidi_override[ov].x + _bidi_run_start + _bidi_run_length); + int32_t bidi_run_start = _convert_pos(sd, sd->bidi_override[ov].x - sd->start + _bidi_run_start); + int32_t bidi_run_end = _convert_pos(sd, sd->bidi_override[ov].x - sd->start + _bidi_run_start + _bidi_run_length); // Shape runs. @@ -4525,7 +4549,7 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { for (int k = spn_from; k != spn_to; k += spn_delta) { const ShapedTextDataAdvanced::Span &span = sd->spans[k]; - if (span.start >= script_run_end || span.end <= script_run_start) { + if (span.start - sd->start >= script_run_end || span.end - sd->start <= script_run_start) { continue; } if (span.embedded_key != Variant()) { @@ -4566,7 +4590,7 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { } fonts.append_array(fonts_scr_only); fonts.append_array(fonts_no_match); - _shape_run(sd, MAX(sd->spans[k].start, script_run_start), MIN(sd->spans[k].end, script_run_end), sd->script_iter->script_ranges[j].script, bidi_run_direction, fonts, k, 0); + _shape_run(sd, MAX(sd->spans[k].start - sd->start, script_run_start), MIN(sd->spans[k].end - sd->start, script_run_end), sd->script_iter->script_ranges[j].script, bidi_run_direction, fonts, k, 0); } } } @@ -4579,56 +4603,56 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { float full_descent = sd->descent; for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { - case INLINE_ALIGN_TO_TOP: { + switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) { + case INLINE_ALIGNMENT_TO_TOP: { E.value.rect.position.y = -sd->ascent; } break; - case INLINE_ALIGN_TO_CENTER: { + case INLINE_ALIGNMENT_TO_CENTER: { E.value.rect.position.y = (-sd->ascent + sd->descent) / 2; } break; - case INLINE_ALIGN_TO_BASELINE: { + case INLINE_ALIGNMENT_TO_BASELINE: { E.value.rect.position.y = 0; } break; - case INLINE_ALIGN_TO_BOTTOM: { + case INLINE_ALIGNMENT_TO_BOTTOM: { E.value.rect.position.y = sd->descent; } break; } - switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { - case INLINE_ALIGN_BOTTOM_TO: { + switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) { + case INLINE_ALIGNMENT_BOTTOM_TO: { E.value.rect.position.y -= E.value.rect.size.y; } break; - case INLINE_ALIGN_CENTER_TO: { + case INLINE_ALIGNMENT_CENTER_TO: { E.value.rect.position.y -= E.value.rect.size.y / 2; } break; - case INLINE_ALIGN_TOP_TO: { + case INLINE_ALIGNMENT_TOP_TO: { // NOP } break; } full_ascent = MAX(full_ascent, -E.value.rect.position.y); full_descent = MAX(full_descent, E.value.rect.position.y + E.value.rect.size.y); } else { - switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { - case INLINE_ALIGN_TO_TOP: { + switch (E.value.inline_align & INLINE_ALIGNMENT_TEXT_MASK) { + case INLINE_ALIGNMENT_TO_TOP: { E.value.rect.position.x = -sd->ascent; } break; - case INLINE_ALIGN_TO_CENTER: { + case INLINE_ALIGNMENT_TO_CENTER: { E.value.rect.position.x = (-sd->ascent + sd->descent) / 2; } break; - case INLINE_ALIGN_TO_BASELINE: { + case INLINE_ALIGNMENT_TO_BASELINE: { E.value.rect.position.x = 0; } break; - case INLINE_ALIGN_TO_BOTTOM: { + case INLINE_ALIGNMENT_TO_BOTTOM: { E.value.rect.position.x = sd->descent; } break; } - switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { - case INLINE_ALIGN_BOTTOM_TO: { + switch (E.value.inline_align & INLINE_ALIGNMENT_IMAGE_MASK) { + case INLINE_ALIGNMENT_BOTTOM_TO: { E.value.rect.position.x -= E.value.rect.size.x; } break; - case INLINE_ALIGN_CENTER_TO: { + case INLINE_ALIGNMENT_CENTER_TO: { E.value.rect.position.x -= E.value.rect.size.x / 2; } break; - case INLINE_ALIGN_TOP_TO: { + case INLINE_ALIGNMENT_TOP_TO: { // NOP } break; } @@ -4971,12 +4995,12 @@ void TextServerAdvanced::_insert_num_systems_lang() { } String TextServerAdvanced::format_number(const String &p_string, const String &p_language) const { - const StringName lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; + const StringName lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; String res = p_string; for (int i = 0; i < num_systems.size(); i++) { if (num_systems[i].lang.has(lang)) { - if (num_systems[i].digits == String()) { + if (num_systems[i].digits.is_empty()) { return p_string; } res.replace("e", num_systems[i].exp); @@ -4996,12 +5020,12 @@ String TextServerAdvanced::format_number(const String &p_string, const String &p } String TextServerAdvanced::parse_number(const String &p_string, const String &p_language) const { - const StringName lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; + const StringName lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; String res = p_string; for (int i = 0; i < num_systems.size(); i++) { if (num_systems[i].lang.has(lang)) { - if (num_systems[i].digits == String()) { + if (num_systems[i].digits.is_empty()) { return p_string; } res.replace(num_systems[i].exp, "e"); @@ -5024,11 +5048,11 @@ String TextServerAdvanced::parse_number(const String &p_string, const String &p_ } String TextServerAdvanced::percent_sign(const String &p_language) const { - const StringName lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; + const StringName lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; for (int i = 0; i < num_systems.size(); i++) { if (num_systems[i].lang.has(lang)) { - if (num_systems[i].percent_sign == String()) { + if (num_systems[i].percent_sign.is_empty()) { return "%"; } return num_systems[i].percent_sign; diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 5eaff67a6e..fb9446da9f 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -269,6 +269,7 @@ class TextServerAdvanced : public TextServer { int _convert_pos(const ShapedTextDataAdvanced *p_sd, int p_pos) const; int _convert_pos_inv(const ShapedTextDataAdvanced *p_sd, int p_pos) const; + bool _shape_substr(ShapedTextDataAdvanced *p_new_sd, const ShapedTextDataAdvanced *p_sd, int p_start, int p_length) const; void _shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_start, int32_t p_end, hb_script_t p_script, hb_direction_t p_direction, Vector<RID> p_fonts, int p_span, int p_fb_index); Glyph _shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size); @@ -476,8 +477,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, 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 bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1) override; + virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_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; |