fix: override broken base sizes & scales for some Twitch emotes (#5279)

This commit is contained in:
pajlada 2024-03-30 14:24:47 +01:00 committed by GitHub
parent 69bdac9936
commit 2f534dc6da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 398 additions and 11 deletions

View file

@ -104,6 +104,7 @@
- Bugfix: Fixed popup windows not persisting between restarts. (#5081) - Bugfix: Fixed popup windows not persisting between restarts. (#5081)
- Bugfix: Fixed splits not retaining their focus after minimizing. (#5080) - Bugfix: Fixed splits not retaining their focus after minimizing. (#5080)
- Bugfix: Fixed _Copy message_ copying the channel name in global search. (#5106) - Bugfix: Fixed _Copy message_ copying the channel name in global search. (#5106)
- Bugfix: Fixed some Twitch emotes sizes being wrong at certain zoom levels. (#5279)
- Bugfix: Fixed a missing space when the image uploader provided a delete link. (#5269) - Bugfix: Fixed a missing space when the image uploader provided a delete link. (#5269)
- Bugfix: Reply contexts now use the color of the replied-to message. (#5145) - Bugfix: Reply contexts now use the color of the replied-to message. (#5145)
- Bugfix: Fixed top-level window getting stuck after opening settings. (#5161, #5166) - Bugfix: Fixed top-level window getting stuck after opening settings. (#5161, #5166)

View file

@ -5,6 +5,400 @@
#include "messages/Image.hpp" #include "messages/Image.hpp"
#include "util/QStringHash.hpp" #include "util/QStringHash.hpp"
namespace {
using namespace chatterino;
Url getEmoteLink(const EmoteId &id, const QString &emoteScale)
{
return {QString(TWITCH_EMOTE_TEMPLATE)
.replace("{id}", id.string)
.replace("{scale}", emoteScale)};
}
QSize getEmoteExpectedBaseSize(const EmoteId &id)
{
// From Twitch docs - expected size for an emote (1x)
constexpr QSize defaultBaseSize(28, 28);
static std::unordered_map<QString, QSize> outliers{
{"555555635", {21, 18}}, /* ;p */
{"555555636", {21, 18}}, /* ;-p */
{"555555614", {21, 18}}, /* O_o */
{"555555641", {21, 18}}, /* :z */
{"555555604", {21, 18}}, /* :\\ */
{"444", {21, 18}}, /* :| */
{"555555634", {21, 18}}, /* ;-P */
{"439", {21, 18}}, /* ;) */
{"555555642", {21, 18}}, /* :-z */
{"555555613", {21, 18}}, /* :-o */
{"555555625", {21, 18}}, /* :-p */
{"433", {21, 18}}, /* :/ */
{"555555622", {21, 18}}, /* :P */
{"555555640", {21, 18}}, /* :-| */
{"555555623", {21, 18}}, /* :-P */
{"555555628", {21, 18}}, /* :) */
{"555555632", {21, 18}}, /* 8-) */
{"555555667", {20, 18}}, /* ;p */
{"445", {21, 18}}, /* <3 */
{"555555668", {20, 18}}, /* ;-p */
{"555555679", {20, 18}}, /* :z */
{"483", {20, 18}}, /* <3 */
{"555555666", {20, 18}}, /* ;-P */
{"497", {20, 18}}, /* O_o */
{"555555664", {20, 18}}, /* :-p */
{"555555671", {20, 18}}, /* :o */
{"555555681", {20, 18}}, /* :Z */
{"555555672", {20, 18}}, /* :-o */
{"555555676", {20, 18}}, /* :-\\ */
{"555555611", {21, 18}}, /* :-O */
{"555555670", {20, 18}}, /* :-O */
{"555555688", {20, 18}}, /* :-D */
{"441", {21, 18}}, /* B) */
{"555555601", {21, 18}}, /* >( */
{"491", {20, 18}}, /* ;P */
{"496", {20, 18}}, /* :D */
{"492", {20, 18}}, /* :O */
{"555555573", {24, 18}}, /* o_O */
{"555555643", {21, 18}}, /* :Z */
{"1898", {26, 28}}, /* ThunBeast */
{"555555682", {20, 18}}, /* :-Z */
{"1896", {20, 30}}, /* WholeWheat */
{"1906", {24, 30}}, /* SoBayed */
{"555555607", {21, 18}}, /* :-( */
{"555555660", {20, 18}}, /* :-( */
{"489", {20, 18}}, /* :( */
{"495", {20, 18}}, /* :s */
{"555555638", {21, 18}}, /* :-D */
{"357", {28, 30}}, /* HotPokket */
{"555555624", {21, 18}}, /* :p */
{"73", {21, 30}}, /* DBstyle */
{"555555674", {20, 18}}, /* :-/ */
{"555555629", {21, 18}}, /* :-) */
{"555555600", {24, 18}}, /* R-) */
{"41", {19, 27}}, /* Kreygasm */
{"555555612", {21, 18}}, /* :o */
{"488", {29, 24}}, /* :7 */
{"69", {41, 28}}, /* BloodTrail */
{"555555608", {21, 18}}, /* R) */
{"501", {20, 18}}, /* ;) */
{"50", {18, 27}}, /* ArsonNoSexy */
{"443", {21, 18}}, /* :D */
{"1904", {24, 30}}, /* BigBrother */
{"555555595", {24, 18}}, /* ;P */
{"555555663", {20, 18}}, /* :p */
{"555555576", {24, 18}}, /* o.o */
{"360", {22, 30}}, /* FailFish */
{"500", {20, 18}}, /* B) */
{"3", {24, 18}}, /* :D */
{"484", {20, 22}}, /* R) */
{"555555678", {20, 18}}, /* :-| */
{"7", {24, 18}}, /* B) */
{"52", {32, 32}}, /* SMOrc */
{"555555644", {21, 18}}, /* :-Z */
{"18", {20, 27}}, /* TheRinger */
{"49106", {27, 28}}, /* CorgiDerp */
{"6", {24, 18}}, /* O_o */
{"10", {24, 18}}, /* :/ */
{"47", {24, 24}}, /* PunchTrees */
{"555555561", {24, 18}}, /* :-D */
{"555555564", {24, 18}}, /* :-| */
{"13", {24, 18}}, /* ;P */
{"555555593", {24, 18}}, /* :p */
{"555555589", {24, 18}}, /* ;) */
{"555555590", {24, 18}}, /* ;-) */
{"486", {27, 42}}, /* :> */
{"40", {21, 27}}, /* KevinTurtle */
{"555555558", {24, 18}}, /* :( */
{"555555597", {24, 18}}, /* ;p */
{"555555580", {24, 18}}, /* :O */
{"555555567", {24, 18}}, /* :Z */
{"1", {24, 18}}, /* :) */
{"11", {24, 18}}, /* ;) */
{"33", {25, 32}}, /* DansGame */
{"555555586", {24, 18}}, /* :-/ */
{"4", {24, 18}}, /* >( */
{"555555588", {24, 18}}, /* :-\\ */
{"12", {24, 18}}, /* :P */
{"555555563", {24, 18}}, /* :| */
{"555555581", {24, 18}}, /* :-O */
{"555555598", {24, 18}}, /* ;-p */
{"555555596", {24, 18}}, /* ;-P */
{"555555557", {24, 18}}, /* :-) */
{"498", {20, 18}}, /* >( */
{"555555680", {20, 18}}, /* :-z */
{"555555587", {24, 18}}, /* :\\ */
{"5", {24, 18}}, /* :| */
{"354", {20, 30}}, /* 4Head */
{"555555562", {24, 18}}, /* >( */
{"555555594", {24, 18}}, /* :-p */
{"490", {20, 18}}, /* :P */
{"555555662", {20, 18}}, /* :-P */
{"2", {24, 18}}, /* :( */
{"1902", {27, 29}}, /* Keepo */
{"555555627", {21, 18}}, /* ;-) */
{"555555566", {24, 18}}, /* :-z */
{"555555559", {24, 18}}, /* :-( */
{"555555592", {24, 18}}, /* :-P */
{"28", {39, 27}}, /* MrDestructoid */
{"8", {24, 18}}, /* :O */
{"244", {24, 30}}, /* FUNgineer */
{"555555591", {24, 18}}, /* :P */
{"555555585", {24, 18}}, /* :/ */
{"494", {20, 18}}, /* :| */
{"9", {24, 18}}, /* <3 */
{"555555584", {24, 18}}, /* <3 */
{"555555579", {24, 18}}, /* 8-) */
{"14", {24, 18}}, /* R) */
{"485", {27, 18}}, /* #/ */
{"555555560", {24, 18}}, /* :D */
{"86", {36, 30}}, /* BibleThump */
{"555555578", {24, 18}}, /* B-) */
{"17", {20, 27}}, /* StoneLightning */
{"436", {21, 18}}, /* :O */
{"555555675", {20, 18}}, /* :\\ */
{"22", {19, 27}}, /* RedCoat */
{"555555574", {24, 18}}, /* o.O */
{"555555603", {21, 18}}, /* :-/ */
{"1901", {24, 28}}, /* Kippa */
{"15", {21, 27}}, /* JKanStyle */
{"555555605", {21, 18}}, /* :-\\ */
{"555555701", {20, 18}}, /* ;-) */
{"487", {20, 42}}, /* <] */
{"555555572", {24, 18}}, /* O.O */
{"65", {40, 30}}, /* FrankerZ */
{"25", {25, 28}}, /* Kappa */
{"36", {36, 30}}, /* PJSalt */
{"499", {20, 18}}, /* :) */
{"555555565", {24, 18}}, /* :z */
{"434", {21, 18}}, /* :( */
{"555555577", {24, 18}}, /* B) */
{"34", {21, 28}}, /* SwiftRage */
{"555555575", {24, 18}}, /* o_o */
{"92", {23, 30}}, /* PMSTwin */
{"555555570", {24, 18}}, /* O.o */
{"555555569", {24, 18}}, /* O_o */
{"493", {20, 18}}, /* :/ */
{"26", {20, 27}}, /* JonCarnage */
{"66", {20, 27}}, /* OneHand */
{"555555568", {24, 18}}, /* :-Z */
{"555555599", {24, 18}}, /* R) */
{"1900", {33, 30}}, /* RalpherZ */
{"555555582", {24, 18}}, /* :o */
{"1899", {22, 30}}, /* TF2John */
{"555555633", {21, 18}}, /* ;P */
{"16", {22, 27}}, /* OptimizePrime */
{"30", {29, 27}}, /* BCWarrior */
{"555555583", {24, 18}}, /* :-o */
{"32", {21, 27}}, /* GingerPower */
{"87", {24, 30}}, /* ShazBotstix */
{"74", {24, 30}}, /* AsianGlow */
{"555555571", {24, 18}}, /* O_O */
{"46", {24, 24}}, /* SSSsss */
};
auto it = outliers.find(id.string);
if (it != outliers.end())
{
return it->second;
}
return defaultBaseSize;
}
qreal getEmote3xScaleFactor(const EmoteId &id)
{
// From Twitch docs - expected size for an emote (1x)
constexpr qreal default3xScaleFactor = 0.25;
static std::unordered_map<QString, qreal> outliers{
{"555555635", 0.3333333333333333}, /* ;p */
{"555555636", 0.3333333333333333}, /* ;-p */
{"555555614", 0.3333333333333333}, /* O_o */
{"555555641", 0.3333333333333333}, /* :z */
{"555555604", 0.3333333333333333}, /* :\\ */
{"444", 0.3333333333333333}, /* :| */
{"555555634", 0.3333333333333333}, /* ;-P */
{"439", 0.3333333333333333}, /* ;) */
{"555555642", 0.3333333333333333}, /* :-z */
{"555555613", 0.3333333333333333}, /* :-o */
{"555555625", 0.3333333333333333}, /* :-p */
{"433", 0.3333333333333333}, /* :/ */
{"555555622", 0.3333333333333333}, /* :P */
{"555555640", 0.3333333333333333}, /* :-| */
{"555555623", 0.3333333333333333}, /* :-P */
{"555555628", 0.3333333333333333}, /* :) */
{"555555632", 0.3333333333333333}, /* 8-) */
{"555555667", 0.3333333333333333}, /* ;p */
{"445", 0.3333333333333333}, /* <3 */
{"555555668", 0.3333333333333333}, /* ;-p */
{"555555679", 0.3333333333333333}, /* :z */
{"483", 0.3333333333333333}, /* <3 */
{"555555666", 0.3333333333333333}, /* ;-P */
{"497", 0.3333333333333333}, /* O_o */
{"555555664", 0.3333333333333333}, /* :-p */
{"555555671", 0.3333333333333333}, /* :o */
{"555555681", 0.3333333333333333}, /* :Z */
{"555555672", 0.3333333333333333}, /* :-o */
{"555555676", 0.3333333333333333}, /* :-\\ */
{"555555611", 0.3333333333333333}, /* :-O */
{"555555670", 0.3333333333333333}, /* :-O */
{"555555688", 0.3333333333333333}, /* :-D */
{"441", 0.3333333333333333}, /* B) */
{"555555601", 0.3333333333333333}, /* >( */
{"491", 0.3333333333333333}, /* ;P */
{"496", 0.3333333333333333}, /* :D */
{"492", 0.3333333333333333}, /* :O */
{"555555573", 0.3333333333333333}, /* o_O */
{"555555643", 0.3333333333333333}, /* :Z */
{"1898", 0.3333333333333333}, /* ThunBeast */
{"555555682", 0.3333333333333333}, /* :-Z */
{"1896", 0.3333333333333333}, /* WholeWheat */
{"1906", 0.3333333333333333}, /* SoBayed */
{"555555607", 0.3333333333333333}, /* :-( */
{"555555660", 0.3333333333333333}, /* :-( */
{"489", 0.3333333333333333}, /* :( */
{"495", 0.3333333333333333}, /* :s */
{"555555638", 0.3333333333333333}, /* :-D */
{"357", 0.3333333333333333}, /* HotPokket */
{"555555624", 0.3333333333333333}, /* :p */
{"73", 0.3333333333333333}, /* DBstyle */
{"555555674", 0.3333333333333333}, /* :-/ */
{"555555629", 0.3333333333333333}, /* :-) */
{"555555600", 0.3333333333333333}, /* R-) */
{"41", 0.3333333333333333}, /* Kreygasm */
{"555555612", 0.3333333333333333}, /* :o */
{"488", 0.3333333333333333}, /* :7 */
{"69", 0.3333333333333333}, /* BloodTrail */
{"555555608", 0.3333333333333333}, /* R) */
{"501", 0.3333333333333333}, /* ;) */
{"50", 0.3333333333333333}, /* ArsonNoSexy */
{"443", 0.3333333333333333}, /* :D */
{"1904", 0.3333333333333333}, /* BigBrother */
{"555555595", 0.3333333333333333}, /* ;P */
{"555555663", 0.3333333333333333}, /* :p */
{"555555576", 0.3333333333333333}, /* o.o */
{"360", 0.3333333333333333}, /* FailFish */
{"500", 0.3333333333333333}, /* B) */
{"3", 0.3333333333333333}, /* :D */
{"484", 0.3333333333333333}, /* R) */
{"555555678", 0.3333333333333333}, /* :-| */
{"7", 0.3333333333333333}, /* B) */
{"52", 0.3333333333333333}, /* SMOrc */
{"555555644", 0.3333333333333333}, /* :-Z */
{"18", 0.3333333333333333}, /* TheRinger */
{"49106", 0.3333333333333333}, /* CorgiDerp */
{"6", 0.3333333333333333}, /* O_o */
{"10", 0.3333333333333333}, /* :/ */
{"47", 0.3333333333333333}, /* PunchTrees */
{"555555561", 0.3333333333333333}, /* :-D */
{"555555564", 0.3333333333333333}, /* :-| */
{"13", 0.3333333333333333}, /* ;P */
{"555555593", 0.3333333333333333}, /* :p */
{"555555589", 0.3333333333333333}, /* ;) */
{"555555590", 0.3333333333333333}, /* ;-) */
{"486", 0.3333333333333333}, /* :> */
{"40", 0.3333333333333333}, /* KevinTurtle */
{"555555558", 0.3333333333333333}, /* :( */
{"555555597", 0.3333333333333333}, /* ;p */
{"555555580", 0.3333333333333333}, /* :O */
{"555555567", 0.3333333333333333}, /* :Z */
{"1", 0.3333333333333333}, /* :) */
{"11", 0.3333333333333333}, /* ;) */
{"33", 0.3333333333333333}, /* DansGame */
{"555555586", 0.3333333333333333}, /* :-/ */
{"4", 0.3333333333333333}, /* >( */
{"555555588", 0.3333333333333333}, /* :-\\ */
{"12", 0.3333333333333333}, /* :P */
{"555555563", 0.3333333333333333}, /* :| */
{"555555581", 0.3333333333333333}, /* :-O */
{"555555598", 0.3333333333333333}, /* ;-p */
{"555555596", 0.3333333333333333}, /* ;-P */
{"555555557", 0.3333333333333333}, /* :-) */
{"498", 0.3333333333333333}, /* >( */
{"555555680", 0.3333333333333333}, /* :-z */
{"555555587", 0.3333333333333333}, /* :\\ */
{"5", 0.3333333333333333}, /* :| */
{"354", 0.3333333333333333}, /* 4Head */
{"555555562", 0.3333333333333333}, /* >( */
{"555555594", 0.3333333333333333}, /* :-p */
{"490", 0.3333333333333333}, /* :P */
{"555555662", 0.3333333333333333}, /* :-P */
{"2", 0.3333333333333333}, /* :( */
{"1902", 0.3333333333333333}, /* Keepo */
{"555555627", 0.3333333333333333}, /* ;-) */
{"555555566", 0.3333333333333333}, /* :-z */
{"555555559", 0.3333333333333333}, /* :-( */
{"555555592", 0.3333333333333333}, /* :-P */
{"28", 0.3333333333333333}, /* MrDestructoid */
{"8", 0.3333333333333333}, /* :O */
{"244", 0.3333333333333333}, /* FUNgineer */
{"555555591", 0.3333333333333333}, /* :P */
{"555555585", 0.3333333333333333}, /* :/ */
{"494", 0.3333333333333333}, /* :| */
{"9", 0.21428571428571427}, /* <3 */
{"555555584", 0.21428571428571427}, /* <3 */
{"555555579", 0.3333333333333333}, /* 8-) */
{"14", 0.3333333333333333}, /* R) */
{"485", 0.3333333333333333}, /* #/ */
{"555555560", 0.3333333333333333}, /* :D */
{"86", 0.3333333333333333}, /* BibleThump */
{"555555578", 0.3333333333333333}, /* B-) */
{"17", 0.3333333333333333}, /* StoneLightning */
{"436", 0.3333333333333333}, /* :O */
{"555555675", 0.3333333333333333}, /* :\\ */
{"22", 0.3333333333333333}, /* RedCoat */
{"245", 0.3333333333333333}, /* ResidentSleeper */
{"555555574", 0.3333333333333333}, /* o.O */
{"555555603", 0.3333333333333333}, /* :-/ */
{"1901", 0.3333333333333333}, /* Kippa */
{"15", 0.3333333333333333}, /* JKanStyle */
{"555555605", 0.3333333333333333}, /* :-\\ */
{"555555701", 0.3333333333333333}, /* ;-) */
{"487", 0.3333333333333333}, /* <] */
{"22639", 0.3333333333333333}, /* BabyRage */
{"555555572", 0.3333333333333333}, /* O.O */
{"65", 0.3333333333333333}, /* FrankerZ */
{"25", 0.3333333333333333}, /* Kappa */
{"36", 0.3333333333333333}, /* PJSalt */
{"499", 0.3333333333333333}, /* :) */
{"555555565", 0.3333333333333333}, /* :z */
{"434", 0.3333333333333333}, /* :( */
{"555555577", 0.3333333333333333}, /* B) */
{"34", 0.3333333333333333}, /* SwiftRage */
{"555555575", 0.3333333333333333}, /* o_o */
{"92", 0.3333333333333333}, /* PMSTwin */
{"555555570", 0.3333333333333333}, /* O.o */
{"555555569", 0.3333333333333333}, /* O_o */
{"493", 0.3333333333333333}, /* :/ */
{"26", 0.3333333333333333}, /* JonCarnage */
{"66", 0.3333333333333333}, /* OneHand */
{"973", 0.3333333333333333}, /* DAESuppy */
{"555555568", 0.3333333333333333}, /* :-Z */
{"555555599", 0.3333333333333333}, /* R) */
{"1900", 0.3333333333333333}, /* RalpherZ */
{"555555582", 0.3333333333333333}, /* :o */
{"1899", 0.3333333333333333}, /* TF2John */
{"555555633", 0.3333333333333333}, /* ;P */
{"16", 0.3333333333333333}, /* OptimizePrime */
{"30", 0.3333333333333333}, /* BCWarrior */
{"555555583", 0.3333333333333333}, /* :-o */
{"32", 0.3333333333333333}, /* GingerPower */
{"87", 0.3333333333333333}, /* ShazBotstix */
{"74", 0.3333333333333333}, /* AsianGlow */
{"555555571", 0.3333333333333333}, /* O_O */
{"46", 0.3333333333333333}, /* SSSsss */
};
auto it = outliers.find(id.string);
if (it != outliers.end())
{
return it->second;
}
return default3xScaleFactor;
}
} // namespace
namespace chatterino { namespace chatterino {
QString TwitchEmotes::cleanUpEmoteCode(const QString &dirtyEmoteCode) QString TwitchEmotes::cleanUpEmoteCode(const QString &dirtyEmoteCode)
@ -44,14 +438,14 @@ EmotePtr TwitchEmotes::getOrCreateEmote(const EmoteId &id,
if (!shared) if (!shared)
{ {
// From Twitch docs - expected size for an emote (1x) auto baseSize = getEmoteExpectedBaseSize(id);
constexpr QSize baseSize(28, 28);
(*cache)[id] = shared = std::make_shared<Emote>(Emote{ (*cache)[id] = shared = std::make_shared<Emote>(Emote{
EmoteName{name}, EmoteName{name},
ImageSet{ ImageSet{
Image::fromUrl(getEmoteLink(id, "1.0"), 1, baseSize), Image::fromUrl(getEmoteLink(id, "1.0"), 1, baseSize),
Image::fromUrl(getEmoteLink(id, "2.0"), 0.5, baseSize * 2), Image::fromUrl(getEmoteLink(id, "2.0"), 0.5, baseSize * 2),
Image::fromUrl(getEmoteLink(id, "3.0"), 0.25, baseSize * 4), Image::fromUrl(getEmoteLink(id, "3.0"),
getEmote3xScaleFactor(id), baseSize * 4),
}, },
Tooltip{name.toHtmlEscaped() + "<br>Twitch Emote"}, Tooltip{name.toHtmlEscaped() + "<br>Twitch Emote"},
}); });
@ -60,11 +454,4 @@ EmotePtr TwitchEmotes::getOrCreateEmote(const EmoteId &id,
return shared; return shared;
} }
Url TwitchEmotes::getEmoteLink(const EmoteId &id, const QString &emoteScale)
{
return {QString(TWITCH_EMOTE_TEMPLATE)
.replace("{id}", id.string)
.replace("{scale}", emoteScale)};
}
} // namespace chatterino } // namespace chatterino

View file

@ -52,7 +52,6 @@ public:
const EmoteName &name) override; const EmoteName &name) override;
private: private:
Url getEmoteLink(const EmoteId &id, const QString &emoteScale);
UniqueAccess<std::unordered_map<EmoteId, std::weak_ptr<Emote>>> UniqueAccess<std::unordered_map<EmoteId, std::weak_ptr<Emote>>>
twitchEmotesCache_; twitchEmotesCache_;
}; };