summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2023-01-31 04:56:23 +0000
committerMatthias Clasen <mclasen@redhat.com>2023-01-31 04:56:23 +0000
commitfad3e7690845f128aa0beba9adaae7038c01269f (patch)
tree6dbf158ea77e0311be9022dcc5741e8af1a27bcb
parent7b4a7d6dc00365289bece029e6698d01441bfb1f (diff)
parentc895f9a8c4b7c4d5553d6fde1c95921117fffbc5 (diff)
downloadpango-fad3e7690845f128aa0beba9adaae7038c01269f.tar.gz
Merge branch 'misc-opt' into 'main'
shape: Avoid some overhead See merge request GNOME/pango!674
-rw-r--r--meson.build6
-rw-r--r--pango/itemize.c17
-rw-r--r--pango/pango-bidi-type.c58
-rw-r--r--pango/pango-break-table.h5
-rw-r--r--pango/pango-emoji-private.h6
-rw-r--r--pango/pango-emoji.c16
-rw-r--r--pango/pango-utils-private.h7
-rw-r--r--pango/shape.c32
8 files changed, 119 insertions, 28 deletions
diff --git a/meson.build b/meson.build
index 50ec14b9..4bd43561 100644
--- a/meson.build
+++ b/meson.build
@@ -247,6 +247,12 @@ harfbuzz_dep = dependency('harfbuzz',
pango_deps += harfbuzz_dep
+if harfbuzz_dep.type_name() != 'internal'
+ if cc.has_function('hb_ot_color_has_layers', dependencies: harfbuzz_dep)
+ pango_conf.set('HAVE_HB_OT_COLOR_HAS_LAYERS', 1)
+ endif
+endif
+
# If option is 'auto' or 'enabled' it is not required to find fontconfig on the
# system because a fallback is done at the end. Override 'disabled' option on
# platforms that requires it.
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];
}