diff options
Diffstat (limited to 'libs/minikin/FontCollection.cpp')
-rw-r--r-- | libs/minikin/FontCollection.cpp | 64 |
1 files changed, 55 insertions, 9 deletions
diff --git a/libs/minikin/FontCollection.cpp b/libs/minikin/FontCollection.cpp index 75cbd76..b1b0aaf 100644 --- a/libs/minikin/FontCollection.cpp +++ b/libs/minikin/FontCollection.cpp @@ -37,6 +37,42 @@ static inline T max(T a, T b) { return a>b ? a : b; } +const uint32_t EMOJI_STYLE_VS = 0xFE0F; +const uint32_t TEXT_STYLE_VS = 0xFE0E; + +// See http://www.unicode.org/Public/9.0.0/ucd/StandardizedVariants-9.0.0d1.txt +// Must be sorted. +const uint32_t EMOJI_STYLE_VS_BASES[] = { + 0x0023, 0x002A, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, + 0x00A9, 0x00AE, 0x203C, 0x2049, 0x2122, 0x2139, 0x2194, 0x2195, 0x2196, 0x2197, 0x2198, 0x2199, + 0x21A9, 0x21AA, 0x231A, 0x231B, 0x2328, 0x23CF, 0x23ED, 0x23EE, 0x23EF, 0x23F1, 0x23F2, 0x23F8, + 0x23F9, 0x23FA, 0x24C2, 0x25AA, 0x25AB, 0x25B6, 0x25C0, 0x25FB, 0x25FC, 0x25FD, 0x25FE, 0x2600, + 0x2601, 0x2602, 0x2603, 0x2604, 0x260E, 0x2611, 0x2614, 0x2615, 0x2618, 0x261D, 0x2620, 0x2622, + 0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2648, 0x2649, 0x264A, 0x264B, + 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, 0x2660, 0x2663, 0x2665, 0x2666, + 0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2696, 0x2697, 0x2699, 0x269B, 0x269C, 0x26A0, + 0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1, 0x26BD, 0x26BE, 0x26C4, 0x26C5, 0x26C8, 0x26CF, 0x26D1, + 0x26D3, 0x26D4, 0x26E9, 0x26EA, 0x26F0, 0x26F1, 0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8, + 0x26F9, 0x26FA, 0x26FD, 0x2702, 0x2708, 0x2709, 0x270C, 0x270D, 0x270F, 0x2712, 0x2714, 0x2716, + 0x271D, 0x2721, 0x2733, 0x2734, 0x2744, 0x2747, 0x2757, 0x2763, 0x2764, 0x27A1, 0x2934, 0x2935, + 0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030, 0x303D, 0x3297, 0x3299, + 0x1F004, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F202, 0x1F21A, 0x1F22F, 0x1F237, 0x1F321, + 0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328, 0x1F329, 0x1F32A, 0x1F32B, 0x1F32C, 0x1F336, + 0x1F37D, 0x1F396, 0x1F397, 0x1F399, 0x1F39A, 0x1F39B, 0x1F39E, 0x1F39F, 0x1F3CB, 0x1F3CC, + 0x1F3CD, 0x1F3CE, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7, 0x1F3D8, 0x1F3D9, 0x1F3DA, 0x1F3DB, + 0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3F3, 0x1F3F5, 0x1F3F7, 0x1F43F, 0x1F441, 0x1F4FD, + 0x1F549, 0x1F54A, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576, 0x1F577, 0x1F578, + 0x1F579, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590, 0x1F5A5, 0x1F5A8, 0x1F5B1, + 0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3, 0x1F5C4, 0x1F5D1, 0x1F5D2, 0x1F5D3, 0x1F5DC, 0x1F5DD, + 0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8, 0x1F5EF, 0x1F5F3, 0x1F5FA, 0x1F6CB, 0x1F6CD, 0x1F6CE, + 0x1F6CF, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3, 0x1F6E4, 0x1F6E5, 0x1F6E9, 0x1F6F0, 0x1F6F3, +}; + +static bool isEmojiStyleVSBase(uint32_t cp) { + const size_t length = sizeof(EMOJI_STYLE_VS_BASES) / sizeof(EMOJI_STYLE_VS_BASES[0]); + return std::binary_search(EMOJI_STYLE_VS_BASES, EMOJI_STYLE_VS_BASES + length, cp); +} + uint32_t FontCollection::sNextId = 0; FontCollection::FontCollection(const vector<FontFamily*>& typefaces) : @@ -156,7 +192,7 @@ uint32_t FontCollection::calcFamilyScore(uint32_t ch, uint32_t vs, int variant, // - Returns 1 if the variation selector is not specified or if the font family only supports the // variation sequence's base character. uint32_t FontCollection::calcCoverageScore(uint32_t ch, uint32_t vs, FontFamily* fontFamily) const { - const bool hasVSGlyph = (vs != 0) && fontFamily->hasVariationSelector(ch, vs); + const bool hasVSGlyph = (vs != 0) && fontFamily->hasGlyph(ch, vs); if (!hasVSGlyph && !fontFamily->getCoverage()->get(ch)) { // The font doesn't support either variation sequence or even the base character. return kUnsupportedFontScore; @@ -176,7 +212,7 @@ uint32_t FontCollection::calcCoverageScore(uint32_t ch, uint32_t vs, FontFamily* return 3; } - if (vs == 0xFE0F || vs == 0xFE0E) { + if (vs == EMOJI_STYLE_VS || vs == TEXT_STYLE_VS) { const FontLanguages& langs = FontLanguageListCache::getById(fontFamily->langId()); bool hasEmojiFlag = false; for (size_t i = 0; i < langs.size(); ++i) { @@ -186,9 +222,9 @@ uint32_t FontCollection::calcCoverageScore(uint32_t ch, uint32_t vs, FontFamily* } } - if (vs == 0xFE0F) { + if (vs == EMOJI_STYLE_VS) { return hasEmojiFlag ? 2 : 1; - } else { // vs == 0xFE0E + } else { // vs == TEXT_STYLE_VS return hasEmojiFlag ? 1 : 2; } } @@ -325,17 +361,27 @@ bool FontCollection::hasVariationSelector(uint32_t baseCodepoint, if (baseCodepoint >= mMaxChar) { return false; } - if (variationSelector == 0) { - return false; - } + + AutoMutex _l(gMinikinLock); // Currently mRanges can not be used here since it isn't aware of the variation sequence. for (size_t i = 0; i < mVSFamilyVec.size(); i++) { - AutoMutex _l(gMinikinLock); - if (mVSFamilyVec[i]->hasVariationSelector(baseCodepoint, variationSelector)) { + if (mVSFamilyVec[i]->hasGlyph(baseCodepoint, variationSelector)) { return true; } } + + // Even if there is no cmap format 14 subtable entry for the given sequence, should return true + // for emoji + U+FE0E case since we have special fallback rule for the sequence. + if (isEmojiStyleVSBase(baseCodepoint) && variationSelector == TEXT_STYLE_VS) { + for (size_t i = 0; i < mFamilies.size(); ++i) { + if (!mFamilies[i]->isColorEmojiFamily() && variationSelector == TEXT_STYLE_VS && + mFamilies[i]->hasGlyph(baseCodepoint, 0)) { + return true; + } + } + } + return false; } |