Fix some missing emoji display.

This commit is contained in:
John Preston 2018-12-11 11:17:19 +04:00
parent 60711471fc
commit ec2a1b3ddb
1 changed files with 119 additions and 38 deletions

View File

@ -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<InputId, uint32> 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<InputId, InputId> FlagAliases = {
{ { 0xD83CDDE8U, 0xD83CDDF5U, }, { 0xD83CDDEBU, 0xD83CDDF7U, } },
{ { 0xD83CDDE7U, 0xD83CDDFBU, }, { 0xD83CDDF3U, 0xD83CDDF4U, } },
{ { 0xD83CDDE6U, 0xD83CDDE8U, }, { 0xD83CDDF8U, 0xD83CDDEDU, } },
};
std::map<Id, Id> 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<Id> 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();
}