Skip to content

Commit 90509e6

Browse files
committed
Merge pull request #102129 from Ivorforce/optimize-text-server-adv-break-iter
Optimize text rendering by caching `UBreakIterator` instances.
2 parents 3bc2821 + 6c82cf0 commit 90509e6

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

modules/text_server_adv/text_server_adv.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5664,8 +5664,12 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) {
56645664
i++;
56655665
}
56665666
int r_end = sd->spans[i].end;
5667-
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);
5668-
if (U_FAILURE(err)) {
5667+
UBreakIterator *bi = sd->_get_break_iterator_for_locale(language, &err);
5668+
if (!U_FAILURE(err) && bi) {
5669+
ubrk_setText(bi, data + _convert_pos_inv(sd, r_start), _convert_pos_inv(sd, r_end - r_start), &err);
5670+
}
5671+
5672+
if (U_FAILURE(err) || !bi) {
56695673
// No data loaded - use fallback.
56705674
for (int j = r_start; j < r_end; j++) {
56715675
char32_t c = sd->text[j - sd->start];
@@ -5694,7 +5698,6 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) {
56945698
}
56955699
}
56965700
}
5697-
ubrk_close(bi);
56985701
i++;
56995702
}
57005703
sd->break_ops_valid = true;
@@ -6142,6 +6145,15 @@ _FORCE_INLINE_ void TextServerAdvanced::_add_featuers(const Dictionary &p_source
61426145
}
61436146
}
61446147

6148+
UBreakIterator *TextServerAdvanced::ShapedTextDataAdvanced::_get_break_iterator_for_locale(const String &p_language, UErrorCode *r_err) {
6149+
HashMap<String, UBreakIterator *>::Iterator key_value = line_break_iterators_per_language.find(p_language);
6150+
if (key_value) {
6151+
return key_value->value;
6152+
}
6153+
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);
6154+
return line_break_iterators_per_language.insert(p_language, brk)->value;
6155+
}
6156+
61456157
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) {
61466158
RID f;
61476159
int fs = p_sd->spans[p_span].font_size;

modules/text_server_adv/text_server_adv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,11 @@ class TextServerAdvanced : public TextServerExtension {
545545
bool js_ops_valid = false;
546546
bool chars_valid = false;
547547

548+
HashMap<String, UBreakIterator *> line_break_iterators_per_language;
549+
550+
// Creating UBreakIterator is surprisingly costly. To improve efficiency, we cache them.
551+
UBreakIterator *_get_break_iterator_for_locale(const String &p_language, UErrorCode *r_err);
552+
548553
~ShapedTextDataAdvanced() {
549554
for (int i = 0; i < bidi_iter.size(); i++) {
550555
if (bidi_iter[i]) {
@@ -557,6 +562,9 @@ class TextServerAdvanced : public TextServerExtension {
557562
if (hb_buffer) {
558563
hb_buffer_destroy(hb_buffer);
559564
}
565+
for (const KeyValue<String, UBreakIterator *> &bi : line_break_iterators_per_language) {
566+
ubrk_close(bi.value);
567+
}
560568
}
561569
};
562570

0 commit comments

Comments
 (0)