diff options
author | Matthias Clasen <mclasen@redhat.com> | 2021-03-29 14:35:11 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2021-03-29 15:05:08 -0400 |
commit | d5a7518b84c29e5877c7408d3bbf97f9dc8c153e (patch) | |
tree | db6a3d0de11ca80a5dcf0213d490d5822070a4b7 /pango/pango-emoji.c | |
parent | 5ccc0c7aa5de2667a5e0da8c35387eb662c3edff (diff) | |
download | pango-d5a7518b84c29e5877c7408d3bbf97f9dc8c153e.tar.gz |
Speed up Emoji classification
Open-code the bsearch here. These functions
show up in profiles, since itemizations uses
an Emoji iter.
Diffstat (limited to 'pango/pango-emoji.c')
-rw-r--r-- | pango/pango-emoji.c | 123 |
1 files changed, 64 insertions, 59 deletions
diff --git a/pango/pango-emoji.c b/pango/pango-emoji.c index e316b370..8d5a46d6 100644 --- a/pango/pango-emoji.c +++ b/pango/pango-emoji.c @@ -52,40 +52,37 @@ #include "pango-emoji-private.h" #include "pango-emoji-table.h" - -static int -interval_compare (const void *key, const void *elt) +static inline gboolean +bsearch_interval (gunichar c, + const struct Interval table[], + guint n) { - gunichar c = GPOINTER_TO_UINT (key); - struct Interval *interval = (struct Interval *)elt; - - if (c < interval->start) - return -1; - if (c > interval->end) - return +1; - - return 0; + guint lower = 0; + guint upper = n - 1; + + while (lower <= upper) + { + int mid = (lower + upper) / 2; + + if (c < table[mid].start) + upper = mid - 1; + else if (c > table[mid].end) + lower = mid + 1; + else + return TRUE; + } + + return FALSE; } #define DEFINE_pango_Is_(name) \ -static gboolean \ +static inline gboolean \ _pango_Is_##name (gunichar ch) \ { \ - /* bsearch() is declared attribute(nonnull(1)) so we can't validly search \ - * for a NULL key */ \ - /* \ - if (G_UNLIKELY (ch == 0)) \ - return FALSE; \ - */ \ - \ - if (bsearch (GUINT_TO_POINTER (ch), \ - _pango_##name##_table, \ - G_N_ELEMENTS (_pango_##name##_table), \ - sizeof _pango_##name##_table[0], \ - interval_compare)) \ - return TRUE; \ - \ - return FALSE; \ + return ch >= _pango_##name##_table[0].start && \ + bsearch_interval (ch, \ + _pango_##name##_table, \ + G_N_ELEMENTS (_pango_##name##_table)); \ } DEFINE_pango_Is_(Emoji) @@ -106,36 +103,36 @@ _pango_Is_Emoji_Extended_Pictographic (gunichar ch) return _pango_Is_Extended_Pictographic (ch); } -static gboolean +static inline gboolean _pango_Is_Emoji_Text_Default (gunichar ch) { return _pango_Is_Emoji (ch) && !_pango_Is_Emoji_Presentation (ch); } -static gboolean +static inline gboolean _pango_Is_Emoji_Emoji_Default (gunichar ch) { return _pango_Is_Emoji_Presentation (ch); } -static gboolean +static inline gboolean _pango_Is_Emoji_Keycap_Base (gunichar ch) { return (ch >= '0' && ch <= '9') || ch == '#' || ch == '*'; } -static gboolean +static inline gboolean _pango_Is_Regional_Indicator (gunichar ch) { return (ch >= 0x1F1E6 && ch <= 0x1F1FF); } -const gunichar kCombiningEnclosingCircleBackslashCharacter = 0x20E0; -const gunichar kCombiningEnclosingKeycapCharacter = 0x20E3; -const gunichar kVariationSelector15Character = 0xFE0E; -const gunichar kVariationSelector16Character = 0xFE0F; -const gunichar kZeroWidthJoinerCharacter = 0x200D; +#define kCombiningEnclosingCircleBackslashCharacter 0x20E0 +#define kCombiningEnclosingKeycapCharacter 0x20E3 +#define kVariationSelector15Character 0xFE0E +#define kVariationSelector16Character 0xFE0F +#define kZeroWidthJoinerCharacter 0x200D enum PangoEmojiScannerCategory { EMOJI = 0, @@ -157,27 +154,38 @@ enum PangoEmojiScannerCategory { kMaxEmojiScannerCategory = 16 }; -static unsigned char +static inline unsigned char _pango_EmojiSegmentationCategory (gunichar codepoint) { /* Specific ones first. */ - if (codepoint == kCombiningEnclosingKeycapCharacter) - return COMBINING_ENCLOSING_KEYCAP; - if (codepoint == kCombiningEnclosingCircleBackslashCharacter) - return COMBINING_ENCLOSING_CIRCLE_BACKSLASH; - if (codepoint == kZeroWidthJoinerCharacter) - return ZWJ; - if (codepoint == kVariationSelector15Character) - return VS15; - if (codepoint == kVariationSelector16Character) - return VS16; - if (codepoint == 0x1F3F4) - return TAG_BASE; - if ((codepoint >= 0xE0030 && codepoint <= 0xE0039) || - (codepoint >= 0xE0061 && codepoint <= 0xE007A)) - return TAG_SEQUENCE; - if (codepoint == 0xE007F) - return TAG_TERM; + switch (codepoint) + { + case 'a' ... 'z': + case 'A' ... 'Z': + case ' ': + return kMaxEmojiScannerCategory; + case '0' ... '9': + return KEYCAP_BASE; + case kCombiningEnclosingKeycapCharacter: + return COMBINING_ENCLOSING_KEYCAP; + case kCombiningEnclosingCircleBackslashCharacter: + return COMBINING_ENCLOSING_CIRCLE_BACKSLASH; + case kZeroWidthJoinerCharacter: + return ZWJ; + case kVariationSelector15Character: + return VS15; + case kVariationSelector16Character: + return VS16; + case 0x1F3F4: + return TAG_BASE; + case 0xE0030 ... 0xE0039: + case 0xE0061 ... 0xE007A: + return TAG_SEQUENCE; + case 0xE007F: + return TAG_TERM; + default: ; + } + if (_pango_Is_Emoji_Modifier_Base (codepoint)) return EMOJI_MODIFIER_BASE; if (_pango_Is_Emoji_Modifier (codepoint)) @@ -186,13 +194,10 @@ _pango_EmojiSegmentationCategory (gunichar codepoint) return REGIONAL_INDICATOR; if (_pango_Is_Emoji_Keycap_Base (codepoint)) return KEYCAP_BASE; - if (_pango_Is_Emoji_Emoji_Default (codepoint)) return EMOJI_EMOJI_PRESENTATION; - if (_pango_Is_Emoji_Text_Default (codepoint)) - return EMOJI_TEXT_PRESENTATION; if (_pango_Is_Emoji (codepoint)) - return EMOJI; + return EMOJI_TEXT_PRESENTATION; /* Ragel state machine will interpret unknown category as "any". */ return kMaxEmojiScannerCategory; |