diff options
Diffstat (limited to 'BuildTools/EmojisGenerator')
-rw-r--r-- | BuildTools/EmojisGenerator/EmojiMapper.cpp | 79 | ||||
-rw-r--r-- | BuildTools/EmojisGenerator/generate.js | 100 | ||||
-rw-r--r-- | BuildTools/EmojisGenerator/package.json | 7 |
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" + } +} |