summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2017-07-31 21:45:16 +0100
committerBehdad Esfahbod <behdad@behdad.org>2017-07-31 23:04:15 +0100
commitf39ad9bab1f327062958b2750bf1f5609a9ee991 (patch)
tree2f4170c32d9101881c86b6d685533a215ab13b6a
parent284d357e3d6e29c1437ca18bab347c1af8330908 (diff)
downloadpango-f39ad9bab1f327062958b2750bf1f5609a9ee991.tar.gz
Add data files and routines for emoji itemization
Ported from Chromium. Not hooked yet.
-rw-r--r--pango/Makefile.am3
-rw-r--r--pango/pango-emoji-private.h49
-rw-r--r--pango/pango-emoji-table.h403
-rw-r--r--pango/pango-emoji.c266
-rw-r--r--tools/Makefile.am1
-rwxr-xr-xtools/gen-emoji-table.py64
6 files changed, 786 insertions, 0 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am
index 95b4dd2a..ac889151 100644
--- a/pango/Makefile.am
+++ b/pango/Makefile.am
@@ -75,6 +75,9 @@ libpango_1_0_la_SOURCES = \
pango-color-table.h \
pango-context.c \
pango-coverage.c \
+ pango-emoji.c \
+ pango-emoji-private.h \
+ pango-emoji-table.h \
pango-engine.c \
pango-engine-private.h \
pango-fontmap.c \
diff --git a/pango/pango-emoji-private.h b/pango/pango-emoji-private.h
new file mode 100644
index 00000000..eb8a52a7
--- /dev/null
+++ b/pango/pango-emoji-private.h
@@ -0,0 +1,49 @@
+/* Pango
+ * pango-emoji-private.h: Emoji handling, private definitions
+ *
+ * Copyright (C) 2017 Google, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_EMOJI_PRIVATE_H__
+#define __PANGO_EMOJI_PRIVATE_H__
+
+#include <glib.h>
+
+typedef struct _PangoEmojiIter PangoEmojiIter;
+
+struct _PangoEmojiIter
+{
+ const gchar *text_start;
+ const gchar *text_end;
+ const gchar *start;
+ const gchar *end;
+ gboolean is_emoji;
+};
+
+PangoEmojiIter *
+_pango_emoji_iter_init (PangoEmojiIter *iter,
+ const char *text,
+ int length);
+
+gboolean
+_pango_emoji_iter_next (PangoEmojiIter *iter);
+
+void
+_pango_emoji_iter_fini (PangoEmojiIter *iter);
+
+#endif /* __PANGO_EMOJI_PRIVATE_H__ */
diff --git a/pango/pango-emoji-table.h b/pango/pango-emoji-table.h
new file mode 100644
index 00000000..7688b578
--- /dev/null
+++ b/pango/pango-emoji-table.h
@@ -0,0 +1,403 @@
+/* == Start of generated table == */
+/*
+ * The following tables are generated by running:
+ *
+ * ./gen-emoji-table.py emoji-data.txt
+ *
+ * on file with this header:
+ *
+ * # emoji-data.txt
+ * # Date: 2016-06-02, 09:26:10 GMT
+ * # © 2016 Unicode®, Inc.
+ * # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+ * # For terms of use, see http://www.unicode.org/terms_of_use.html
+ * #
+ * # Emoji Data for UTR #51
+ * # Version: 3.0
+ * #
+ * # For documentation and usage, see http://www.unicode.org/reports/tr51
+ */
+
+#ifndef PANGO_EMOJI_TABLE_H
+#define PANGO_EMOJI_TABLE_H
+
+#include <glib.h>
+
+struct Interval {
+ gunichar start, end;
+};
+
+static const struct Interval _pango_Emoji_table[] =
+{
+ {0x0023, 0x0023},
+ {0x002A, 0x002A},
+ {0x0030, 0x0039},
+ {0x00A9, 0x00A9},
+ {0x00AE, 0x00AE},
+ {0x203C, 0x203C},
+ {0x2049, 0x2049},
+ {0x2122, 0x2122},
+ {0x2139, 0x2139},
+ {0x2194, 0x2199},
+ {0x21A9, 0x21AA},
+ {0x231A, 0x231B},
+ {0x2328, 0x2328},
+ {0x23CF, 0x23CF},
+ {0x23E9, 0x23F3},
+ {0x23F8, 0x23FA},
+ {0x24C2, 0x24C2},
+ {0x25AA, 0x25AB},
+ {0x25B6, 0x25B6},
+ {0x25C0, 0x25C0},
+ {0x25FB, 0x25FE},
+ {0x2600, 0x2604},
+ {0x260E, 0x260E},
+ {0x2611, 0x2611},
+ {0x2614, 0x2615},
+ {0x2618, 0x2618},
+ {0x261D, 0x261D},
+ {0x2620, 0x2620},
+ {0x2622, 0x2623},
+ {0x2626, 0x2626},
+ {0x262A, 0x262A},
+ {0x262E, 0x262F},
+ {0x2638, 0x263A},
+ {0x2648, 0x2653},
+ {0x2660, 0x2660},
+ {0x2663, 0x2663},
+ {0x2665, 0x2666},
+ {0x2668, 0x2668},
+ {0x267B, 0x267B},
+ {0x267F, 0x267F},
+ {0x2692, 0x2694},
+ {0x2696, 0x2697},
+ {0x2699, 0x2699},
+ {0x269B, 0x269C},
+ {0x26A0, 0x26A1},
+ {0x26AA, 0x26AB},
+ {0x26B0, 0x26B1},
+ {0x26BD, 0x26BE},
+ {0x26C4, 0x26C5},
+ {0x26C8, 0x26C8},
+ {0x26CE, 0x26CE},
+ {0x26CF, 0x26CF},
+ {0x26D1, 0x26D1},
+ {0x26D3, 0x26D4},
+ {0x26E9, 0x26EA},
+ {0x26F0, 0x26F5},
+ {0x26F7, 0x26FA},
+ {0x26FD, 0x26FD},
+ {0x2702, 0x2702},
+ {0x2705, 0x2705},
+ {0x2708, 0x2709},
+ {0x270A, 0x270B},
+ {0x270C, 0x270D},
+ {0x270F, 0x270F},
+ {0x2712, 0x2712},
+ {0x2714, 0x2714},
+ {0x2716, 0x2716},
+ {0x271D, 0x271D},
+ {0x2721, 0x2721},
+ {0x2728, 0x2728},
+ {0x2733, 0x2734},
+ {0x2744, 0x2744},
+ {0x2747, 0x2747},
+ {0x274C, 0x274C},
+ {0x274E, 0x274E},
+ {0x2753, 0x2755},
+ {0x2757, 0x2757},
+ {0x2763, 0x2764},
+ {0x2795, 0x2797},
+ {0x27A1, 0x27A1},
+ {0x27B0, 0x27B0},
+ {0x27BF, 0x27BF},
+ {0x2934, 0x2935},
+ {0x2B05, 0x2B07},
+ {0x2B1B, 0x2B1C},
+ {0x2B50, 0x2B50},
+ {0x2B55, 0x2B55},
+ {0x3030, 0x3030},
+ {0x303D, 0x303D},
+ {0x3297, 0x3297},
+ {0x3299, 0x3299},
+ {0x1F004, 0x1F004},
+ {0x1F0CF, 0x1F0CF},
+ {0x1F170, 0x1F171},
+ {0x1F17E, 0x1F17E},
+ {0x1F17F, 0x1F17F},
+ {0x1F18E, 0x1F18E},
+ {0x1F191, 0x1F19A},
+ {0x1F1E6, 0x1F1FF},
+ {0x1F201, 0x1F202},
+ {0x1F21A, 0x1F21A},
+ {0x1F22F, 0x1F22F},
+ {0x1F232, 0x1F23A},
+ {0x1F250, 0x1F251},
+ {0x1F300, 0x1F320},
+ {0x1F321, 0x1F321},
+ {0x1F324, 0x1F32C},
+ {0x1F32D, 0x1F32F},
+ {0x1F330, 0x1F335},
+ {0x1F336, 0x1F336},
+ {0x1F337, 0x1F37C},
+ {0x1F37D, 0x1F37D},
+ {0x1F37E, 0x1F37F},
+ {0x1F380, 0x1F393},
+ {0x1F396, 0x1F397},
+ {0x1F399, 0x1F39B},
+ {0x1F39E, 0x1F39F},
+ {0x1F3A0, 0x1F3C4},
+ {0x1F3C5, 0x1F3C5},
+ {0x1F3C6, 0x1F3CA},
+ {0x1F3CB, 0x1F3CE},
+ {0x1F3CF, 0x1F3D3},
+ {0x1F3D4, 0x1F3DF},
+ {0x1F3E0, 0x1F3F0},
+ {0x1F3F3, 0x1F3F5},
+ {0x1F3F7, 0x1F3F7},
+ {0x1F3F8, 0x1F3FF},
+ {0x1F400, 0x1F43E},
+ {0x1F43F, 0x1F43F},
+ {0x1F440, 0x1F440},
+ {0x1F441, 0x1F441},
+ {0x1F442, 0x1F4F7},
+ {0x1F4F8, 0x1F4F8},
+ {0x1F4F9, 0x1F4FC},
+ {0x1F4FD, 0x1F4FD},
+ {0x1F4FF, 0x1F4FF},
+ {0x1F500, 0x1F53D},
+ {0x1F549, 0x1F54A},
+ {0x1F54B, 0x1F54E},
+ {0x1F550, 0x1F567},
+ {0x1F56F, 0x1F570},
+ {0x1F573, 0x1F579},
+ {0x1F57A, 0x1F57A},
+ {0x1F587, 0x1F587},
+ {0x1F58A, 0x1F58D},
+ {0x1F590, 0x1F590},
+ {0x1F595, 0x1F596},
+ {0x1F5A4, 0x1F5A4},
+ {0x1F5A5, 0x1F5A5},
+ {0x1F5A8, 0x1F5A8},
+ {0x1F5B1, 0x1F5B2},
+ {0x1F5BC, 0x1F5BC},
+ {0x1F5C2, 0x1F5C4},
+ {0x1F5D1, 0x1F5D3},
+ {0x1F5DC, 0x1F5DE},
+ {0x1F5E1, 0x1F5E1},
+ {0x1F5E3, 0x1F5E3},
+ {0x1F5E8, 0x1F5E8},
+ {0x1F5EF, 0x1F5EF},
+ {0x1F5F3, 0x1F5F3},
+ {0x1F5FA, 0x1F5FA},
+ {0x1F5FB, 0x1F5FF},
+ {0x1F600, 0x1F600},
+ {0x1F601, 0x1F610},
+ {0x1F611, 0x1F611},
+ {0x1F612, 0x1F614},
+ {0x1F615, 0x1F615},
+ {0x1F616, 0x1F616},
+ {0x1F617, 0x1F617},
+ {0x1F618, 0x1F618},
+ {0x1F619, 0x1F619},
+ {0x1F61A, 0x1F61A},
+ {0x1F61B, 0x1F61B},
+ {0x1F61C, 0x1F61E},
+ {0x1F61F, 0x1F61F},
+ {0x1F620, 0x1F625},
+ {0x1F626, 0x1F627},
+ {0x1F628, 0x1F62B},
+ {0x1F62C, 0x1F62C},
+ {0x1F62D, 0x1F62D},
+ {0x1F62E, 0x1F62F},
+ {0x1F630, 0x1F633},
+ {0x1F634, 0x1F634},
+ {0x1F635, 0x1F640},
+ {0x1F641, 0x1F642},
+ {0x1F643, 0x1F644},
+ {0x1F645, 0x1F64F},
+ {0x1F680, 0x1F6C5},
+ {0x1F6CB, 0x1F6CF},
+ {0x1F6D0, 0x1F6D0},
+ {0x1F6D1, 0x1F6D2},
+ {0x1F6E0, 0x1F6E5},
+ {0x1F6E9, 0x1F6E9},
+ {0x1F6EB, 0x1F6EC},
+ {0x1F6F0, 0x1F6F0},
+ {0x1F6F3, 0x1F6F3},
+ {0x1F6F4, 0x1F6F6},
+ {0x1F910, 0x1F918},
+ {0x1F919, 0x1F91E},
+ {0x1F920, 0x1F927},
+ {0x1F930, 0x1F930},
+ {0x1F933, 0x1F93A},
+ {0x1F93C, 0x1F93E},
+ {0x1F940, 0x1F945},
+ {0x1F947, 0x1F94B},
+ {0x1F950, 0x1F95E},
+ {0x1F980, 0x1F984},
+ {0x1F985, 0x1F991},
+ {0x1F9C0, 0x1F9C0},
+};
+
+static const struct Interval _pango_Emoji_Presentation_table[] =
+{
+ {0x231A, 0x231B},
+ {0x23E9, 0x23EC},
+ {0x23F0, 0x23F0},
+ {0x23F3, 0x23F3},
+ {0x25FD, 0x25FE},
+ {0x2614, 0x2615},
+ {0x2648, 0x2653},
+ {0x267F, 0x267F},
+ {0x2693, 0x2693},
+ {0x26A1, 0x26A1},
+ {0x26AA, 0x26AB},
+ {0x26BD, 0x26BE},
+ {0x26C4, 0x26C5},
+ {0x26CE, 0x26CE},
+ {0x26D4, 0x26D4},
+ {0x26EA, 0x26EA},
+ {0x26F2, 0x26F3},
+ {0x26F5, 0x26F5},
+ {0x26FA, 0x26FA},
+ {0x26FD, 0x26FD},
+ {0x2705, 0x2705},
+ {0x270A, 0x270B},
+ {0x2728, 0x2728},
+ {0x274C, 0x274C},
+ {0x274E, 0x274E},
+ {0x2753, 0x2755},
+ {0x2757, 0x2757},
+ {0x2795, 0x2797},
+ {0x27B0, 0x27B0},
+ {0x27BF, 0x27BF},
+ {0x2B1B, 0x2B1C},
+ {0x2B50, 0x2B50},
+ {0x2B55, 0x2B55},
+ {0x1F004, 0x1F004},
+ {0x1F0CF, 0x1F0CF},
+ {0x1F18E, 0x1F18E},
+ {0x1F191, 0x1F19A},
+ {0x1F1E6, 0x1F1FF},
+ {0x1F201, 0x1F201},
+ {0x1F21A, 0x1F21A},
+ {0x1F22F, 0x1F22F},
+ {0x1F232, 0x1F236},
+ {0x1F238, 0x1F23A},
+ {0x1F250, 0x1F251},
+ {0x1F300, 0x1F320},
+ {0x1F32D, 0x1F32F},
+ {0x1F330, 0x1F335},
+ {0x1F337, 0x1F37C},
+ {0x1F37E, 0x1F37F},
+ {0x1F380, 0x1F393},
+ {0x1F3A0, 0x1F3C4},
+ {0x1F3C5, 0x1F3C5},
+ {0x1F3C6, 0x1F3CA},
+ {0x1F3CF, 0x1F3D3},
+ {0x1F3E0, 0x1F3F0},
+ {0x1F3F4, 0x1F3F4},
+ {0x1F3F8, 0x1F3FF},
+ {0x1F400, 0x1F43E},
+ {0x1F440, 0x1F440},
+ {0x1F442, 0x1F4F7},
+ {0x1F4F8, 0x1F4F8},
+ {0x1F4F9, 0x1F4FC},
+ {0x1F4FF, 0x1F4FF},
+ {0x1F500, 0x1F53D},
+ {0x1F54B, 0x1F54E},
+ {0x1F550, 0x1F567},
+ {0x1F57A, 0x1F57A},
+ {0x1F595, 0x1F596},
+ {0x1F5A4, 0x1F5A4},
+ {0x1F5FB, 0x1F5FF},
+ {0x1F600, 0x1F600},
+ {0x1F601, 0x1F610},
+ {0x1F611, 0x1F611},
+ {0x1F612, 0x1F614},
+ {0x1F615, 0x1F615},
+ {0x1F616, 0x1F616},
+ {0x1F617, 0x1F617},
+ {0x1F618, 0x1F618},
+ {0x1F619, 0x1F619},
+ {0x1F61A, 0x1F61A},
+ {0x1F61B, 0x1F61B},
+ {0x1F61C, 0x1F61E},
+ {0x1F61F, 0x1F61F},
+ {0x1F620, 0x1F625},
+ {0x1F626, 0x1F627},
+ {0x1F628, 0x1F62B},
+ {0x1F62C, 0x1F62C},
+ {0x1F62D, 0x1F62D},
+ {0x1F62E, 0x1F62F},
+ {0x1F630, 0x1F633},
+ {0x1F634, 0x1F634},
+ {0x1F635, 0x1F640},
+ {0x1F641, 0x1F642},
+ {0x1F643, 0x1F644},
+ {0x1F645, 0x1F64F},
+ {0x1F680, 0x1F6C5},
+ {0x1F6CC, 0x1F6CC},
+ {0x1F6D0, 0x1F6D0},
+ {0x1F6D1, 0x1F6D2},
+ {0x1F6EB, 0x1F6EC},
+ {0x1F6F4, 0x1F6F6},
+ {0x1F910, 0x1F918},
+ {0x1F919, 0x1F91E},
+ {0x1F920, 0x1F927},
+ {0x1F930, 0x1F930},
+ {0x1F933, 0x1F93A},
+ {0x1F93C, 0x1F93E},
+ {0x1F940, 0x1F945},
+ {0x1F947, 0x1F94B},
+ {0x1F950, 0x1F95E},
+ {0x1F980, 0x1F984},
+ {0x1F985, 0x1F991},
+ {0x1F9C0, 0x1F9C0},
+};
+
+static const struct Interval _pango_Emoji_Modifier_table[] =
+{
+ {0x1F3FB, 0x1F3FF},
+};
+
+static const struct Interval _pango_Emoji_Modifier_Base_table[] =
+{
+ {0x261D, 0x261D},
+ {0x26F9, 0x26F9},
+ {0x270A, 0x270B},
+ {0x270C, 0x270D},
+ {0x1F385, 0x1F385},
+ {0x1F3C3, 0x1F3C4},
+ {0x1F3CA, 0x1F3CA},
+ {0x1F3CB, 0x1F3CB},
+ {0x1F442, 0x1F443},
+ {0x1F446, 0x1F450},
+ {0x1F466, 0x1F469},
+ {0x1F46E, 0x1F46E},
+ {0x1F470, 0x1F478},
+ {0x1F47C, 0x1F47C},
+ {0x1F481, 0x1F483},
+ {0x1F485, 0x1F487},
+ {0x1F4AA, 0x1F4AA},
+ {0x1F575, 0x1F575},
+ {0x1F57A, 0x1F57A},
+ {0x1F590, 0x1F590},
+ {0x1F595, 0x1F596},
+ {0x1F645, 0x1F647},
+ {0x1F64B, 0x1F64F},
+ {0x1F6A3, 0x1F6A3},
+ {0x1F6B4, 0x1F6B6},
+ {0x1F6C0, 0x1F6C0},
+ {0x1F918, 0x1F918},
+ {0x1F919, 0x1F91E},
+ {0x1F926, 0x1F926},
+ {0x1F930, 0x1F930},
+ {0x1F933, 0x1F939},
+ {0x1F93C, 0x1F93E},
+};
+
+#endif /* PANGO_EMOJI_TABLE_H */
+
+/* == End of generated table == */
diff --git a/pango/pango-emoji.c b/pango/pango-emoji.c
new file mode 100644
index 00000000..630a0e7f
--- /dev/null
+++ b/pango/pango-emoji.c
@@ -0,0 +1,266 @@
+/* Pango
+ * pango-emoji.c: Emoji handling
+ *
+ * Copyright (C) 2017 Google, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Implementation of pango_emoji_iter is derived from Chromium:
+ *
+ * https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/fonts/FontFallbackPriority.h
+ * https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/text/CharacterEmoji.cpp
+ * https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/fonts/SymbolsIterator.cpp
+ *
+ * // Copyright 2015 The Chromium Authors. All rights reserved.
+ * // Use of this source code is governed by a BSD-style license that can be
+ * // found in the LICENSE file.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include "pango-emoji-private.h"
+#include "pango-emoji-table.h"
+
+
+static int
+interval_compare (const void *key, const void *elt)
+{
+ 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;
+}
+
+#define DEFINE_pango_Is_(name) \
+static 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; \
+}
+
+DEFINE_pango_Is_(Emoji)
+DEFINE_pango_Is_(Emoji_Presentation)
+DEFINE_pango_Is_(Emoji_Modifier)
+DEFINE_pango_Is_(Emoji_Modifier_Base)
+
+
+static gboolean
+_pango_Is_Emoji_Text_Default (gunichar ch)
+{
+ return _pango_Is_Emoji (ch) && !_pango_Is_Emoji_Presentation (ch);
+}
+
+static gboolean
+_pango_Is_Emoji_Emoji_Default (gunichar ch)
+{
+ return _pango_Is_Emoji_Presentation (ch);
+}
+
+static gboolean
+_pango_Is_Emoji_Keycap_Base (gunichar ch)
+{
+ return (ch >= '0' && ch <= '9') || ch == '#' || ch == '*';
+}
+
+static gboolean
+_pango_Is_Regional_Indicator (gunichar ch)
+{
+ return (ch >= 0x1F1E6 && ch <= 0x1F1FF);
+}
+
+
+const gunichar kCombiningEnclosingCircleBackslashCharacter = 0x20E0;
+const gunichar kCombiningEnclosingKeycapCharacter = 0x20E3;
+const gunichar kEyeCharacter = 0x1F441;
+const gunichar kFemaleSignCharacter = 0x2640;
+const gunichar kLeftSpeechBubbleCharacter = 0x1F5E8;
+const gunichar kMaleSignCharacter = 0x2642;
+const gunichar kRainbowCharacter = 0x1F308;
+const gunichar kStaffOfAesculapiusCharacter = 0x2695;
+const gunichar kVariationSelector15Character = 0xFE0E;
+const gunichar kVariationSelector16Character = 0xFE0F;
+const gunichar kWavingWhiteFlagCharacter = 0x1F3F3;
+const gunichar kZeroWidthJoinerCharacter = 0x200D;
+
+
+typedef enum {
+ PANGO_EMOJI_TYPE_INVALID,
+ PANGO_EMOJI_TYPE_TEXT, /* For regular non-symbols text */
+ PANGO_EMOJI_TYPE_EMOJI_TEXT, /* For emoji in text presentaiton */
+ PANGO_EMOJI_TYPE_EMOJI_EMOJI /* For emoji in emoji presentation */
+} PangoEmojiType;
+
+static PangoEmojiType
+_pango_get_emoji_type (gunichar codepoint)
+{
+ /* Those should only be Emoji presentation as combinations of two. */
+ if (_pango_Is_Emoji_Keycap_Base (codepoint) ||
+ _pango_Is_Regional_Indicator (codepoint))
+ return PANGO_EMOJI_TYPE_TEXT;
+
+ if (codepoint == kCombiningEnclosingKeycapCharacter)
+ return PANGO_EMOJI_TYPE_EMOJI_EMOJI;
+
+ if (_pango_Is_Emoji_Emoji_Default (codepoint) ||
+ _pango_Is_Emoji_Modifier_Base (codepoint) ||
+ _pango_Is_Emoji_Modifier (codepoint))
+ return PANGO_EMOJI_TYPE_EMOJI_EMOJI;
+
+ if (_pango_Is_Emoji_Text_Default (codepoint))
+ return PANGO_EMOJI_TYPE_EMOJI_TEXT;
+
+ return PANGO_EMOJI_TYPE_TEXT;
+}
+
+
+PangoEmojiIter *
+_pango_emoji_iter_init (PangoEmojiIter *iter,
+ const char *text,
+ int length)
+{
+ iter->text_start = text;
+ if (length >= 0)
+ iter->text_end = text + length;
+ else
+ iter->text_end = text + strlen (text);
+
+ iter->start = text;
+ iter->end = text;
+ iter->is_emoji = FALSE;
+
+ _pango_emoji_iter_next (iter);
+
+ return iter;
+}
+
+void
+_pango_emoji_iter_fini (PangoEmojiIter *iter)
+{
+}
+
+#define PANGO_EMOJI_TYPE_IS_EMOJI(typ) ((typ) == PANGO_EMOJI_TYPE_EMOJI_EMOJI)
+
+gboolean
+_pango_emoji_iter_next (PangoEmojiIter *iter)
+{
+ PangoEmojiType current_emoji_type = PANGO_EMOJI_TYPE_INVALID;
+
+ if (iter->end == iter->text_end)
+ return FALSE;
+
+ iter->start = iter->end;
+
+ for (; iter->end < iter->text_end; iter->end = g_utf8_next_char (iter->end))
+ {
+ gunichar ch = g_utf8_get_char (iter->end);
+
+ /* Except at the beginning, ZWJ just carries over the emoji or neutral
+ * text type, VS15 & VS16 we just carry over as well, since we already
+ * resolved those through lookahead. Also, don't downgrade to text
+ * 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) &&
+ ch != kVariationSelector15Character &&
+ ch != kVariationSelector16Character &&
+ ch != kCombiningEnclosingCircleBackslashCharacter &&
+ !_pango_Is_Regional_Indicator(ch) &&
+ !((ch == kLeftSpeechBubbleCharacter ||
+ ch == kRainbowCharacter ||
+ ch == kMaleSignCharacter ||
+ ch == kFemaleSignCharacter ||
+ ch == kStaffOfAesculapiusCharacter) &&
+ iter->is_emoji)) ||
+ current_emoji_type == PANGO_EMOJI_TYPE_INVALID) {
+ current_emoji_type = _pango_get_emoji_type (ch);
+ }
+
+ if (iter->end < iter->text_end)
+ {
+ gunichar peek_char = g_utf8_get_char (iter->end);
+
+ /* Variation Selectors */
+ if (current_emoji_type ==
+ PANGO_EMOJI_TYPE_EMOJI_EMOJI &&
+ peek_char == kVariationSelector15Character) {
+ current_emoji_type = PANGO_EMOJI_TYPE_EMOJI_TEXT;
+ }
+
+ if ((current_emoji_type ==
+ PANGO_EMOJI_TYPE_EMOJI_TEXT ||
+ _pango_Is_Emoji_Keycap_Base(ch)) &&
+ peek_char == kVariationSelector16Character) {
+ current_emoji_type = PANGO_EMOJI_TYPE_EMOJI_EMOJI;
+ }
+
+ /* Combining characters Keycap... */
+ if (_pango_Is_Emoji_Keycap_Base(ch) &&
+ peek_char == kCombiningEnclosingKeycapCharacter) {
+ current_emoji_type = PANGO_EMOJI_TYPE_EMOJI_EMOJI;
+ };
+
+ /* Regional indicators */
+ if (_pango_Is_Regional_Indicator(ch) &&
+ _pango_Is_Regional_Indicator(peek_char)) {
+ current_emoji_type = PANGO_EMOJI_TYPE_EMOJI_EMOJI;
+ }
+
+ /* Upgrade text presentation emoji to emoji presentation when followed by
+ * ZWJ, Example U+1F441 U+200D U+1F5E8, eye + ZWJ + left speech bubble. */
+ if ((ch == kEyeCharacter ||
+ ch == kWavingWhiteFlagCharacter) &&
+ peek_char == kZeroWidthJoinerCharacter) {
+ current_emoji_type = PANGO_EMOJI_TYPE_EMOJI_EMOJI;
+ }
+ }
+
+ if (iter->is_emoji != PANGO_EMOJI_TYPE_IS_EMOJI (current_emoji_type) && iter->start != iter->text_start)
+ {
+ iter->is_emoji = PANGO_EMOJI_TYPE_IS_EMOJI (current_emoji_type);
+ return TRUE;
+ }
+ }
+
+ iter->is_emoji = PANGO_EMOJI_TYPE_IS_EMOJI (current_emoji_type);
+
+ return TRUE;
+}
+
+
+/**********************************************************
+ * End of code from Chromium
+ **********************************************************/
diff --git a/tools/Makefile.am b/tools/Makefile.am
index eb34f31f..83d243f2 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -12,6 +12,7 @@ EXTRA_PROGRAMS = \
EXTRA_DIST= \
gen-color-table.pl \
+ gen-emoji-table.py \
rgb.txt
gen_script_for_lang_SOURCES = gen-script-for-lang.c
diff --git a/tools/gen-emoji-table.py b/tools/gen-emoji-table.py
new file mode 100755
index 00000000..600fe80f
--- /dev/null
+++ b/tools/gen-emoji-table.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+
+from __future__ import print_function, division, absolute_import
+import sys
+import os.path
+from collections import OrderedDict
+
+if len (sys.argv) != 2:
+ print("usage: ./gen-emoji-table.py emoji-data.txt", file=sys.stderr)
+ sys.exit (1)
+
+f = open(sys.argv[1])
+header = [f.readline () for _ in range(10)]
+
+sets = OrderedDict()
+for line in f.readlines():
+ line = line.strip()
+ if not line or line[0] == '#':
+ continue
+ rang, typ = [s.strip() for s in line.split('#')[0].split(';')[:2]]
+
+ rang = [int(s, 16) for s in rang.split('..')]
+ if len(rang) > 1:
+ start, end = rang
+ else:
+ start = end = rang[0]
+
+ if typ not in sets:
+ sets[typ] = set()
+ sets[typ].add((start, end))
+
+
+
+print("/* == Start of generated table == */")
+print("/*")
+print(" * The following tables are generated by running:")
+print(" *")
+print(" * ./gen-emoji-table.py emoji-data.txt")
+print(" *")
+print(" * on file with this header:")
+print(" *")
+for l in header:
+ print(" * %s" % (l.strip()))
+print(" */")
+print()
+print("#ifndef PANGO_EMOJI_TABLE_H")
+print("#define PANGO_EMOJI_TABLE_H")
+print()
+print("#include <glib.h>")
+print()
+print("struct Interval {\n gunichar start, end;\n};")
+
+for typ,s in sets.items():
+ print()
+ print("static const struct Interval _pango_%s_table[] =" % typ)
+ print("{")
+ for pair in sorted(s):
+ print(" {0x%04X, 0x%04X}," % pair)
+ print("};")
+
+print()
+print("#endif /* PANGO_EMOJI_TABLE_H */")
+print()
+print("/* == End of generated table == */")