Skip to content

Commit

Permalink
[TextServer] Add extra fallback step, to lookup for individual charac…
Browse files Browse the repository at this point in the history
…ters.
  • Loading branch information
bruvzg committed Feb 9, 2024
1 parent 4e990cd commit 062a93f
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 28 deletions.
96 changes: 69 additions & 27 deletions modules/text_server_adv/text_server_adv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5814,7 +5814,7 @@ _FORCE_INLINE_ void TextServerAdvanced::_add_featuers(const Dictionary &p_source
}
}

void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_end, hb_script_t p_script, hb_direction_t p_direction, TypedArray<RID> p_fonts, int64_t p_span, int64_t p_fb_index, int64_t p_prev_start, int64_t p_prev_end) {
void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_end, hb_script_t p_script, hb_direction_t p_direction, TypedArray<RID> p_fonts, int64_t p_span, int64_t p_fb_index, int64_t p_prev_start, int64_t p_prev_end, RID p_prev_font) {
RID f;
int fs = p_sd->spans[p_span].font_size;

Expand Down Expand Up @@ -5844,29 +5844,71 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
}

if (!f.is_valid()) {
// No valid font, use fallback hex code boxes.
for (int i = p_start; i < p_end; i++) {
// Shaping failed, try looking up raw characters or use fallback hex code boxes.
int fb_from = (p_direction != HB_DIRECTION_RTL) ? p_start : p_end - 1;
int fb_to = (p_direction != HB_DIRECTION_RTL) ? p_end : p_start - 1;
int fb_delta = (p_direction != HB_DIRECTION_RTL) ? +1 : -1;

for (int i = fb_from; i != fb_to; i += fb_delta) {
if (p_sd->preserve_invalid || (p_sd->preserve_control && is_control(p_sd->text[i]))) {
Glyph gl;
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;
gl.font_rid = RID();
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(fs, gl.index).x;
p_sd->ascent = MAX(p_sd->ascent, get_hex_code_box_size(fs, gl.index).y);
} else {
gl.advance = get_hex_code_box_size(fs, gl.index).y;
gl.y_off = get_hex_code_box_size(fs, gl.index).y;
gl.x_off = -Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5);
p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5));
p_sd->descent = MAX(p_sd->descent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5));

bool found = false;
for (int j = 0; j <= p_fonts.size(); j++) {
RID f_rid;
if (j == p_fonts.size()) {
f_rid = p_prev_font;
} else {
f_rid = p_fonts[j];
}
if (f_rid.is_valid() && _font_has_char(f_rid, p_sd->text[i])) {
gl.font_rid = f_rid;
gl.index = _font_get_glyph_index(gl.font_rid, fs, p_sd->text[i], 0);
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = _font_get_glyph_advance(gl.font_rid, fs, gl.index).x;
gl.x_off = 0;
gl.y_off = _font_get_baseline_offset(gl.font_rid) * (double)(_font_get_ascent(gl.font_rid, gl.font_size) + _font_get_descent(gl.font_rid, gl.font_size));
p_sd->ascent = MAX(p_sd->ascent, _font_get_ascent(gl.font_rid, gl.font_size) + _font_get_spacing(gl.font_rid, SPACING_TOP));
p_sd->descent = MAX(p_sd->descent, _font_get_descent(gl.font_rid, gl.font_size) + _font_get_spacing(gl.font_rid, SPACING_BOTTOM));
} else {
gl.advance = _font_get_glyph_advance(gl.font_rid, fs, gl.index).y;
gl.x_off = -Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5) + _font_get_baseline_offset(gl.font_rid) * (double)(_font_get_ascent(gl.font_rid, gl.font_size) + _font_get_descent(gl.font_rid, gl.font_size));
gl.y_off = _font_get_ascent(gl.font_rid, gl.font_size);
p_sd->ascent = MAX(p_sd->ascent, Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));
p_sd->descent = MAX(p_sd->descent, Math::round(_font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));
}
double scale = _font_get_scale(gl.font_rid, fs);
bool subpos = (scale != 1.0) || (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_ONE_HALF) || (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (_font_get_subpixel_positioning(gl.font_rid) == SUBPIXEL_POSITIONING_AUTO && fs <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
if (!subpos) {
gl.advance = Math::round(gl.advance);
gl.x_off = Math::round(gl.x_off);
}
found = true;
break;
}
}
if (!found) {
gl.font_rid = RID();
gl.index = p_sd->text[i];
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
gl.advance = get_hex_code_box_size(fs, gl.index).x;
p_sd->ascent = MAX(p_sd->ascent, get_hex_code_box_size(fs, gl.index).y);
} else {
gl.advance = get_hex_code_box_size(fs, gl.index).y;
gl.y_off = get_hex_code_box_size(fs, gl.index).y;
gl.x_off = -Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5);
p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5));
p_sd->descent = MAX(p_sd->descent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5));
}
}

p_sd->width += gl.advance;

