diff options
author | Matthias Clasen <mclasen@redhat.com> | 2023-01-31 04:56:23 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2023-01-31 04:56:23 +0000 |
commit | fad3e7690845f128aa0beba9adaae7038c01269f (patch) | |
tree | 6dbf158ea77e0311be9022dcc5741e8af1a27bcb /pango | |
parent | 7b4a7d6dc00365289bece029e6698d01441bfb1f (diff) | |
parent | c895f9a8c4b7c4d5553d6fde1c95921117fffbc5 (diff) | |
download | pango-fad3e7690845f128aa0beba9adaae7038c01269f.tar.gz |
Merge branch 'misc-opt' into 'main'
shape: Avoid some overhead
See merge request GNOME/pango!674
Diffstat (limited to 'pango')
-rw-r--r-- | pango/itemize.c | 17 | ||||
-rw-r--r-- | pango/pango-bidi-type.c | 58 | ||||
-rw-r--r-- | pango/pango-break-table.h | 5 | ||||
-rw-r--r-- | pango/pango-emoji-private.h | 6 | ||||
-rw-r--r-- | pango/pango-emoji.c | 16 | ||||
-rw-r--r-- | pango/pango-utils-private.h | 7 | ||||
-rw-r--r-- | pango/shape.c | 32 |
7 files changed, 113 insertions, 28 deletions
diff --git a/pango/itemize.c b/pango/itemize.c index 35f17d54..5500d56d 100644 --- a/pango/itemize.c +++ b/pango/itemize.c @@ -33,6 +33,7 @@ #include "pango-emoji-private.h" #include "pango-attributes-private.h" #include "pango-item-private.h" +#include "pango-utils-private.h" #include <hb-ot.h> @@ -292,6 +293,7 @@ struct _ItemizeState PangoItem *item; guint8 *embedding_levels; + guint8 embedding_levels_[64]; int embedding_end_offset; const char *embedding_end; guint8 embedding; @@ -433,6 +435,10 @@ itemize_state_init (ItemizeState *state, PangoAttrIterator *cached_iter, const PangoFontDescription *desc) { + unsigned int n_chars; + + n_chars = g_utf8_strlen (text + start_index, length); + state->context = context; state->text = text; state->end = text + start_index + length; @@ -447,7 +453,11 @@ itemize_state_init (ItemizeState *state, /* First, apply the bidirectional algorithm to break * the text into directional runs. */ - state->embedding_levels = pango_log2vis_get_embedding_levels (text + start_index, length, &base_dir); + if (n_chars < 64) + state->embedding_levels = state->embedding_levels_; + else + state->embedding_levels = g_new (guint8, n_chars); + pango_log2vis_fill_embedding_levels (text + start_index, length, n_chars, state->embedding_levels, &base_dir); state->embedding_end_offset = 0; state->embedding_end = text + start_index; @@ -503,7 +513,7 @@ itemize_state_init (ItemizeState *state, &state->script_end, &state->script); width_iter_init (&state->width_iter, text + start_index, length); - _pango_emoji_iter_init (&state->emoji_iter, text + start_index, length); + _pango_emoji_iter_init (&state->emoji_iter, text + start_index, length, n_chars); if (!PANGO_GRAVITY_IS_VERTICAL (state->context->resolved_gravity)) state->width_iter.end = state->end; @@ -1017,7 +1027,8 @@ itemize_state_process_run (ItemizeState *state) static void itemize_state_finish (ItemizeState *state) { - g_free (state->embedding_levels); + if (state->embedding_levels != state->embedding_levels_) + g_free (state->embedding_levels); if (state->free_attr_iter) pango_attr_iterator_destroy (state->attr_iter); _pango_script_iter_fini (&state->script_iter); diff --git a/pango/pango-bidi-type.c b/pango/pango-bidi-type.c index f854a1b8..4277dc19 100644 --- a/pango/pango-bidi-type.c +++ b/pango/pango-bidi-type.c @@ -29,6 +29,7 @@ #include "pango-bidi-type.h" #include "pango-utils.h" +#include "pango-utils-private.h" /** * pango_bidi_type_for_unichar: @@ -109,15 +110,37 @@ pango_bidi_type_for_unichar (gunichar ch) */ guint8 * pango_log2vis_get_embedding_levels (const gchar *text, - int length, - PangoDirection *pbase_dir) + int length, + PangoDirection *pbase_dir) { - glong n_chars, i; - guint8 *embedding_levels_list; + unsigned int n_chars; + guint8 *embedding_levels; + + if (length < 0) + length = strlen (text); + + n_chars = g_utf8_strlen (text, length); + embedding_levels = g_new (guint8, n_chars); + + pango_log2vis_fill_embedding_levels (text, length, n_chars, embedding_levels, pbase_dir); + + return embedding_levels; +} + +void +pango_log2vis_fill_embedding_levels (const gchar *text, + int length, + unsigned int n_chars, + guint8 *embedding_levels_list, + PangoDirection *pbase_dir) +{ + glong i; const gchar *p; FriBidiParType fribidi_base_dir; FriBidiCharType *bidi_types; + FriBidiCharType bidi_types_[64]; FriBidiBracketType *bracket_types; + FriBidiBracketType bracket_types_[64]; FriBidiLevel max_level; FriBidiCharType ored_types = 0; FriBidiCharType anded_strongs = FRIBIDI_TYPE_RLE; @@ -145,14 +168,16 @@ pango_log2vis_get_embedding_levels (const gchar *text, break; } - if (length < 0) - length = strlen (text); - - n_chars = g_utf8_strlen (text, length); - - bidi_types = g_new (FriBidiCharType, n_chars); - bracket_types = g_new (FriBidiBracketType, n_chars); - embedding_levels_list = g_new (guint8, n_chars); + if (n_chars < 64) + { + bidi_types = bidi_types_; + bracket_types = bracket_types_; + } + else + { + bidi_types = g_new (FriBidiCharType, n_chars); + bracket_types = g_new (FriBidiBracketType, n_chars); + } for (i = 0, p = text; p < text + length; p = g_utf8_next_char(p), i++) { @@ -232,12 +257,13 @@ pango_log2vis_get_embedding_levels (const gchar *text, } resolved: - g_free (bidi_types); - g_free (bracket_types); + if (n_chars >= 64) + { + g_free (bidi_types); + g_free (bracket_types); + } *pbase_dir = (fribidi_base_dir == FRIBIDI_PAR_LTR) ? PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL; - - return embedding_levels_list; } /** diff --git a/pango/pango-break-table.h b/pango/pango-break-table.h index b0ef21bf..981a9898 100644 --- a/pango/pango-break-table.h +++ b/pango/pango-break-table.h @@ -626,7 +626,10 @@ _pango_is_Consonant_Preceding_Repha (gunichar wc) static inline gboolean _pango_is_EastAsianWide (gunichar wc) { - if ((wc >= 0x1100 && wc <= 0x27B0)) + if (wc < 0x1100) + return FALSE; + + if (wc <= 0x27B0) { if ((wc >= 0x1100 && wc <= 0x25FE)) { diff --git a/pango/pango-emoji-private.h b/pango/pango-emoji-private.h index d5cbccf4..6f0d86f9 100644 --- a/pango/pango-emoji-private.h +++ b/pango/pango-emoji-private.h @@ -41,14 +41,16 @@ struct _PangoEmojiIter gboolean is_emoji; unsigned char *types; + unsigned char types_[64]; unsigned int n_chars; unsigned int cursor; }; PangoEmojiIter * _pango_emoji_iter_init (PangoEmojiIter *iter, - const char *text, - int length); + const char *text, + int length, + unsigned int n_chars); gboolean _pango_emoji_iter_next (PangoEmojiIter *iter); diff --git a/pango/pango-emoji.c b/pango/pango-emoji.c index e1f16dba..83ebfe6e 100644 --- a/pango/pango-emoji.c +++ b/pango/pango-emoji.c @@ -213,14 +213,19 @@ typedef unsigned char *emoji_text_iter_t; PangoEmojiIter * _pango_emoji_iter_init (PangoEmojiIter *iter, - const char *text, - int length) + const char *text, + int length, + unsigned int n_chars) { - unsigned int n_chars = g_utf8_strlen (text, length); - unsigned char *types = g_malloc (n_chars); + unsigned char *types; unsigned int i; const char *p; + if (n_chars < 64) + types = iter->types_; + else + types = g_malloc (n_chars); + p = text; for (i = 0; i < n_chars; i++) { @@ -247,7 +252,8 @@ _pango_emoji_iter_init (PangoEmojiIter *iter, void _pango_emoji_iter_fini (PangoEmojiIter *iter) { - g_free (iter->types); + if (iter->types != iter->types_) + g_free (iter->types); } gboolean diff --git a/pango/pango-utils-private.h b/pango/pango-utils-private.h index 4087dc14..78b06113 100644 --- a/pango/pango-utils-private.h +++ b/pango/pango-utils-private.h @@ -54,6 +54,13 @@ const char * pango_get_sysconf_subdirectory (void) G_GNUC_PURE; PANGO_DEPRECATED const char * pango_get_lib_subdirectory (void) G_GNUC_PURE; +void pango_log2vis_fill_embedding_levels (const char *text, + int length, + unsigned int n_chars, + guint8 *embedding_levels, + PangoDirection *pbase_dir); + + G_END_DECLS #endif /* __PANGO_UTILS_PRIATE_H__ */ diff --git a/pango/shape.c b/pango/shape.c index 81cfedf0..a69207bf 100644 --- a/pango/shape.c +++ b/pango/shape.c @@ -299,6 +299,34 @@ find_text_transform (const PangoAnalysis *analysis) return transform; } +static inline gboolean +face_has_layers (hb_face_t *face) +{ +#ifdef HAVE_HB_OT_COLOR_HAS_LAYERS + return hb_ot_color_has_layers (face); +#else + hb_blob_t *blob; + gboolean ret; + + blob = hb_face_reference_table (face, HB_TAG ('C','O','L','R')); + ret = blob != hb_blob_get_empty (); + + hb_blob_destroy (blob); + + return ret; +#endif +} + +static gboolean +font_has_color (hb_font_t *font) +{ + hb_face_t *face; + + face = hb_font_get_face (font); + + return face_has_layers (face) || hb_ot_color_has_png (face) || hb_ot_color_has_svg (face); +} + static gboolean glyph_has_color (hb_font_t *font, hb_codepoint_t glyph) @@ -367,6 +395,7 @@ pango_hb_shape (const char *item_text, PangoGlyphInfo *infos; PangoTextTransform transform; int hyphen_index; + gboolean font_is_color; g_return_if_fail (analysis != NULL); g_return_if_fail (analysis->font != NULL); @@ -497,13 +526,14 @@ pango_hb_shape (const char *item_text, pango_glyph_string_set_size (glyphs, num_glyphs); infos = glyphs->glyphs; last_cluster = -1; + font_is_color = font_has_color (hb_font); for (i = 0; i < num_glyphs; i++) { infos[i].glyph = hb_glyph->codepoint; glyphs->log_clusters[i] = hb_glyph->cluster - item_offset; infos[i].attr.is_cluster_start = glyphs->log_clusters[i] != last_cluster; - infos[i].attr.is_color = glyph_has_color (hb_font, hb_glyph->codepoint); + infos[i].attr.is_color = font_is_color && glyph_has_color (hb_font, hb_glyph->codepoint); hb_glyph++; last_cluster = glyphs->log_clusters[i]; } |