diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2017-07-31 23:03:30 +0100 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2017-07-31 23:04:36 +0100 |
commit | fe0669798d617406b52a638fb2525b1f7527a2d6 (patch) | |
tree | fb07b695692ba66b11c8e79864f4ce5c97f386b0 | |
parent | f39ad9bab1f327062958b2750bf1f5609a9ee991 (diff) | |
download | pango-fe0669798d617406b52a638fb2525b1f7527a2d6.tar.gz |
Choose emoji font for color emoji
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=785566
-rw-r--r-- | pango/pango-context.c | 45 | ||||
-rw-r--r-- | pango/pango-emoji.c | 16 |
2 files changed, 50 insertions, 11 deletions
diff --git a/pango/pango-context.c b/pango/pango-context.c index 0ba2a0cd..df011f6f 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -38,6 +38,7 @@ #include "pango-engine-private.h" #include "pango-script-private.h" +#include "pango-emoji-private.h" /** * PangoContext: @@ -691,7 +692,8 @@ typedef enum { LANG_CHANGED = 1 << 2, FONT_CHANGED = 1 << 3, DERIVED_LANG_CHANGED = 1 << 4, - WIDTH_CHANGED = 1 << 5 + WIDTH_CHANGED = 1 << 5, + EMOJI_CHANGED = 1 << 6, } ChangedFlags; @@ -738,6 +740,7 @@ struct _ItemizeState gboolean free_attr_iter; const char *attr_end; PangoFontDescription *font_desc; + PangoFontDescription *emoji_font_desc; PangoLanguage *lang; GSList *extra_attrs; gboolean copy_extra_attrs; @@ -749,6 +752,7 @@ struct _ItemizeState PangoScript script; PangoWidthIter width_iter; + PangoEmojiIter emoji_iter; PangoLanguage *derived_lang; PangoEngineLang *lang_engine; @@ -799,6 +803,12 @@ update_attr_iterator (ItemizeState *state) else state->attr_end = state->end; + if (state->emoji_font_desc) + { + pango_font_description_free (state->emoji_font_desc); + state->emoji_font_desc = NULL; + } + old_lang = state->lang; if (state->font_desc) pango_font_description_free (state->font_desc); @@ -839,6 +849,8 @@ update_end (ItemizeState *state) state->run_end = state->script_end; if (state->width_iter.end < state->run_end) state->run_end = state->width_iter.end; + if (state->emoji_iter.end < state->run_end) + state->run_end = state->emoji_iter.end; } /* g_unichar_iswide() uses EastAsianWidth, which is broken. @@ -920,6 +932,11 @@ width_iter_init (PangoWidthIter* iter, const char* text, int length) } static void +width_iter_fini (PangoWidthIter* iter) +{ +} + +static void itemize_state_init (ItemizeState *state, PangoContext *context, const char *text, @@ -967,6 +984,7 @@ itemize_state_init (ItemizeState *state, state->free_attr_iter = FALSE; } + state->emoji_font_desc = NULL; if (state->attr_iter) { state->font_desc = NULL; @@ -992,8 +1010,8 @@ itemize_state_init (ItemizeState *state, pango_script_iter_get_range (&state->script_iter, NULL, &state->script_end, &state->script); - /* Initialize the width iterator */ width_iter_init (&state->width_iter, text + start_index, length); + _pango_emoji_iter_init (&state->emoji_iter, text + start_index, length); update_end (state); @@ -1012,7 +1030,7 @@ itemize_state_init (ItemizeState *state, state->cache = NULL; state->base_font = NULL; - state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED | FONT_CHANGED | WIDTH_CHANGED; + state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED | FONT_CHANGED | WIDTH_CHANGED | EMOJI_CHANGED; } static gboolean @@ -1048,6 +1066,11 @@ itemize_state_next (ItemizeState *state) width_iter_next (&state->width_iter); state->changed |= WIDTH_CHANGED; } + if (state->run_end == state->emoji_iter.end) + { + _pango_emoji_iter_next (&state->emoji_iter); + state->changed |= EMOJI_CHANGED; + } update_end (state); @@ -1352,6 +1375,11 @@ itemize_state_update_for_new_run (ItemizeState *state) state->lang_engine = _pango_get_language_engine (); } + if (state->changed & (EMOJI_CHANGED)) + { + state->changed |= FONT_CHANGED; + } + if (state->changed & (FONT_CHANGED | DERIVED_LANG_CHANGED) && state->current_fonts) { @@ -1362,9 +1390,15 @@ itemize_state_update_for_new_run (ItemizeState *state) if (!state->current_fonts) { + gboolean is_emoji = state->emoji_iter.is_emoji; + if (is_emoji && !state->emoji_font_desc) + { + state->emoji_font_desc = pango_font_description_copy_static (state->font_desc); + pango_font_description_set_family_static (state->emoji_font_desc, "emoji"); + } state->current_fonts = pango_font_map_load_fontset (state->context->font_map, state->context, - state->font_desc, + is_emoji ? state->emoji_font_desc : state->font_desc, state->derived_lang); state->cache = get_font_cache (state->current_fonts); } @@ -1492,6 +1526,9 @@ itemize_state_finish (ItemizeState *state) pango_attr_iterator_destroy (state->attr_iter); _pango_script_iter_fini (&state->script_iter); pango_font_description_free (state->font_desc); + pango_font_description_free (state->emoji_font_desc); + width_iter_fini (&state->width_iter); + _pango_emoji_iter_fini (&state->emoji_iter); if (state->current_fonts) g_object_unref (state->current_fonts); diff --git a/pango/pango-emoji.c b/pango/pango-emoji.c index 630a0e7f..0e332dff 100644 --- a/pango/pango-emoji.c +++ b/pango/pango-emoji.c @@ -160,7 +160,7 @@ _pango_emoji_iter_init (PangoEmojiIter *iter, iter->start = text; iter->end = text; - iter->is_emoji = FALSE; + iter->is_emoji = (gboolean) 2; /* HACK */ _pango_emoji_iter_next (iter); @@ -194,7 +194,7 @@ _pango_emoji_iter_next (PangoEmojiIter *iter) * presentation for emoji that are part of a ZWJ sequence, example * U+1F441 U+200D U+1F5E8, eye (text presentation) + ZWJ + left speech * bubble, see below. */ - if ((!(ch == kZeroWidthJoinerCharacter && iter->is_emoji) && + if ((!(ch == kZeroWidthJoinerCharacter && !iter->is_emoji) && ch != kVariationSelector15Character && ch != kVariationSelector16Character && ch != kCombiningEnclosingCircleBackslashCharacter && @@ -204,14 +204,14 @@ _pango_emoji_iter_next (PangoEmojiIter *iter) ch == kMaleSignCharacter || ch == kFemaleSignCharacter || ch == kStaffOfAesculapiusCharacter) && - iter->is_emoji)) || + !iter->is_emoji)) || current_emoji_type == PANGO_EMOJI_TYPE_INVALID) { current_emoji_type = _pango_get_emoji_type (ch); } - if (iter->end < iter->text_end) + if (g_utf8_next_char (iter->end) < iter->text_end) /* Optimize. */ { - gunichar peek_char = g_utf8_get_char (iter->end); + gunichar peek_char = g_utf8_get_char (g_utf8_next_char (iter->end)); /* Variation Selectors */ if (current_emoji_type == @@ -248,9 +248,11 @@ _pango_emoji_iter_next (PangoEmojiIter *iter) } } - if (iter->is_emoji != PANGO_EMOJI_TYPE_IS_EMOJI (current_emoji_type) && iter->start != iter->text_start) + if (iter->is_emoji == (gboolean) 2) + iter->is_emoji = !PANGO_EMOJI_TYPE_IS_EMOJI (current_emoji_type); + if (iter->is_emoji == PANGO_EMOJI_TYPE_IS_EMOJI (current_emoji_type)) { - iter->is_emoji = PANGO_EMOJI_TYPE_IS_EMOJI (current_emoji_type); + iter->is_emoji = !PANGO_EMOJI_TYPE_IS_EMOJI (current_emoji_type); return TRUE; } } |