diff options
-rw-r--r-- | pango/break.c | 5 | ||||
-rw-r--r-- | pango/pango-context.c | 15 | ||||
-rw-r--r-- | pango/pango-emoji.c | 123 | ||||
-rw-r--r-- | pango/pango-impl-utils.h | 3 | ||||
-rw-r--r-- | pango/pangofc-shape.c | 27 |
5 files changed, 92 insertions, 81 deletions
diff --git a/pango/break.c b/pango/break.c index fadf01d0..6b8e5c01 100644 --- a/pango/break.c +++ b/pango/break.c @@ -362,12 +362,15 @@ pango_default_break (const gchar *text, case G_UNICODE_PARAGRAPH_SEPARATOR: attrs[i].is_white = TRUE; break; - default: + case G_UNICODE_CONTROL: if (wc == '\t' || wc == '\n' || wc == '\r' || wc == '\f') attrs[i].is_white = TRUE; else attrs[i].is_white = FALSE; break; + default: + attrs[i].is_white = FALSE; + break; } /* Just few spaces have variable width. So explicitly mark them. diff --git a/pango/pango-context.c b/pango/pango-context.c index ccaa1bac..90952add 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -910,6 +910,9 @@ width_iter_is_upright (gunichar ch) int st = 0; int ed = max; + if (ch < upright[0][0]) + return FALSE; + while (st <= ed) { int mid = (st + ed) / 2; @@ -926,7 +929,7 @@ width_iter_is_upright (gunichar ch) } static void -width_iter_next(PangoWidthIter* iter) +width_iter_next (PangoWidthIter *iter) { gboolean met_joiner = FALSE; iter->start = iter->end; @@ -958,9 +961,9 @@ width_iter_next(PangoWidthIter* iter) } /* for variation selector, tag and emoji modifier. */ - if (G_UNLIKELY(ch == 0xFE0EU || ch == 0xFE0FU - || (ch >= 0xE0020 && ch <= 0xE007F) - || (ch >= 0x1F3FB && ch <= 0x1F3FF))) + if (G_UNLIKELY (ch == 0xFE0EU || ch == 0xFE0FU || + (ch >= 0xE0020 && ch <= 0xE007F) || + (ch >= 0x1F3FB && ch <= 0x1F3FF))) { iter->end = g_utf8_next_char (iter->end); continue; @@ -968,6 +971,7 @@ width_iter_next(PangoWidthIter* iter) if (width_iter_is_upright (ch) != iter->upright) break; + iter->end = g_utf8_next_char (iter->end); } } @@ -1000,7 +1004,6 @@ itemize_state_init (ItemizeState *state, PangoAttrIterator *cached_iter, const PangoFontDescription *desc) { - state->context = context; state->text = text; state->end = text + start_index + length; @@ -1576,7 +1579,7 @@ pango_itemize_with_base_dir (PangoContext *context, g_return_val_if_fail (length >= 0, NULL); g_return_val_if_fail (length == 0 || text != NULL, NULL); - if (length == 0 || g_utf8_strlen (text + start_index, length) == 0) + if (length == 0 || g_utf8_get_char (text + start_index) == '\0') return NULL; itemize_state_init (&state, context, text, base_dir, start_index, length, 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; diff --git a/pango/pango-impl-utils.h b/pango/pango-impl-utils.h index d2420321..bbeca994 100644 --- a/pango/pango-impl-utils.h +++ b/pango/pango-impl-utils.h @@ -163,6 +163,9 @@ pango_get_ignorable (gunichar ch) for (i = 0; i < G_N_ELEMENTS (ignorables); i++) { + if (ch < ignorables[i].ch) + return NULL; + if (ch == ignorables[i].ch) return ignorables[i].nick; } diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c index 5c716b24..0a5ce7f9 100644 --- a/pango/pangofc-shape.c +++ b/pango/pangofc-shape.c @@ -151,18 +151,10 @@ pango_hb_font_get_nominal_glyph (hb_font_t *font, { PangoHbShapeContext *context = (PangoHbShapeContext *) font_data; - if ((context->show_flags & PANGO_SHOW_IGNORABLES) != 0) + if (context->show_flags != 0) { - if (pango_get_ignorable (unicode)) - { - *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode); - return TRUE; - } - } - - if ((context->show_flags & PANGO_SHOW_SPACES) != 0) - { - if (g_unichar_type (unicode) == G_UNICODE_SPACE_SEPARATOR) + if ((context->show_flags & PANGO_SHOW_SPACES) != 0 && + g_unichar_type (unicode) == G_UNICODE_SPACE_SEPARATOR) { /* Replace 0x20 by visible space, since we * don't draw a hex box for 0x20 @@ -173,11 +165,16 @@ pango_hb_font_get_nominal_glyph (hb_font_t *font, *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode); return TRUE; } - } - if ((context->show_flags & PANGO_SHOW_LINE_BREAKS) != 0) - { - if (unicode == 0x2028) + if ((context->show_flags & PANGO_SHOW_IGNORABLES) != 0 && + pango_get_ignorable (unicode)) + { + *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode); + return TRUE; + } + + if ((context->show_flags & PANGO_SHOW_LINE_BREAKS) != 0 && + unicode == 0x2028) { /* Always mark LS as unknown. If it ends up * at the line end, PangoLayout takes care of |