Skip to content

Commit

Permalink
Optimize text rendering by caching UBreakIterator instances.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivorforce committed Jan 29, 2025
1 parent e549802 commit 6c82cf0
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
18 changes: 15 additions & 3 deletions modules/text_server_adv/text_server_adv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5632,8 +5632,12 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) {
i++;
}
int r_end = sd->spans[i].end;
UBreakIterator *bi = ubrk_open(UBRK_LINE, (language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale().ascii().get_data() : language.ascii().get_data(), data + _convert_pos_inv(sd, r_start), _convert_pos_inv(sd, r_end - r_start), &err);
if (U_FAILURE(err)) {
UBreakIterator *bi = sd->_get_break_iterator_for_locale(language, &err);
if (!U_FAILURE(err) && bi) {
ubrk_setText(bi, data + _convert_pos_inv(sd, r_start), _convert_pos_inv(sd, r_end - r_start), &err);
}

if (U_FAILURE(err) || !bi) {
// No data loaded - use fallback.
for (int j = r_start; j < r_end; j++) {
char32_t c = sd->text[j - sd->start];
Expand Down Expand Up @@ -5662,7 +5666,6 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) {
}
}
}
ubrk_close(bi);
i++;
}
sd->break_ops_valid = true;
Expand Down Expand Up @@ -6110,6 +6113,15 @@ _FORCE_INLINE_ void TextServerAdvanced::_add_featuers(const Dictionary &p_source
}
}

UBreakIterator *TextServerAdvanced::ShapedTextDataAdvanced::_get_break_iterator_for_locale(const String &p_language, UErrorCode *r_err) {
HashMap<String, UBreakIterator *>::Iterator key_value = line_break_iterators_per_language.find(p_language);
if (key_value) {
return key_value->value;
}
UBreakIterator *brk = ubrk_open(UBRK_LINE, p_language.is_empty() ? TranslationServer::get_singleton()->get_tool_locale().ascii().get_data() : p_language.ascii().get_data(), nullptr, 0, r_err);
return line_break_iterators_per_language.insert(p_language, brk)->value;
}

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
8 changes: 8 additions & 0 deletions modules/text_server_adv/text_server_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,11 @@ class TextServerAdvanced : public TextServerExtension {
bool js_ops_valid = false;
bool chars_valid = false;

HashMap<String, UBreakIterator *> line_break_iterators_per_language;

// Creating UBreakIterator is surprisingly costly. To improve efficiency, we cache them.
UBreakIterator *_get_break_iterator_for_locale(const String &p_language, UErrorCode *r_err);

~ShapedTextDataAdvanced() {
for (int i = 0; i < bidi_iter.size(); i++) {
if (bidi_iter[i]) {
Expand All @@ -556,6 +561,9 @@ class TextServerAdvanced : public TextServerExtension {
if (hb_buffer) {
hb_buffer_destroy(hb_buffer);
}
for (const KeyValue<String, UBreakIterator *> &bi : line_break_iterators_per_language) {
ubrk_close(bi.value);
}
}
};

Expand Down

0 comments on commit 6c82cf0

Please sign in to comment.