diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2020-12-07 11:08:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-07 11:08:34 +0100 |
commit | 93e9c9c470aeb1d8d2af0d4f63525a405be08a2e (patch) | |
tree | 9fca1de4fe7727cf51ccde57e7c3f4aedfde6d0a /modules | |
parent | 73eb8d5a2094fc7512b17712b402bdb73c5f5b63 (diff) | |
parent | 0ef483e9a940e8a2e236f923f1625a4aba77978a (diff) | |
download | redot-engine-93e9c9c470aeb1d8d2af0d4f63525a405be08a2e.tar.gz |
Merge pull request #43981 from bruvzg/ctl_font_spacing
[Complex Text Layouts] Adds missing Font::SPACING_* to the controls, align glyphs to pixel grid.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/text_server_adv/bitmap_font_adv.cpp | 14 | ||||
-rw-r--r-- | modules/text_server_adv/bitmap_font_adv.h | 3 | ||||
-rw-r--r-- | modules/text_server_adv/script_iterator.cpp | 3 | ||||
-rw-r--r-- | modules/text_server_adv/text_server_adv.cpp | 183 | ||||
-rw-r--r-- | modules/text_server_fb/text_server_fb.cpp | 106 |
5 files changed, 180 insertions, 129 deletions
diff --git a/modules/text_server_adv/bitmap_font_adv.cpp b/modules/text_server_adv/bitmap_font_adv.cpp index 10c3732fd7..f743000bc1 100644 --- a/modules/text_server_adv/bitmap_font_adv.cpp +++ b/modules/text_server_adv/bitmap_font_adv.cpp @@ -175,8 +175,9 @@ static hb_bool_t hb_bmp_get_font_h_extents(hb_font_t *font, void *font_data, hb_ return true; } -static hb_font_funcs_t *_hb_bmp_get_font_funcs() { - hb_font_funcs_t *funcs = hb_font_funcs_create(); +static hb_font_funcs_t *funcs = nullptr; +void hb_bmp_create_font_funcs() { + funcs = hb_font_funcs_create(); hb_font_funcs_set_font_h_extents_func(funcs, hb_bmp_get_font_h_extents, nullptr, nullptr); //hb_font_funcs_set_font_v_extents_func (funcs, hb_bmp_get_font_v_extents, nullptr, nullptr); @@ -194,12 +195,17 @@ static hb_font_funcs_t *_hb_bmp_get_font_funcs() { //hb_font_funcs_set_glyph_from_name_func (funcs, hb_bmp_get_glyph_from_name, nullptr, nullptr); hb_font_funcs_make_immutable(funcs); +} - return funcs; +void hb_bmp_free_font_funcs() { + if (funcs != nullptr) { + hb_font_funcs_destroy(funcs); + funcs = nullptr; + } } static void _hb_bmp_font_set_funcs(hb_font_t *p_font, BitmapFontDataAdvanced *p_face, int p_size, bool p_unref) { - hb_font_set_funcs(p_font, _hb_bmp_get_font_funcs(), _hb_bmp_font_create(p_face, p_size, p_unref), _hb_bmp_font_destroy); + hb_font_set_funcs(p_font, funcs, _hb_bmp_font_create(p_face, p_size, p_unref), _hb_bmp_font_destroy); } hb_font_t *hb_bmp_font_create(BitmapFontDataAdvanced *p_face, int p_size, hb_destroy_func_t p_destroy) { diff --git a/modules/text_server_adv/bitmap_font_adv.h b/modules/text_server_adv/bitmap_font_adv.h index b2fe7f43af..cb1a726f76 100644 --- a/modules/text_server_adv/bitmap_font_adv.h +++ b/modules/text_server_adv/bitmap_font_adv.h @@ -33,6 +33,9 @@ #include "font_adv.h" +void hb_bmp_create_font_funcs(); +void hb_bmp_free_font_funcs(); + struct BitmapFontDataAdvanced : public FontDataAdvanced { _THREAD_SAFE_CLASS_ diff --git a/modules/text_server_adv/script_iterator.cpp b/modules/text_server_adv/script_iterator.cpp index 8a2b2cced0..60a617c3a7 100644 --- a/modules/text_server_adv/script_iterator.cpp +++ b/modules/text_server_adv/script_iterator.cpp @@ -56,11 +56,12 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length int paren_sp = -1; int start_sp = paren_sp; UErrorCode err = U_ZERO_ERROR; + const char32_t *str = p_string.ptr(); do { script_code = USCRIPT_COMMON; for (script_start = script_end; script_end < p_length; script_end++) { - UChar32 ch = p_string[script_end]; + UChar32 ch = str[script_end]; UScriptCode sc = uscript_getScript(ch, &err); if (U_FAILURE(err)) { ERR_FAIL_MSG(u_errorName(err)); diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index e391777eea..dacf649987 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -1108,7 +1108,9 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, sd->width = 0; sd->upos = 0; sd->uthk = 0; - for (int i = 0; i < sd->glyphs.size(); i++) { + int sd_size = sd->glyphs.size(); + + for (int i = 0; i < sd_size; i++) { Glyph gl = sd->glyphs[i]; Variant key; if (gl.count == 1) { @@ -1128,8 +1130,8 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y); } break; case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y / 2); - sd->descent = MAX(sd->descent, sd->objects[key].rect.size.y / 2); + 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); @@ -1144,8 +1146,8 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x); } break; case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x / 2); - sd->descent = MAX(sd->descent, sd->objects[key].rect.size.x / 2); + 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); @@ -1160,19 +1162,19 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, sd->ascent = MAX(sd->ascent, MAX(fd->get_ascent(gl.font_size), -gl.y_off)); sd->descent = MAX(sd->descent, MAX(fd->get_descent(gl.font_size), gl.y_off)); } else { - sd->ascent = MAX(sd->ascent, fd->get_advance(gl.index, gl.font_size).x * 0.5); - sd->descent = MAX(sd->descent, fd->get_advance(gl.index, gl.font_size).x * 0.5); + sd->ascent = MAX(sd->ascent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); + sd->descent = MAX(sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); } sd->upos = MAX(sd->upos, font_get_underline_position(gl.font_rid, gl.font_size)); sd->uthk = MAX(sd->uthk, font_get_underline_thickness(gl.font_rid, gl.font_size)); } else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) { // Glyph not found, replace with hex code box. if (sd->orientation == ORIENTATION_HORIZONTAL) { - sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f); - sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f); + sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); + sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f)); } else { - sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); - sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); + sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); + sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); } } sd->width += gl.advance * gl.repeat; @@ -1248,6 +1250,11 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng new_sd->utf16 = new_sd->text.utf16(); new_sd->script_iter = memnew(ScriptIterator(new_sd->text, 0, new_sd->text.length())); + int sd_size = sd->glyphs.size(); + const Glyph *sd_glyphs = sd->glyphs.ptr(); + const FontDataAdvanced *fd = nullptr; + RID prev_rid = RID(); + for (int ov = 0; ov < sd->bidi_override.size(); ov++) { UErrorCode err = U_ZERO_ERROR; @@ -1280,21 +1287,23 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng 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); - for (int j = 0; j < sd->glyphs.size(); j++) { - if ((sd->glyphs[j].start >= bidi_run_start) && (sd->glyphs[j].end <= bidi_run_end)) { + for (int j = 0; j < sd_size; j++) { + if ((sd_glyphs[j].start >= bidi_run_start) && (sd_glyphs[j].end <= bidi_run_end)) { // Copy glyphs. - Glyph gl = sd->glyphs[j]; + Glyph gl = sd_glyphs[j]; Variant key; + bool find_embedded = false; if (gl.count == 1) { for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { if (E->get().pos == gl.start) { + find_embedded = true; key = E->key(); new_sd->objects[key] = E->get(); break; } } } - if (key != Variant()) { + 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; @@ -1303,8 +1312,8 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng 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, new_sd->objects[key].rect.size.y / 2); - new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.y / 2); + 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); @@ -1318,8 +1327,8 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng 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, new_sd->objects[key].rect.size.x / 2); - new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.x / 2); + 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); @@ -1327,23 +1336,26 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng } } } else { - const FontDataAdvanced *fd = font_owner.getornull(gl.font_rid); + if (prev_rid != gl.font_rid) { + fd = font_owner.getornull(gl.font_rid); + prev_rid = gl.font_rid; + } if (fd != nullptr) { if (new_sd->orientation == ORIENTATION_HORIZONTAL) { new_sd->ascent = MAX(new_sd->ascent, MAX(fd->get_ascent(gl.font_size), -gl.y_off)); new_sd->descent = MAX(new_sd->descent, MAX(fd->get_descent(gl.font_size), gl.y_off)); } else { - new_sd->ascent = MAX(new_sd->ascent, fd->get_advance(gl.index, gl.font_size).x * 0.5); - new_sd->descent = MAX(new_sd->descent, fd->get_advance(gl.index, gl.font_size).x * 0.5); + new_sd->ascent = MAX(new_sd->ascent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); + new_sd->descent = MAX(new_sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); } } else if (new_sd->preserve_invalid || (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 * 0.75f); - new_sd->descent = MAX(new_sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f); + new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); + new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f)); } else { - new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); - new_sd->descent = MAX(new_sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); + 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)); } } new_sd->width += gl.advance * gl.repeat; @@ -1491,9 +1503,9 @@ float TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, float p_width, if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { float old_adv = gl.advance; if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) { - gl.advance = MAX(gl.advance + delta_width_per_space, 0.f); + gl.advance = Math::round(MAX(gl.advance + delta_width_per_space, 0.f)); } else { - gl.advance = MAX(gl.advance + delta_width_per_space, 0.05 * gl.font_size); + gl.advance = Math::round(MAX(gl.advance + delta_width_per_space, 0.05 * gl.font_size)); } sd->width += (gl.advance - old_adv); } @@ -1529,8 +1541,10 @@ float TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<float delta = -1; } + Glyph *gl = sd->glyphs.ptrw(); + for (int i = start; i != end; i += delta) { - if ((sd->glyphs[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) { + if ((gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) { float tab_off = 0.f; while (tab_off <= off) { tab_off += p_tab_stops[tab_index]; @@ -1539,13 +1553,13 @@ float TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<float tab_index = 0; } } - float old_adv = sd->glyphs.write[i].advance; - sd->glyphs.write[i].advance = (tab_off - off); - sd->width += sd->glyphs.write[i].advance - old_adv; + float old_adv = gl[i].advance; + gl[i].advance = tab_off - off; + sd->width += gl[i].advance - old_adv; off = 0; continue; } - off += sd->glyphs[i].advance * sd->glyphs[i].repeat; + off += gl[i].advance * gl[i].repeat; } return 0.f; @@ -1565,8 +1579,7 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { const UChar *data = sd->utf16.ptr(); - Map<int, bool> breaks; - + HashMap<int, bool> breaks; UErrorCode err = U_ZERO_ERROR; for (int i = 0; i < sd->spans.size(); i++) { UBreakIterator *bi = ubrk_open(UBRK_LINE, sd->spans[i].language.ascii().get_data(), data + _convert_pos_inv(sd, sd->spans[i].start), _convert_pos_inv(sd, sd->spans[i].end - sd->spans[i].start), &err); @@ -1598,40 +1611,48 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { sd->sort_valid = false; sd->glyphs_logical.clear(); + int sd_size = sd->glyphs.size(); + const char32_t *ch = sd->text.ptr(); + Glyph *sd_glyphs = sd->glyphs.ptrw(); - for (int i = 0; i < sd->glyphs.size(); i++) { - if (sd->glyphs[i].count > 0) { - char32_t c = sd->text[sd->glyphs[i].start - sd->start]; + for (int i = 0; i < sd_size; i++) { + if (sd_glyphs[i].count > 0) { + char32_t c = ch[sd_glyphs[i].start - sd->start]; if (c == 0xfffc) { continue; } if (c == 0x0009 || c == 0x000b) { - sd->glyphs.write[i].flags |= GRAPHEME_IS_TAB; + sd_glyphs[i].flags |= GRAPHEME_IS_TAB; } if (breaks.has(sd->glyphs[i].start)) { if (breaks[sd->glyphs[i].start]) { - sd->glyphs.write[i].flags |= GRAPHEME_IS_BREAK_HARD; + sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD; } else { if (is_whitespace(c)) { - sd->glyphs.write[i].flags |= GRAPHEME_IS_BREAK_SOFT; - sd->glyphs.write[i].flags |= GRAPHEME_IS_SPACE; + sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_SOFT; + sd_glyphs[i].flags |= GRAPHEME_IS_SPACE; } else { TextServer::Glyph gl; - gl.start = sd->glyphs[i].start; - gl.end = sd->glyphs[i].end; + gl.start = sd_glyphs[i].start; + gl.end = sd_glyphs[i].end; gl.count = 1; gl.repeat = 1; - gl.font_rid = sd->glyphs[i].font_rid; - gl.font_size = sd->glyphs[i].font_size; + gl.font_rid = sd_glyphs[i].font_rid; + gl.font_size = sd_glyphs[i].font_size; gl.flags = GRAPHEME_IS_BREAK_SOFT | GRAPHEME_IS_VIRTUAL; - sd->glyphs.insert(i + sd->glyphs[i].count, gl); // insert after - i += sd->glyphs[i].count; + sd->glyphs.insert(i + sd_glyphs[i].count, gl); // insert after + + // Update write pointer and size. + sd_size = sd->glyphs.size(); + sd_glyphs = sd->glyphs.ptrw(); + + i += sd_glyphs[i].count; continue; } } } - i += (sd->glyphs[i].count - 1); + i += (sd_glyphs[i].count - 1); } } @@ -1767,9 +1788,10 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) { sd->sort_valid = false; sd->glyphs_logical.clear(); + int sd_size = sd->glyphs.size(); if (jstops.size() > 0) { - for (int i = 0; i < sd->glyphs.size(); i++) { + for (int i = 0; i < sd_size; i++) { if (sd->glyphs[i].count > 0) { if (jstops.has(sd->glyphs[i].start)) { char32_t c = sd->text[sd->glyphs[i].start - sd->start]; @@ -1850,15 +1872,15 @@ TextServer::Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced if (glyph_count > 0) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) { - gl.advance = glyph_pos[0].x_advance / (64.0 / fd->get_font_scale(p_font_size)); + gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / fd->get_font_scale(p_font_size))); } else { - gl.advance = -glyph_pos[0].y_advance / (64.0 / fd->get_font_scale(p_font_size)); + gl.advance = -Math::round(glyph_pos[0].y_advance / (64.0 / fd->get_font_scale(p_font_size))); } gl.count = 1; gl.index = glyph_info[0].codepoint; - gl.x_off = glyph_pos[0].x_offset / (64.0 / fd->get_font_scale(p_font_size)); - gl.y_off = -glyph_pos[0].y_offset / (64.0 / fd->get_font_scale(p_font_size)); + gl.x_off = Math::round(glyph_pos[0].x_offset / (64.0 / fd->get_font_scale(p_font_size))); + gl.y_off = -Math::round(glyph_pos[0].y_offset / (64.0 / fd->get_font_scale(p_font_size))); if ((glyph_info[0].codepoint != 0) || !u_isgraph(p_char)) { gl.flags |= GRAPHEME_IS_VALID; @@ -1873,8 +1895,9 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star fd = font_owner.getornull(p_fonts[p_fb_index]); } + int fs = p_sd->spans[p_span].font_size; if (fd == nullptr) { - // Add fallback glyohs + // Add fallback glyphs for (int i = p_start; i < p_end; i++) { if (p_sd->preserve_invalid || (p_sd->preserve_control && is_control(p_sd->text[i]))) { TextServer::Glyph gl; @@ -1882,20 +1905,20 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star gl.end = i + 1; gl.count = 1; gl.index = p_sd->text[i]; - gl.font_size = p_sd->spans[p_span].font_size; + gl.font_size = fs; gl.font_rid = RID(); gl.flags = 0; if (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) { gl.flags |= TextServer::GRAPHEME_IS_RTL; } if (p_sd->orientation == ORIENTATION_HORIZONTAL) { - gl.advance = get_hex_code_box_size(gl.font_size, gl.index).x; - p_sd->ascent = MAX(p_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f); - p_sd->descent = MAX(p_sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f); + gl.advance = get_hex_code_box_size(fs, gl.index).x; + p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).y * 0.75f)); + p_sd->descent = MAX(p_sd->descent, Math::round(get_hex_code_box_size(fs, gl.index).y * 0.25f)); } else { - gl.advance = get_hex_code_box_size(gl.font_size, gl.index).y; - p_sd->ascent = MAX(p_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); - p_sd->descent = MAX(p_sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); + gl.advance = get_hex_code_box_size(fs, gl.index).y; + p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5f)); + p_sd->descent = MAX(p_sd->descent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5f)); } p_sd->width += gl.advance; @@ -1905,7 +1928,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star return; } - hb_font_t *hb_font = fd->get_hb_handle(p_sd->spans[p_span].font_size); + hb_font_t *hb_font = fd->get_hb_handle(fs); ERR_FAIL_COND(hb_font == nullptr); hb_buffer_clear_contents(p_sd->hb_buffer); @@ -1981,17 +2004,17 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star gl.count = 0; gl.font_rid = p_fonts[p_fb_index]; - gl.font_size = p_sd->spans[p_span].font_size; + gl.font_size = fs; gl.index = glyph_info[i].codepoint; if (gl.index != 0) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) { - gl.advance = glyph_pos[i].x_advance / (64.0 / fd->get_font_scale(gl.font_size)); + gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / fd->get_font_scale(fs))); } else { - gl.advance = -glyph_pos[i].y_advance / (64.0 / fd->get_font_scale(gl.font_size)); + gl.advance = -Math::round(glyph_pos[i].y_advance / (64.0 / fd->get_font_scale(fs))); } - gl.x_off = glyph_pos[i].x_offset / (64.0 / fd->get_font_scale(gl.font_size)); - gl.y_off = -glyph_pos[i].y_offset / (64.0 / fd->get_font_scale(gl.font_size)); + gl.x_off = Math::round(glyph_pos[i].x_offset / (64.0 / fd->get_font_scale(fs))); + gl.y_off = -Math::round(glyph_pos[i].y_offset / (64.0 / fd->get_font_scale(fs))); } if (p_sd->preserve_control) { @@ -2026,14 +2049,12 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star } for (int j = 0; j < w[i].count; j++) { if (p_sd->orientation == ORIENTATION_HORIZONTAL) { - p_sd->ascent = MAX(p_sd->ascent, MAX(fd->get_ascent(w[i + j].font_size), w[i + j].y_off)); - p_sd->descent = MAX(p_sd->descent, MAX(fd->get_descent(w[i + j].font_size), w[i + j].y_off)); + 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, fd->get_advance(w[i + j].index, w[i + j].font_size).x * 0.5); - p_sd->descent = MAX(p_sd->descent, fd->get_advance(w[i + j].index, w[i + j].font_size).x * 0.5); + p_sd->ascent = MAX(p_sd->ascent, Math::round(fd->get_advance(w[i + j].index, fs).x * 0.5)); + p_sd->descent = MAX(p_sd->descent, Math::round(fd->get_advance(w[i + j].index, fs).x * 0.5)); } - p_sd->upos = MAX(p_sd->upos, font_get_underline_position(w[i + j].font_rid, w[i + j].font_size)); - p_sd->uthk = MAX(p_sd->uthk, font_get_underline_thickness(w[i + j].font_rid, w[i + j].font_size)); p_sd->width += w[i + j].advance; p_sd->glyphs.push_back(w[i + j]); } @@ -2051,6 +2072,10 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star if (failed_subrun_start != p_end + 1) { _shape_run(p_sd, failed_subrun_start, failed_subrun_end, p_script, p_direction, p_fonts, p_span, p_fb_index + 1); } + p_sd->ascent = MAX(p_sd->ascent, fd->get_ascent(fs)); + p_sd->descent = MAX(p_sd->descent, fd->get_descent(fs)); + p_sd->upos = MAX(p_sd->upos, fd->get_underline_position(fs)); + p_sd->uthk = MAX(p_sd->uthk, fd->get_underline_thickness(fs)); } } @@ -2180,8 +2205,8 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y); } break; case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y / 2); - sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.y / 2); + 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); @@ -2195,8 +2220,8 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x); } break; case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x / 2); - sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.x / 2); + 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); @@ -2507,9 +2532,11 @@ void TextServerAdvanced::register_server() { } TextServerAdvanced::TextServerAdvanced() { + hb_bmp_create_font_funcs(); } TextServerAdvanced::~TextServerAdvanced() { + hb_bmp_free_font_funcs(); u_cleanup(); #ifndef ICU_STATIC_DATA if (icu_data != nullptr) { diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index e74a1d9ef9..383250996d 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -625,7 +625,11 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key, sd->width = 0; sd->upos = 0; sd->uthk = 0; - for (int i = 0; i < sd->glyphs.size(); i++) { + int sd_size = sd->glyphs.size(); + const FontDataFallback *fd = nullptr; + RID prev_rid = RID(); + + for (int i = 0; i < sd_size; i++) { Glyph gl = sd->glyphs[i]; Variant key; if (gl.count == 1) { @@ -645,8 +649,8 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key, sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y); } break; case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y / 2); - sd->descent = MAX(sd->descent, sd->objects[key].rect.size.y / 2); + 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); @@ -661,8 +665,8 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key, sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x); } break; case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x / 2); - sd->descent = MAX(sd->descent, sd->objects[key].rect.size.x / 2); + 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); @@ -671,25 +675,28 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key, sd->glyphs.write[i].advance = sd->objects[key].rect.size.y; } } else { - const FontDataFallback *fd = font_owner.getornull(gl.font_rid); + if (prev_rid != gl.font_rid) { + fd = font_owner.getornull(gl.font_rid); + prev_rid = gl.font_rid; + } if (fd != nullptr) { if (sd->orientation == ORIENTATION_HORIZONTAL) { sd->ascent = MAX(sd->ascent, fd->get_ascent(gl.font_size)); sd->descent = MAX(sd->descent, fd->get_descent(gl.font_size)); } else { - sd->ascent = MAX(sd->ascent, fd->get_advance(gl.index, gl.font_size).x * 0.5); - sd->descent = MAX(sd->descent, fd->get_advance(gl.index, gl.font_size).x * 0.5); + sd->ascent = MAX(sd->ascent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); + sd->descent = MAX(sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); } sd->upos = MAX(sd->upos, font_get_underline_position(gl.font_rid, gl.font_size)); sd->uthk = MAX(sd->uthk, font_get_underline_thickness(gl.font_rid, gl.font_size)); } else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) { // Glyph not found, replace with hex code box. if (sd->orientation == ORIENTATION_HORIZONTAL) { - sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f); - sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f); + sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); + sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f)); } else { - sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); - sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); + sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); + sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); } } sd->width += gl.advance * gl.repeat; @@ -760,21 +767,25 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng if (p_length > 0) { new_sd->text = sd->text.substr(p_start, p_length); + int sd_size = sd->glyphs.size(); + const Glyph *sd_glyphs = sd->glyphs.ptr(); - for (int i = 0; i < sd->glyphs.size(); i++) { - if ((sd->glyphs[i].start >= new_sd->start) && (sd->glyphs[i].end <= new_sd->end)) { - Glyph gl = sd->glyphs[i]; + for (int i = 0; i < sd_size; i++) { + if ((sd_glyphs[i].start >= new_sd->start) && (sd_glyphs[i].end <= new_sd->end)) { + Glyph gl = sd_glyphs[i]; Variant key; + bool find_embedded = false; if (gl.count == 1) { for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { if (E->get().pos == gl.start) { + find_embedded = true; key = E->key(); new_sd->objects[key] = E->get(); break; } } } - if (key != Variant()) { + 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; @@ -783,8 +794,8 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng 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, new_sd->objects[key].rect.size.y / 2); - new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.y / 2); + 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); @@ -798,8 +809,8 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng 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, new_sd->objects[key].rect.size.x / 2); - new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.x / 2); + 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); @@ -813,17 +824,17 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng new_sd->ascent = MAX(new_sd->ascent, fd->get_ascent(gl.font_size)); new_sd->descent = MAX(new_sd->descent, fd->get_descent(gl.font_size)); } else { - new_sd->ascent = MAX(new_sd->ascent, fd->get_advance(gl.index, gl.font_size).x * 0.5); - new_sd->descent = MAX(new_sd->descent, fd->get_advance(gl.index, gl.font_size).x * 0.5); + new_sd->ascent = MAX(new_sd->ascent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); + new_sd->descent = MAX(new_sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); } } else if (new_sd->preserve_invalid || (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 * 0.75f); - new_sd->descent = MAX(new_sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f); + new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); + new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f)); } else { - new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); - new_sd->descent = MAX(new_sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); + 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)); } } new_sd->width += gl.advance * gl.repeat; @@ -943,7 +954,7 @@ float TextServerFallback::shaped_text_fit_to_width(RID p_shaped, float p_width, if (gl.count > 0) { if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { float old_adv = gl.advance; - gl.advance = MAX(gl.advance + delta_width_per_space, 0.05 * gl.font_size); + gl.advance = Math::round(MAX(gl.advance + delta_width_per_space, 0.05 * gl.font_size)); sd->width += (gl.advance - old_adv); } } @@ -978,8 +989,10 @@ float TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<float delta = -1; } + Glyph *gl = sd->glyphs.ptrw(); + for (int i = start; i != end; i += delta) { - if ((sd->glyphs[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) { + if ((gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) { float tab_off = 0.f; while (tab_off <= off) { tab_off += p_tab_stops[tab_index]; @@ -988,13 +1001,13 @@ float TextServerFallback::shaped_text_tab_align(RID p_shaped, const Vector<float tab_index = 0; } } - float old_adv = sd->glyphs.write[i].advance; - sd->glyphs.write[i].advance = (tab_off - off); - sd->width += sd->glyphs.write[i].advance - old_adv; + float old_adv = gl[i].advance; + gl[i].advance = tab_off - off; + sd->width += gl[i].advance - old_adv; off = 0; continue; } - off += sd->glyphs[i].advance * sd->glyphs[i].repeat; + off += gl[i].advance * gl[i].repeat; } return 0.f; @@ -1012,7 +1025,8 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) { return true; // Noting to do. } - for (int i = 0; i < sd->glyphs.size(); i++) { + int sd_size = sd->glyphs.size(); + for (int i = 0; i < sd_size; i++) { if (sd->glyphs[i].count > 0) { char32_t c = sd->text[sd->glyphs[i].start]; if (is_whitespace(c) && !is_linebreak(c)) { @@ -1086,8 +1100,8 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) { sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y); } break; case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y / 2); - sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.y / 2); + 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); @@ -1101,8 +1115,8 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) { sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x); } break; case VALIGN_CENTER: { - sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x / 2); - sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.x / 2); + 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); @@ -1157,14 +1171,14 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) { sd->descent = MAX(sd->descent, fd->get_descent(gl.font_size)); } else { gl.advance = fd->get_advance(gl.index, gl.font_size).y; - gl.x_off = -fd->get_advance(gl.index, gl.font_size).x * 0.5; + gl.x_off = -Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5); gl.y_off = fd->get_ascent(gl.font_size); - sd->ascent = MAX(sd->ascent, fd->get_advance(gl.index, gl.font_size).x * 0.5); - sd->descent = MAX(sd->descent, fd->get_advance(gl.index, gl.font_size).x * 0.5); + sd->ascent = MAX(sd->ascent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); + sd->descent = MAX(sd->descent, Math::round(fd->get_advance(gl.index, gl.font_size).x * 0.5)); } } - sd->upos = MAX(sd->upos, font_get_underline_position(gl.font_rid, gl.font_size)); - sd->uthk = MAX(sd->uthk, font_get_underline_thickness(gl.font_rid, gl.font_size)); + sd->upos = MAX(sd->upos, fd->get_underline_position(gl.font_size)); + sd->uthk = MAX(sd->uthk, fd->get_underline_thickness(gl.font_size)); // Add kerning to previous glyph. if (sd->glyphs.size() > 0) { @@ -1181,12 +1195,12 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) { // Glyph not found, replace with hex code box. if (sd->orientation == ORIENTATION_HORIZONTAL) { gl.advance = get_hex_code_box_size(gl.font_size, gl.index).x; - sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f); - sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f); + sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); + sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f)); } else { gl.advance = get_hex_code_box_size(gl.font_size, gl.index).y; - sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); - sd->descent = MAX(sd->descent, get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f); + sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); + sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); } } sd->width += gl.advance; |