19cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien/*
29cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Copyright (C) 2013 The Android Open Source Project
39cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
49cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Licensed under the Apache License, Version 2.0 (the "License");
59cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * you may not use this file except in compliance with the License.
69cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * You may obtain a copy of the License at
79cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
89cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *      http://www.apache.org/licenses/LICENSE-2.0
99cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Unless required by applicable law or agreed to in writing, software
119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * distributed under the License is distributed on an "AS IS" BASIS,
129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * See the License for the specific language governing permissions and
149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * limitations under the License.
159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien */
169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
17ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien// #define VERBOSE_DEBUG
18ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien
19ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien#define LOG_TAG "Minikin"
20ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien#include <cutils/log.h>
216f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka#include <algorithm>
229cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
23997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien#include "unicode/unistr.h"
24997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien#include "unicode/unorm2.h"
25997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien
26198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka#include "FontLanguage.h"
276d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka#include "FontLanguageListCache.h"
28c31e3883456e018d742e9f29815ba5ff8b315ea1Raph Levien#include "MinikinInternal.h"
299cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <minikin/FontCollection.h>
309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
319cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienusing std::vector;
329cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
339cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Leviennamespace android {
349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
359cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levientemplate <typename T>
369cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienstatic inline T max(T a, T b) {
379cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    return a>b ? a : b;
389cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
40994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonakaconst uint32_t EMOJI_STYLE_VS = 0xFE0F;
41994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonakaconst uint32_t TEXT_STYLE_VS = 0xFE0E;
42994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka
43994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka// See http://www.unicode.org/Public/9.0.0/ucd/StandardizedVariants-9.0.0d1.txt
44994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka// Must be sorted.
45994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonakaconst uint32_t EMOJI_STYLE_VS_BASES[] = {
46994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x0023, 0x002A, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039,
47994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x00A9, 0x00AE, 0x203C, 0x2049, 0x2122, 0x2139, 0x2194, 0x2195, 0x2196, 0x2197, 0x2198, 0x2199,
48994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x21A9, 0x21AA, 0x231A, 0x231B, 0x2328, 0x23CF, 0x23ED, 0x23EE, 0x23EF, 0x23F1, 0x23F2, 0x23F8,
49994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x23F9, 0x23FA, 0x24C2, 0x25AA, 0x25AB, 0x25B6, 0x25C0, 0x25FB, 0x25FC, 0x25FD, 0x25FE, 0x2600,
50994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x2601, 0x2602, 0x2603, 0x2604, 0x260E, 0x2611, 0x2614, 0x2615, 0x2618, 0x261D, 0x2620, 0x2622,
51994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2648, 0x2649, 0x264A, 0x264B,
52994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, 0x2660, 0x2663, 0x2665, 0x2666,
53994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2696, 0x2697, 0x2699, 0x269B, 0x269C, 0x26A0,
54994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1, 0x26BD, 0x26BE, 0x26C4, 0x26C5, 0x26C8, 0x26CF, 0x26D1,
55994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x26D3, 0x26D4, 0x26E9, 0x26EA, 0x26F0, 0x26F1, 0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8,
56994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x26F9, 0x26FA, 0x26FD, 0x2702, 0x2708, 0x2709, 0x270C, 0x270D, 0x270F, 0x2712, 0x2714, 0x2716,
57994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x271D, 0x2721, 0x2733, 0x2734, 0x2744, 0x2747, 0x2757, 0x2763, 0x2764, 0x27A1, 0x2934, 0x2935,
58994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030, 0x303D, 0x3297, 0x3299,
59994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F004, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F202, 0x1F21A, 0x1F22F, 0x1F237, 0x1F321,
60994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328, 0x1F329, 0x1F32A, 0x1F32B, 0x1F32C, 0x1F336,
61994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F37D, 0x1F396, 0x1F397, 0x1F399, 0x1F39A, 0x1F39B, 0x1F39E, 0x1F39F, 0x1F3CB, 0x1F3CC,
62994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F3CD, 0x1F3CE, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7, 0x1F3D8, 0x1F3D9, 0x1F3DA, 0x1F3DB,
63994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3F3, 0x1F3F5, 0x1F3F7, 0x1F43F, 0x1F441, 0x1F4FD,
64994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F549, 0x1F54A, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576, 0x1F577, 0x1F578,
65994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F579, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590, 0x1F5A5, 0x1F5A8, 0x1F5B1,
66994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3, 0x1F5C4, 0x1F5D1, 0x1F5D2, 0x1F5D3, 0x1F5DC, 0x1F5DD,
67994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8, 0x1F5EF, 0x1F5F3, 0x1F5FA, 0x1F6CB, 0x1F6CD, 0x1F6CE,
68994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    0x1F6CF, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3, 0x1F6E4, 0x1F6E5, 0x1F6E9, 0x1F6F0, 0x1F6F3,
69994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka};
70994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka
71994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonakastatic bool isEmojiStyleVSBase(uint32_t cp) {
72994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    const size_t length = sizeof(EMOJI_STYLE_VS_BASES) / sizeof(EMOJI_STYLE_VS_BASES[0]);
73994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    return std::binary_search(EMOJI_STYLE_VS_BASES, EMOJI_STYLE_VS_BASES + length, cp);
74994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka}
75994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka
764d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levienuint32_t FontCollection::sNextId = 0;
774d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien
789cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienFontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
799cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    mMaxChar(0) {
80c31e3883456e018d742e9f29815ba5ff8b315ea1Raph Levien    AutoMutex _l(gMinikinLock);
814d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien    mId = sNextId++;
829cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    vector<uint32_t> lastChar;
839cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    size_t nTypefaces = typefaces.size();
849cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#ifdef VERBOSE_DEBUG
85bae347682989d2627081310129a5b60541ed6ad0Seigo Nonaka    ALOGD("nTypefaces = %zd\n", nTypefaces);
869cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif
879cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const FontStyle defaultStyle;
889cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    for (size_t i = 0; i < nTypefaces; i++) {
899cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        FontFamily* family = typefaces[i];
909a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien        MinikinFont* typeface = family->getClosestMatch(defaultStyle).font;
914d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien        if (typeface == NULL) {
924d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien            continue;
934d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien        }
94bd36ec766a451c62ffdd407d5ce1a355e8f7dfd8Raph Levien        family->RefLocked();
9513f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien        const SparseBitSet* coverage = family->getCoverage();
96cb20a2f0b366bfc16db3a489a60156dec7a9fe21Andreas Gampe        if (coverage == nullptr) {
97cb20a2f0b366bfc16db3a489a60156dec7a9fe21Andreas Gampe            family->UnrefLocked();
98cb20a2f0b366bfc16db3a489a60156dec7a9fe21Andreas Gampe            continue;
99cb20a2f0b366bfc16db3a489a60156dec7a9fe21Andreas Gampe        }
100cb20a2f0b366bfc16db3a489a60156dec7a9fe21Andreas Gampe        mFamilies.push_back(family);  // emplace_back would be better
1016b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        if (family->hasVSTable()) {
1026b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka            mVSFamilyVec.push_back(family);
1036b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        }
10413f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien        mMaxChar = max(mMaxChar, coverage->length());
10513f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien        lastChar.push_back(coverage->nextSetBit(0));
1069cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
10713f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien    nTypefaces = mFamilies.size();
108156acb18f53b32655abb34166ea737e4320ca366Raph Levien    LOG_ALWAYS_FATAL_IF(nTypefaces == 0,
109156acb18f53b32655abb34166ea737e4320ca366Raph Levien        "Font collection must have at least one valid typeface");
11072fe9422c869b7878240a23e4650d9d90edb1c2aRaph Levien    size_t nPages = (mMaxChar + kPageMask) >> kLogCharsPerPage;
1119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    size_t offset = 0;
11280d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    // TODO: Use variation selector map for mRanges construction.
11380d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    // A font can have a glyph for a base code point and variation selector pair but no glyph for
11480d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    // the base code point without variation selector. The family won't be listed in the range in
11580d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    // this case.
1169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    for (size_t i = 0; i < nPages; i++) {
1179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        Range dummy;
1189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        mRanges.push_back(dummy);
1199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        Range* range = &mRanges.back();
1209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#ifdef VERBOSE_DEBUG
121bae347682989d2627081310129a5b60541ed6ad0Seigo Nonaka        ALOGD("i=%zd: range start = %zd\n", i, offset);
1229cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif
1239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        range->start = offset;
1249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        for (size_t j = 0; j < nTypefaces; j++) {
1259cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            if (lastChar[j] < (i + 1) << kLogCharsPerPage) {
12613f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien                FontFamily* family = mFamilies[j];
12713f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien                mFamilyVec.push_back(family);
1289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                offset++;
12913f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien                uint32_t nextChar = family->getCoverage()->nextSetBit((i + 1) << kLogCharsPerPage);
1309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#ifdef VERBOSE_DEBUG
131bae347682989d2627081310129a5b60541ed6ad0Seigo Nonaka                ALOGD("nextChar = %d (j = %zd)\n", nextChar, j);
1329cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif
1339cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien                lastChar[j] = nextChar;
1349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            }
1359cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
1369cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        range->end = offset;
1379cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
1389cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1409cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienFontCollection::~FontCollection() {
14113f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien    for (size_t i = 0; i < mFamilies.size(); i++) {
14213f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien        mFamilies[i]->UnrefLocked();
1439cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
1449cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1459cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1466f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// Special scores for the font fallback.
1476f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonakaconst uint32_t kUnsupportedFontScore = 0;
1486f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonakaconst uint32_t kFirstFontScore = UINT32_MAX;
1496f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
1506f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// Calculates a font score.
1516f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// The score of the font family is based on three subscores.
1526f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//  - Coverage Score: How well the font family covers the given character or variation sequence.
1536f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//  - Language Score: How well the font family is appropriate for the language.
1546f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//  - Variant Score: Whether the font family matches the variant. Note that this variant is not the
1556f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//    one in BCP47. This is our own font variant (e.g., elegant, compact).
1566f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//
1576f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// Then, there is a priority for these three subscores as follow:
1586f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//   Coverage Score > Language Score > Variant Score
1596f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// The returned score reflects this priority order.
1606f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//
1616f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// Note that there are two special scores.
1626f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//  - kUnsupportedFontScore: When the font family doesn't support the variation sequence or even its
1636f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//    base character.
1646f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//  - kFirstFontScore: When the font is the first font family in the collection and it supports the
1656f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//    given character or variation sequence.
1666f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonakauint32_t FontCollection::calcFamilyScore(uint32_t ch, uint32_t vs, int variant, uint32_t langListId,
1676f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka                                        FontFamily* fontFamily) const {
1686f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
1696f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    const uint32_t coverageScore = calcCoverageScore(ch, vs, fontFamily);
1706f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    if (coverageScore == kFirstFontScore || coverageScore == kUnsupportedFontScore) {
1716f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        // No need to calculate other scores.
1726f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        return coverageScore;
1736f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    }
1746f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
1756f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    const uint32_t languageScore = calcLanguageMatchingScore(langListId, *fontFamily);
1766f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    const uint32_t variantScore = calcVariantMatchingScore(variant, *fontFamily);
1776f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
1786f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    // Subscores are encoded into 31 bits representation to meet the subscore priority.
1796f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    // The highest 2 bits are for coverage score, then following 28 bits are for language score,
1806f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    // then the last 1 bit is for variant score.
1816f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    return coverageScore << 29 | languageScore << 1 | variantScore;
1826f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka}
1836f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
1846f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// Calculates a font score based on variation sequence coverage.
1856f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// - Returns kUnsupportedFontScore if the font doesn't support the variation sequence or its base
1866f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//   character.
1876f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// - Returns kFirstFontScore if the font family is the first font family in the collection and it
1886f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//   supports the given character or variation sequence.
1896f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// - Returns 3 if the font family supports the variation sequence.
1906f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// - Returns 2 if the vs is a color variation selector (U+FE0F) and if the font is an emoji font.
1916f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// - Returns 2 if the vs is a text variation selector (U+FE0E) and if the font is not an emoji font.
1926f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// - Returns 1 if the variation selector is not specified or if the font family only supports the
1936f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//   variation sequence's base character.
1946f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonakauint32_t FontCollection::calcCoverageScore(uint32_t ch, uint32_t vs, FontFamily* fontFamily) const {
195994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    const bool hasVSGlyph = (vs != 0) && fontFamily->hasGlyph(ch, vs);
1966f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    if (!hasVSGlyph && !fontFamily->getCoverage()->get(ch)) {
1976f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        // The font doesn't support either variation sequence or even the base character.
1986f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        return kUnsupportedFontScore;
1996f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    }
2006f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
2016f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    if ((vs == 0 || hasVSGlyph) && mFamilies[0] == fontFamily) {
2026f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        // If the first font family supports the given character or variation sequence, always use
2036f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        // it.
2046f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        return kFirstFontScore;
2056f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    }
2066f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
2076f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    if (vs == 0) {
2086f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        return 1;
2096f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    }
2106f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
2116f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    if (hasVSGlyph) {
2126f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        return 3;
2136f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    }
2146f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
215994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    if (vs == EMOJI_STYLE_VS || vs == TEXT_STYLE_VS) {
216f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        const FontLanguages& langs = FontLanguageListCache::getById(fontFamily->langId());
217f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        bool hasEmojiFlag = false;
218f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        for (size_t i = 0; i < langs.size(); ++i) {
219f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka            if (langs[i].hasEmojiFlag()) {
220f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka                hasEmojiFlag = true;
221f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka                break;
222f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka            }
223f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        }
224f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka
225994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka        if (vs == EMOJI_STYLE_VS) {
2266f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka            return hasEmojiFlag ? 2 : 1;
227994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka        } else {  // vs == TEXT_STYLE_VS
2286f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka            return hasEmojiFlag ? 1 : 2;
2296f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        }
2306f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    }
2316f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    return 1;
2326f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka}
2336f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
2346f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// Calculates font scores based on the script matching and primary langauge matching.
2356f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//
2366f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// If the font's script doesn't support the requested script, the font gets a score of 0. If the
2376f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// font's script supports the requested script and the font has the same primary language as the
2386f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// requested one, the font gets a score of 2. If the font's script supports the requested script
2396f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// but the primary language is different from the requested one, the font gets a score of 1.
2406f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//
2416f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// If two languages in the requested list have the same language score, the font matching with
2426f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// higher priority language gets a higher score. For example, in the case the user requested
2436f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// language list is "ja-Jpan,en-Latn". The score of for the font of "ja-Jpan" gets a higher score
2446f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// than the font of "en-Latn".
2456f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//
2466f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// To achieve the above two conditions, the language score is determined as follows:
2476f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//   LanguageScore = s(0) * 3^(m - 1) + s(1) * 3^(m - 2) + ... + s(m - 2) * 3 + s(m - 1)
2486f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// Here, m is the maximum number of languages to be compared, and s(i) is the i-th language's
2496f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// matching score. The possible values of s(i) are 0, 1 and 2.
2506f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonakauint32_t FontCollection::calcLanguageMatchingScore(
2516f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        uint32_t userLangListId, const FontFamily& fontFamily) {
2526f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    const FontLanguages& langList = FontLanguageListCache::getById(userLangListId);
253f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    const FontLanguages& fontLanguages = FontLanguageListCache::getById(fontFamily.langId());
2546f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
2556f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    const size_t maxCompareNum = std::min(langList.size(), FONT_LANGUAGES_LIMIT);
256f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    uint32_t score = 0;
257f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    for (size_t i = 0; i < maxCompareNum; ++i) {
258f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        score = score * 3u + langList[i].calcScoreFor(fontLanguages);
2596f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    }
2606f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    return score;
2616f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka}
2626f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
2636f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// Calculates a font score based on variant ("compact" or "elegant") matching.
2646f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//  - Returns 1 if the font doesn't have variant or the variant matches with the text style.
2656f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka//  - No score if the font has a variant but it doesn't match with the text style.
2666f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonakauint32_t FontCollection::calcVariantMatchingScore(int variant, const FontFamily& fontFamily) {
2676f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    return (fontFamily.variant() == 0 || fontFamily.variant() == variant) ? 1 : 0;
2686f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka}
2696f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
2707b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien// Implement heuristic for choosing best-match font. Here are the rules:
2717b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien// 1. If first font in the collection has the character, it wins.
2726f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// 2. Calculate a score for the font family. See comments in calcFamilyScore for the detail.
2736f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka// 3. Highest score wins, with ties resolved to the first font.
274cee83d40324b1f3b8e113eb8c9eda8e12ef36923Seigo Nonaka// This method never returns nullptr.
275bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo NonakaFontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs,
2766d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka            uint32_t langListId, int variant) const {
2779cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (ch >= mMaxChar) {
278cee83d40324b1f3b8e113eb8c9eda8e12ef36923Seigo Nonaka        return mFamilies[0];
2799cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
280fc119c68f5def1e44e65ae4cdd147c01d62c9ad2Seigo Nonaka
2816b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka    const std::vector<FontFamily*>* familyVec = &mFamilyVec;
2826b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka    Range range = mRanges[ch >> kLogCharsPerPage];
2836b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka
2846b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka    std::vector<FontFamily*> familyVecForVS;
2856b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka    if (vs != 0) {
2866b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        // If variation selector is specified, need to search for both the variation sequence and
2876b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        // its base codepoint. Compute the union vector of them.
2886b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        familyVecForVS = mVSFamilyVec;
2896b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        familyVecForVS.insert(familyVecForVS.end(),
2906b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka                mFamilyVec.begin() + range.start, mFamilyVec.begin() + range.end);
2916b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        std::sort(familyVecForVS.begin(), familyVecForVS.end());
2926b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        auto last = std::unique(familyVecForVS.begin(), familyVecForVS.end());
2936b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        familyVecForVS.erase(last, familyVecForVS.end());
2946b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka
2956b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        familyVec = &familyVecForVS;
2966b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        range = { 0, familyVecForVS.size() };
297fc119c68f5def1e44e65ae4cdd147c01d62c9ad2Seigo Nonaka    }
298fc119c68f5def1e44e65ae4cdd147c01d62c9ad2Seigo Nonaka
2999cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#ifdef VERBOSE_DEBUG
300bae347682989d2627081310129a5b60541ed6ad0Seigo Nonaka    ALOGD("querying range %zd:%zd\n", range.start, range.end);
3019cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif
302bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    FontFamily* bestFamily = nullptr;
3036f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    uint32_t bestScore = kUnsupportedFontScore;
3049cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    for (size_t i = range.start; i < range.end; i++) {
3056b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka        FontFamily* family = (*familyVec)[i];
3066f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        const uint32_t score = calcFamilyScore(ch, vs, variant, langListId, family);
3076f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        if (score == kFirstFontScore) {
3086f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka            // If the first font family supports the given character or variation sequence, always
3096f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka            // use it.
3106f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka            return family;
3116f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        }
3126f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka        if (score > bestScore) {
3136f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka            bestScore = score;
3146f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka            bestFamily = family;
3159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
3166d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    }
317cee83d40324b1f3b8e113eb8c9eda8e12ef36923Seigo Nonaka    if (bestFamily == nullptr) {
318997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien        UErrorCode errorCode = U_ZERO_ERROR;
319997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien        const UNormalizer2* normalizer = unorm2_getNFDInstance(&errorCode);
320997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien        if (U_SUCCESS(errorCode)) {
321997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien            UChar decomposed[4];
322997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien            int len = unorm2_getRawDecomposition(normalizer, ch, decomposed, 4, &errorCode);
323997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien            if (U_SUCCESS(errorCode) && len > 0) {
324997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien                int off = 0;
325997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien                U16_NEXT_UNSAFE(decomposed, off, ch);
3266d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka                return getFamilyForChar(ch, vs, langListId, variant);
327997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien            }
328997c799e3ec6bf8adf687e29670d23d91e0f5feeRaph Levien        }
32913f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien        bestFamily = mFamilies[0];
330156acb18f53b32655abb34166ea737e4320ca366Raph Levien    }
33113f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien    return bestFamily;
3329cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
3339cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
334bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levienconst uint32_t NBSP = 0xa0;
335bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levienconst uint32_t ZWJ = 0x200c;
336bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levienconst uint32_t ZWNJ = 0x200d;
33790a09c3f36d98530822392446884b8af68035908Raph Levienconst uint32_t HYPHEN = 0x2010;
33890a09c3f36d98530822392446884b8af68035908Raph Levienconst uint32_t NB_HYPHEN = 0x2011;
339f952161b874fd2e9af474b9fd2ebcca1f3bb4555Behdad Esfahbod
340bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien// Characters where we want to continue using existing font run instead of
341bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien// recomputing the best match in the fallback list.
34290a09c3f36d98530822392446884b8af68035908Raph Levienstatic const uint32_t stickyWhitelist[] = { '!', ',', '-', '.', ':', ';', '?', NBSP, ZWJ, ZWNJ,
34316ed4ef07ed8fb2333447b48055633bf8d4f38e4Roozbeh Pournader        HYPHEN, NB_HYPHEN };
344bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien
345bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levienstatic bool isStickyWhitelisted(uint32_t c) {
346bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien    for (size_t i = 0; i < sizeof(stickyWhitelist) / sizeof(stickyWhitelist[0]); i++) {
347bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien        if (stickyWhitelist[i] == c) return true;
348bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien    }
349bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien    return false;
350bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien}
351bb601b67dd05947f92cc23092bfb8a059c2e3377Raph Levien
352bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonakastatic bool isVariationSelector(uint32_t c) {
353bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    return (0xFE00 <= c && c <= 0xFE0F) || (0xE0100 <= c && c <= 0xE01EF);
354bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka}
355bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka
35680d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonakabool FontCollection::hasVariationSelector(uint32_t baseCodepoint,
35780d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka        uint32_t variationSelector) const {
35880d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    if (!isVariationSelector(variationSelector)) {
35980d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka        return false;
36080d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    }
36180d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    if (baseCodepoint >= mMaxChar) {
36280d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka        return false;
36380d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    }
364994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka
365994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    AutoMutex _l(gMinikinLock);
3666b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka
36780d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    // Currently mRanges can not be used here since it isn't aware of the variation sequence.
3686b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka    for (size_t i = 0; i < mVSFamilyVec.size(); i++) {
369994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka        if (mVSFamilyVec[i]->hasGlyph(baseCodepoint, variationSelector)) {
3706b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka            return true;
37180d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka        }
37280d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    }
373994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka
374994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    // Even if there is no cmap format 14 subtable entry for the given sequence, should return true
375994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    // for emoji + U+FE0E case since we have special fallback rule for the sequence.
376994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    if (isEmojiStyleVSBase(baseCodepoint) && variationSelector == TEXT_STYLE_VS) {
377994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka        for (size_t i = 0; i < mFamilies.size(); ++i) {
378994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka            if (!mFamilies[i]->isColorEmojiFamily() && variationSelector == TEXT_STYLE_VS &&
379994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka                mFamilies[i]->hasGlyph(baseCodepoint, 0)) {
380994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka                return true;
381994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka            }
382994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka        }
383994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka    }
384994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka
38580d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka    return false;
38680d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka}
38780d113bcd4bbc395218503354af1a5a6dba59b4bSeigo Nonaka
3889cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienvoid FontCollection::itemize(const uint16_t *string, size_t string_size, FontStyle style,
3899cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        vector<Run>* result) const {
3906d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka    const uint32_t langListId = style.getLanguageListId();
3917b221d97b7b64dc5ce457e19666d55d042e22e62Raph Levien    int variant = style.getVariant();
39213f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien    FontFamily* lastFamily = NULL;
3939cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    Run* run = NULL;
394bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka
395bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    if (string_size == 0) {
396bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        return;
397bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    }
398bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka
399bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    const uint32_t kEndOfString = 0xFFFFFFFF;
400bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka
401bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    uint32_t nextCh = 0;
402bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    uint32_t prevCh = 0;
403bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    size_t nextUtf16Pos = 0;
404bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    size_t readLength = 0;
405bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    U16_NEXT(string, readLength, string_size, nextCh);
406bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka
407bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    do {
408bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        const uint32_t ch = nextCh;
409bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        const size_t utf16Pos = nextUtf16Pos;
410bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        nextUtf16Pos = readLength;
411bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        if (readLength < string_size) {
412bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka            U16_NEXT(string, readLength, string_size, nextCh);
413bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        } else {
414bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka            nextCh = kEndOfString;
415bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        }
416bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka
417bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        bool shouldContinueRun = false;
418bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        if (lastFamily != nullptr) {
419bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka            if (isStickyWhitelisted(ch)) {
420bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka                // Continue using existing font as long as it has coverage and is whitelisted
421bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka                shouldContinueRun = lastFamily->getCoverage()->get(ch);
422bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka            } else if (isVariationSelector(ch)) {
423bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka                // Always continue if the character is a variation selector.
424bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka                shouldContinueRun = true;
4259cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            }
4269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
427bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka
428bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        if (!shouldContinueRun) {
4296d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka            FontFamily* family = getFamilyForChar(ch, isVariationSelector(nextCh) ? nextCh : 0,
4306d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka                    langListId, variant);
431bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka            if (utf16Pos == 0 || family != lastFamily) {
432bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka                size_t start = utf16Pos;
43316ed4ef07ed8fb2333447b48055633bf8d4f38e4Roozbeh Pournader                // Workaround for combining marks and emoji modifiers until we implement
43416ed4ef07ed8fb2333447b48055633bf8d4f38e4Roozbeh Pournader                // per-cluster font selection: if a combining mark or an emoji modifier is found in
43516ed4ef07ed8fb2333447b48055633bf8d4f38e4Roozbeh Pournader                // a different font that also supports the previous character, attach previous
43616ed4ef07ed8fb2333447b48055633bf8d4f38e4Roozbeh Pournader                // character to the new run. U+20E3 COMBINING ENCLOSING KEYCAP, used in emoji, is
43716ed4ef07ed8fb2333447b48055633bf8d4f38e4Roozbeh Pournader                // handled properly by this since it's a combining mark too.
4380036da164e3b25f1ac29c840c1fe15b03dc6677fSeigo Nonaka                if (utf16Pos != 0 &&
43916ed4ef07ed8fb2333447b48055633bf8d4f38e4Roozbeh Pournader                        ((U_GET_GC_MASK(ch) & U_GC_M_MASK) != 0 ||
44016ed4ef07ed8fb2333447b48055633bf8d4f38e4Roozbeh Pournader                         (isEmojiModifier(ch) && isEmojiBase(prevCh))) &&
4410036da164e3b25f1ac29c840c1fe15b03dc6677fSeigo Nonaka                        family && family->getCoverage()->get(prevCh)) {
4423dd8757fcf48976295bac566277b6da1046e8362Seigo Nonaka                    const size_t prevChLength = U16_LENGTH(prevCh);
4433dd8757fcf48976295bac566277b6da1046e8362Seigo Nonaka                    run->end -= prevChLength;
444f952161b874fd2e9af474b9fd2ebcca1f3bb4555Behdad Esfahbod                    if (run->start == run->end) {
445f952161b874fd2e9af474b9fd2ebcca1f3bb4555Behdad Esfahbod                        result->pop_back();
446f952161b874fd2e9af474b9fd2ebcca1f3bb4555Behdad Esfahbod                    }
4473dd8757fcf48976295bac566277b6da1046e8362Seigo Nonaka                    start -= prevChLength;
448f952161b874fd2e9af474b9fd2ebcca1f3bb4555Behdad Esfahbod                }
449066e8575af64fb452617ac6005de6ccf6509553bRaph Levien                Run dummy;
450066e8575af64fb452617ac6005de6ccf6509553bRaph Levien                result->push_back(dummy);
451066e8575af64fb452617ac6005de6ccf6509553bRaph Levien                run = &result->back();
452cee83d40324b1f3b8e113eb8c9eda8e12ef36923Seigo Nonaka                run->fakedFont = family->getClosestMatch(style);
45313f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien                lastFamily = family;
454f952161b874fd2e9af474b9fd2ebcca1f3bb4555Behdad Esfahbod                run->start = start;
4559cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            }
4569cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
457bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        prevCh = ch;
458bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka        run->end = nextUtf16Pos;  // exclusive
459bbdd73ec077a1bb6801b25a639834be16dfd78cbSeigo Nonaka    } while (nextCh != kEndOfString);
4609cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
4619cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
46289566f0ada1cafe673efa064cde38467990235d4Raph LevienMinikinFont* FontCollection::baseFont(FontStyle style) {
4639a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    return baseFontFaked(style).font;
4649a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien}
4659a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien
4669a5f713add8cfb91ac2c9ed5c917309053201ab6Raph LevienFakedFont FontCollection::baseFontFaked(FontStyle style) {
46713f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien    return mFamilies[0]->getClosestMatch(style);
46889566f0ada1cafe673efa064cde38467990235d4Raph Levien}
46989566f0ada1cafe673efa064cde38467990235d4Raph Levien
4704d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levienuint32_t FontCollection::getId() const {
4714d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien    return mId;
4724d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien}
4734d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien
4749cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}  // namespace android
475