From ec2a1b3ddbd46bcf694b583caa2ee7b25f0f9cc6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 11 Dec 2018 11:17:19 +0400 Subject: [PATCH] Fix some missing emoji display. --- Telegram/SourceFiles/codegen/emoji/data.cpp | 157 +++++++++++++++----- 1 file changed, 119 insertions(+), 38 deletions(-) diff --git a/Telegram/SourceFiles/codegen/emoji/data.cpp b/Telegram/SourceFiles/codegen/emoji/data.cpp index ad7a807bf..b747654ac 100644 --- a/Telegram/SourceFiles/codegen/emoji/data.cpp +++ b/Telegram/SourceFiles/codegen/emoji/data.cpp @@ -1890,6 +1890,30 @@ InputCategory Category7 = { { 0xD83CDDFFU, 0xD83CDDFCU, }, }; +// Original data has those emoji only with gender symbols. +// But they should be displayed as emoji even without gender symbols. +// So we map which gender symbol to use for an emoji without one. +std::map WithoutGenderAliases = { + { { 0xD83EDDB8U, }, 0x2640U }, + { { 0xD83EDDB9U, }, 0x2640U }, + { { 0xD83EDDD9U, }, 0x2640U }, + { { 0xD83EDDDAU, }, 0x2640U }, + { { 0xD83EDDDBU, }, 0x2640U }, + { { 0xD83EDDDCU, }, 0x2642U }, + { { 0xD83EDDDDU, }, 0x2642U }, + { { 0xD83EDDDEU, }, 0x2642U }, + { { 0xD83EDDD6U, }, 0x2642U }, + { { 0xD83EDDD7U, }, 0x2640U }, + { { 0xD83EDDD8U, }, 0x2640U }, +}; + +// Some flags are sent as one string, but are rendered as a different too. +std::map FlagAliases = { + { { 0xD83CDDE8U, 0xD83CDDF5U, }, { 0xD83CDDEBU, 0xD83CDDF7U, } }, + { { 0xD83CDDE7U, 0xD83CDDFBU, }, { 0xD83CDDF3U, 0xD83CDDF4U, } }, + { { 0xD83CDDE6U, 0xD83CDDE8U, }, { 0xD83CDDF8U, 0xD83CDDEDU, } }, +}; + std::map Aliases; constexpr auto kErrorBadData = 401; @@ -2087,7 +2111,7 @@ bool AddItemBeforeItem(const InputId &add, const InputId &before) { return true; } -bool CheckOldInCurrent() { +bool CheckOldInCurrent(std::set variatedIds) { const auto categories = { &Category1, &Category2, @@ -2107,28 +2131,47 @@ bool CheckOldInCurrent() { &old::Category7, }; const auto genders = { 0x2640U, 0x2642U }; - const auto addGender = [&](const InputId &was, int index) { + const auto addGender = [](const InputId &was, uint32 gender) { auto result = was; result.push_back(0x200DU); - result.push_back(*(begin(genders) + index)); + result.push_back(gender); result.push_back(0xFE0FU); return result; }; + const auto addGenderByIndex = [&](const InputId &was, int index) { + return addGender(was, *(begin(genders) + index)); + }; + const auto find = []( + const InputCategory &list, + const InputId &id) { + return (std::find(begin(list), end(list), id) != end(list)); + }; + const auto findInMany = [&]( + auto &&list, + const InputId &id) { + for (const auto current : list) { + if (find(*current, id)) { + return true; + } + } + return false; + }; + const auto emplaceColoredAlias = [](const InputId &real, const InputId &alias, uint32_t color) { + if (real.size() < 2 || alias.size() < 2 || real[1] != Colors[0] || alias[1] != Colors[0]) { + return false; + } + auto key = real; + key[1] = color; + auto value = alias; + value[1] = color; + Aliases.emplace(BareIdFromInput(key), BareIdFromInput(value)); + return true; + }; auto result = true; for (auto c = begin(old); c != end(old); ++c) { const auto category = *c; for (auto i = begin(*category); i != end(*category); ++i) { - const auto find = []( - auto &&list, - const InputId &id) { - for (const auto current : list) { - if (std::find(begin(*current), end(*current), id) != end(*current)) { - return true; - } - } - return false; - }; - if (find(categories, *i)) { + if (findInMany(categories, *i)) { continue; } @@ -2136,7 +2179,7 @@ bool CheckOldInCurrent() { if (i->back() == 0xFE0FU) { auto other = *i; other.pop_back(); - if (find(categories, other)) { + if (findInMany(categories, other)) { continue; } } @@ -2145,7 +2188,7 @@ bool CheckOldInCurrent() { if (i->back() != 0xFE0FU) { auto other = *i; other.push_back(0xFE0FU); - if (find(categories, other)) { + if (findInMany(categories, other)) { continue; } } @@ -2158,7 +2201,7 @@ bool CheckOldInCurrent() { altered.push_back(0x200DU); altered.push_back(*g); altered.push_back(0xFE0FU); - if (find(old, altered)) { + if (findInMany(old, altered)) { return int(g - begin(genders)); } } @@ -2176,9 +2219,9 @@ bool CheckOldInCurrent() { } const auto genderIndex = (1 - otherGenderIndex); - const auto real = addGender(*i, genderIndex); + const auto real = addGenderByIndex(*i, genderIndex); const auto bare = BareIdFromInput(real); - if (!find(categories, real)) { + if (!findInMany(categories, real)) { common::logError(kErrorBadData, "input") << "Bad data: old emoji (category " << (c - begin(old)) @@ -2198,11 +2241,6 @@ bool CheckOldInCurrent() { } } for (auto i = begin(old::ColoredEmoji); i != end(old::ColoredEmoji); ++i) { - const auto find = []( - const InputCategory &list, - const InputId &id) { - return (std::find(begin(list), end(list), id) != end(list)); - }; if (find(ColoredEmoji, *i)) { continue; } @@ -2229,7 +2267,7 @@ bool CheckOldInCurrent() { } const auto genderIndex = (1 - otherGenderIndex); - const auto real = addGender(*i, genderIndex); + const auto real = addGenderByIndex(*i, genderIndex); const auto bare = BareIdFromInput(real); if (!find(ColoredEmoji, real)) { common::logError(kErrorBadData, "input") @@ -2245,19 +2283,8 @@ bool CheckOldInCurrent() { << "Bad data: two aliases for a gendered emoji."; result = false; } else { - const auto emplaceAlias = [&](uint32_t color) { - if (real.size() < 2 || i->size() < 2 || real[1] != Colors[0] || (*i)[1] != Colors[0]) { - return false; - } - auto key = real; - key[1] = color; - auto value = *i; - value[1] = color; - Aliases.emplace(BareIdFromInput(key), BareIdFromInput(value)); - return true; - }; for (const auto color : Colors) { - if (!emplaceAlias(color)) { + if (!emplaceColoredAlias(real, *i, color)) { common::logError(kErrorBadData, "input") << "Bad data: bad colored emoji."; result = false; @@ -2266,6 +2293,60 @@ bool CheckOldInCurrent() { } } } + + for (const auto [inputId, gender] : WithoutGenderAliases) { + if (findInMany(categories, inputId)) { + continue; + } + const auto real = [&] { + auto result = addGender(inputId, gender); + if (findInMany(categories, result)) { + return result; + } + result.push_back(kPostfix); + return result; + }(); + const auto bare = BareIdFromInput(real); + if (!findInMany(categories, real)) { + common::logError(kErrorBadData, "input") + << "Bad data: without gender alias not found with gender."; + result = false; + } else if (Aliases.find(bare) != end(Aliases)) { + common::logError(kErrorBadData, "input") + << "Bad data: two aliases for a gendered emoji."; + result = false; + } else { + Aliases.emplace(bare, BareIdFromInput(inputId)); + } + if (variatedIds.find(bare) != variatedIds.end()) { + auto colorReal = real; + colorReal.insert(colorReal.begin() + 1, Colors[0]); + auto colorInput = inputId; + colorInput.insert(colorInput.begin() + 1, Colors[0]); + for (const auto color : Colors) { + if (!emplaceColoredAlias(colorReal, colorInput, color)) { + common::logError(kErrorBadData, "input") + << "Bad data: bad colored emoji."; + result = false; + break; + } + } + + } + } + + for (const auto [inputId, real] : FlagAliases) { + const auto bare = BareIdFromInput(real); + if (Aliases.find(bare) != end(Aliases)) { + common::logError(kErrorBadData, "input") + << "Bad data: two aliases for a flag emoji."; + result = false; + } + else { + Aliases.emplace(bare, BareIdFromInput(inputId)); + } + } + return result; } @@ -2289,7 +2370,7 @@ Data PrepareData() { return Data(); } - if (!CheckOldInCurrent()) { + if (!CheckOldInCurrent(variatedIds)) { return Data(); }