summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'BuildTools/EmojisGenerator')
-rw-r--r--BuildTools/EmojisGenerator/EmojiMapper.cpp79
-rw-r--r--BuildTools/EmojisGenerator/generate.js100
-rw-r--r--BuildTools/EmojisGenerator/package.json7
3 files changed, 186 insertions, 0 deletions
diff --git a/BuildTools/EmojisGenerator/EmojiMapper.cpp b/BuildTools/EmojisGenerator/EmojiMapper.cpp
new file mode 100644
index 0000000..be1c811
--- /dev/null
+++ b/BuildTools/EmojisGenerator/EmojiMapper.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016-2017 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <SwifTools/EmojiMapper.h>
+
+#include <string>
+#include <unordered_map>
+
+namespace Swift {
+
+ //AUTO-GENERATED CONTENT
+ <%= mapping %>
+
+ std::vector<std::string> EmojiMapper::getCategories() {
+ std::vector<std::string> categories;
+ for (const auto& keyValuePair : emojisInCategory) {
+ categories.push_back(keyValuePair.first);
+ }
+ return categories;
+ }
+
+ std::string EmojiMapper::shortnameToUnicode(const std::string& shortname) {
+ auto unicodeSequenceIterator = shortnameUnicode.find(shortname);
+ if (unicodeSequenceIterator != shortnameUnicode.end()) {
+ return unicodeSequenceIterator->second;
+ }
+ else {
+ return std::string();
+ }
+ }
+
+ std::string EmojiMapper::unicodeToShortname(const std::string& unicode) {
+ auto shortnameIterator = unicodeShortname.find(unicode);
+ if (shortnameIterator != unicodeShortname.end()) {
+ return shortnameIterator->second;
+ }
+ else {
+ return std::string();
+ }
+ }
+
+ std::vector<std::string> EmojiMapper::categoryNameToEmojis(const std::string& categoryName) {
+ auto emojiIterator = emojisInCategory.find(categoryName);
+ if (emojiIterator != emojisInCategory.end()) {
+ return emojiIterator->second;
+ }
+ else {
+ return std::vector<std::string>();
+ }
+ }
+
+ std::string EmojiMapper::categoryToFlagshipUnicodeEmoji(const std::string& category) {
+ if (category == "recent") {
+ return shortnameToUnicode(":clock3:");
+ } else if (category == "people") {
+ return shortnameToUnicode(":smiley:");
+ } else if (category == "nature" ) {
+ return shortnameToUnicode(":dog:");
+ } else if (category == "food") {
+ return shortnameToUnicode(":apple:");
+ } else if (category == "activity") {
+ return shortnameToUnicode(":soccer:");
+ } else if (category == "travel") {
+ return shortnameToUnicode(":red_car:");
+ } else if (category == "objects") {
+ return shortnameToUnicode(":bulb:");
+ } else if (category == "symbols") {
+ return shortnameToUnicode(":heavy_division_sign:");
+ } else if (category == "regional") {
+ return shortnameToUnicode(":regional_indicator_a:");
+ } else if (category == "flags") {
+ return shortnameToUnicode(":flag_white:");
+ }
+ return std::string();
+ }
+}
diff --git a/BuildTools/EmojisGenerator/generate.js b/BuildTools/EmojisGenerator/generate.js
new file mode 100644
index 0000000..2b5541f
--- /dev/null
+++ b/BuildTools/EmojisGenerator/generate.js
@@ -0,0 +1,100 @@
+var util = require("util"),
+ fs = require("fs"),
+ _ = require("underscore");
+
+// Load emojis
+var emojis = require("./emoji.json");
+
+var unicodeCodepointToByteArray = function (codepoint) {
+ var utf8 = unescape(encodeURIComponent(String.fromCodePoint(parseInt(codepoint, 16))));
+
+ var arr = [];
+ for (var i = 0; i < utf8.length; i++) {
+ arr.push(utf8.charCodeAt(i));
+ }
+ return arr;
+}
+
+var byteArrayToCStringLiteral = function (byteArray) {
+ var literalString = "";
+ for (var i = 0; i < byteArray.length; i++) {
+ literalString += "\\x" + byteArray[i].toString(16);
+ }
+ return literalString;
+}
+
+var mapping = '';
+// Generate C++ mapping for shortnameUnicode_
+mapping += 'const std::unordered_map<std::string, std::string> EmojiMapper::shortnameUnicode = std::unordered_map<std::string, std::string>{' + _(emojis).filter(function(data) {
+ // Only use emojis with 2 or less codepoints, as Qt's harfbuzz version
+ // has issues rendering those as a single glyph.
+ return data.unicode.split("-").length < 3;
+}).map(function(data) {
+ var shortname = data.shortname;
+ // Get codepoints
+ var codepoints = _(data.unicode.split("-")).map(function (code) {
+ //return "\\U" + "0".repeat(8-code.length) + code;
+ return byteArrayToCStringLiteral(unicodeCodepointToByteArray(code));
+ });
+
+ // .join('\\U0000200D') -> join characters with a zero width joiner, required by
+ // some emojis pattern (:family_mwg: for example)
+ // Currently do no join them by a ZWJ as it breaks rendering of a lot simple emojis
+ // like $EMOJI followed by skin tone modifier.
+ //return '{"' + shortname + '", "' + codepoints.join(byteArrayToCStringLiteral(unicodeCodepointToByteArray('200D'))) + '"}';
+ return '{"' + shortname + '", "' + codepoints.join("") + '"}';
+}).join(", ") + '};\n\n';
+
+// Generate C++ code for the reverse mapping (i.e. unicodeShortname_ )
+mapping += ' const std::unordered_map<std::string, std::string> EmojiMapper::unicodeShortname = [](){\n' +
+ ' std::unordered_map<std::string, std::string> unicodeSequenceToShortname;\n' +
+ ' const auto& shortnameToUnicodeMap = EmojiMapper::shortnameUnicode;\n' +
+ ' for (const auto& shortnameToUnicode : shortnameToUnicodeMap) {\n' +
+ ' unicodeSequenceToShortname[shortnameToUnicode.second] = shortnameToUnicode.first;\n' +
+ ' }\n' +
+ ' return unicodeSequenceToShortname;\n' +
+ ' }();\n\n';
+
+// Generate C++ mapping for categories
+var CategoryMapping = new Map();
+_(emojis).filter(function(data) {
+ // Only use emojis with 2 or less codepoints, as Qt's harfbuzz version
+ // has issues rendering those as a single glyph.
+ return data.unicode.split("-").length < 3;
+}).map(function(data, category) {
+ // Get codepoints
+ var codepoints = _(data.unicode.split("-")).map(function (code) {
+ //return "\\U" + "0".repeat(8-code.length) + code;
+ return byteArrayToCStringLiteral(unicodeCodepointToByteArray(code));
+ });
+ if (!CategoryMapping.has(data.category)) {
+ CategoryMapping = CategoryMapping.set(data.category, []);
+ }
+ //CategoryMapping.get(data.category).push(codepoints.join(byteArrayToCStringLiteral(unicodeCodepointToByteArray('200D'))));
+ // Currently do no join them by a ZWJ as it breaks rendering of a lot simple emojis
+ // like $EMOJI followed by skin tone modifier.
+ CategoryMapping.get(data.category).push(codepoints.join(""));
+ //return 'categories_["' + data.category + '"].push_back("' + codepoints.join('\\U0000200D') + '");';
+});
+
+mapping += ' const std::unordered_map<std::string, std::vector<std::string>> EmojiMapper::emojisInCategory = std::unordered_map<std::string, std::vector<std::string>>{';
+categoryMappings = [];
+for (var category of CategoryMapping.keys()) {
+ categoryMappings.push('{"' + category + '", {' + CategoryMapping.get(category).map(function (literal) {
+ return '"' + literal + '"';
+ }).join(', ') + '}}')
+}
+mapping += categoryMappings.join(', ');
+mapping += '};\n'
+
+mapping.replace(/^\s*\n/gm, '');
+
+// Generate C++ class from template
+var input = fs.readFileSync("./EmojiMapper.cpp");
+var output = _(input.toString()).template()({ mapping: mapping });
+
+// Write C++ class to file
+var output_path = "../../SwifTools/EmojiMapper.cpp";
+fs.writeFileSync(output_path, output);
+
+console.log("Generated " + output_path);
diff --git a/BuildTools/EmojisGenerator/package.json b/BuildTools/EmojisGenerator/package.json
new file mode 100644
index 0000000..8b719ba
--- /dev/null
+++ b/BuildTools/EmojisGenerator/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "emojione-android",
+ "version": "0.1.0",
+ "dependencies": {
+ "underscore": "^1.7.0"
+ }
+}