p_sd->glyphs.push_back(gl);
Expand Down Expand Up @@ -6041,7 +6083,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
for (unsigned int i = 0; i < glyph_count; i++) {
if ((w[i].flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) {
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_start, p_end);
_shape_run(p_sd, failed_subrun_start, failed_subrun_end, p_script, p_direction, p_fonts, p_span, p_fb_index + 1, p_start, p_end, (p_fb_index >= p_fonts.size()) ? f : RID());
failed_subrun_start = p_end + 1;
failed_subrun_end = p_start;
}
Expand Down Expand Up @@ -6071,7 +6113,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
}
memfree(w);
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_start, p_end);
_shape_run(p_sd, failed_subrun_start, failed_subrun_end, p_script, p_direction, p_fonts, p_span, p_fb_index + 1, p_start, p_end, (p_fb_index >= p_fonts.size()) ? f : RID());
}
p_sd->ascent = MAX(p_sd->ascent, _font_get_ascent(f, fs) + _font_get_spacing(f, SPACING_TOP));
p_sd->descent = MAX(p_sd->descent, _font_get_descent(f, fs) + _font_get_spacing(f, SPACING_BOTTOM));
Expand Down Expand Up @@ -6195,21 +6237,21 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
for (int i = 0; i < bidi_run_count; i++) {
int32_t _bidi_run_start = 0;
int32_t _bidi_run_length = end - start;
bool is_rtl = false;
bool is_ltr = false;
hb_direction_t bidi_run_direction = HB_DIRECTION_INVALID;
if (bidi_iter) {
is_rtl = (ubidi_getVisualRun(bidi_iter, i, &_bidi_run_start, &_bidi_run_length) == UBIDI_LTR);
is_ltr = (ubidi_getVisualRun(bidi_iter, i, &_bidi_run_start, &_bidi_run_length) == UBIDI_LTR);
}
switch (sd->orientation) {
case ORIENTATION_HORIZONTAL: {
if (is_rtl) {
if (is_ltr) {
bidi_run_direction = HB_DIRECTION_LTR;
} else {
bidi_run_direction = HB_DIRECTION_RTL;
}
} break;
case ORIENTATION_VERTICAL: {
if (is_rtl) {
if (is_ltr) {
bidi_run_direction = HB_DIRECTION_TTB;
} else {
bidi_run_direction = HB_DIRECTION_BTT;
Expand All @@ -6222,9 +6264,9 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {

// Shape runs.

int scr_from = (is_rtl) ? 0 : sd->script_iter->script_ranges.size() - 1;
int scr_to = (is_rtl) ? sd->script_iter->script_ranges.size() : -1;
int scr_delta = (is_rtl) ? +1 : -1;
int scr_from = (is_ltr) ? 0 : sd->script_iter->script_ranges.size() - 1;
int scr_to = (is_ltr) ? sd->script_iter->script_ranges.size() : -1;
int scr_delta = (is_ltr) ? +1 : -1;

for (int j = scr_from; j != scr_to; j += scr_delta) {
if ((sd->script_iter->script_ranges[j].start < bidi_run_end) && (sd->script_iter->script_ranges[j].end > bidi_run_start)) {
Expand All @@ -6234,9 +6276,9 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
hb_tag_to_string(hb_script_to_iso15924_tag(sd->script_iter->script_ranges[j].script), scr_buffer);
String script_code = String(scr_buffer);

int spn_from = (is_rtl) ? 0 : sd->spans.size() - 1;
int spn_to = (is_rtl) ? sd->spans.size() : -1;
int spn_delta = (is_rtl) ? +1 : -1;
int spn_from = (is_ltr) ? 0 : sd->spans.size() - 1;
int spn_to = (is_ltr) ? sd->spans.size() : -1;
int spn_delta = (is_ltr) ? +1 : -1;

for (int k = spn_from; k != spn_to; k += spn_delta) {
const ShapedTextDataAdvanced::Span &span = sd->spans[k];
Expand Down Expand Up @@ -6284,7 +6326,7 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) {
}
fonts.append_array(fonts_scr_only);
fonts.append_array(fonts_no_match);
_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, 0, 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, 0, 0, RID());
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion modules/text_server_adv/text_server_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ class TextServerAdvanced : public TextServerExtension {
int64_t _convert_pos(const ShapedTextDataAdvanced *p_sd, int64_t p_pos) const;
int64_t _convert_pos_inv(const ShapedTextDataAdvanced *p_sd, int64_t p_pos) const;
bool _shape_substr(ShapedTextDataAdvanced *p_new_sd, const ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_length) const;
void _shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_end, hb_script_t p_script, hb_direction_t p_direction, TypedArray<RID> p_fonts, int64_t p_span, int64_t p_fb_index, int64_t p_prev_start, int64_t p_prev_end);
void _shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_start, int64_t p_end, hb_script_t p_script, hb_direction_t p_direction, TypedArray<RID> p_fonts, int64_t p_span, int64_t p_fb_index, int64_t p_prev_start, int64_t p_prev_end, RID p_prev_font);
Glyph _shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, const RID &p_font, int64_t p_font_size);
_FORCE_INLINE_ RID _find_sys_font_for_text(const RID &p_fdef, const String &p_script_code, const String &p_language, const String &p_text);

Expand Down

0 comments on commit 062a93f

Please sign in to comment.