Locale.cpp revision e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1
1198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka/*
2198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * Copyright (C) 2015 The Android Open Source Project
3198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka *
4198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * Licensed under the Apache License, Version 2.0 (the "License");
5198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * you may not use this file except in compliance with the License.
6198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * You may obtain a copy of the License at
7198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka *
8198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka *      http://www.apache.org/licenses/LICENSE-2.0
9198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka *
10198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * Unless required by applicable law or agreed to in writing, software
11198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * distributed under the License is distributed on an "AS IS" BASIS,
12198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * See the License for the specific language governing permissions and
14198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka * limitations under the License.
15198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka */
16198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
17198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka#define LOG_TAG "Minikin"
18198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
19198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka#include "FontLanguage.h"
20198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
21e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui#include <algorithm>
22198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka#include <hb.h>
23e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui#include <string.h>
24198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka#include <unicode/uloc.h>
25198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
2614e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakanamespace minikin {
27198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
28198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka#define SCRIPT_TAG(c1, c2, c3, c4) \
29198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        (((uint32_t)(c1)) << 24 | ((uint32_t)(c2)) << 16 | ((uint32_t)(c3)) <<  8 | \
30198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka         ((uint32_t)(c4)))
31198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
32e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui// Check if a language code supports emoji according to its subtag
33e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yiruistatic bool isEmojiSubtag(const char* buf, size_t bufLen, const char* subtag, size_t subtagLen) {
34e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    if (bufLen < subtagLen) {
35e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        return false;
36e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    }
37e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    if (strncmp(buf, subtag, subtagLen) != 0) {
38e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        return false;  // no match between two strings
39e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    }
40e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    return (bufLen == subtagLen || buf[subtagLen] == '\0' ||
41e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui            buf[subtagLen] == '-' || buf[subtagLen] == '_');
42e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui}
43e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui
44198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka// Parse BCP 47 language identifier into internal structure
45198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo NonakaFontLanguage::FontLanguage(const char* buf, size_t length) : FontLanguage() {
46198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    size_t i;
47198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    for (i = 0; i < length; i++) {
48198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        char c = buf[i];
49198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        if (c == '-' || c == '_') break;
50198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    }
51198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    if (i == 2 || i == 3) {  // only accept two or three letter language code.
52198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        mLanguage = buf[0] | (buf[1] << 8) | ((i == 3) ? (buf[2] << 16) : 0);
53198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    } else {
54198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        // We don't understand anything other than two-letter or three-letter
55198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        // language codes, so we skip parsing the rest of the string.
56198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        mLanguage = 0ul;
57198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        return;
58198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    }
59198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
60198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    size_t next;
61198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    for (i++; i < length; i = next + 1) {
62198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        for (next = i; next < length; next++) {
63198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            char c = buf[next];
64198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            if (c == '-' || c == '_') break;
65198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        }
66198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        if (next - i == 4 && 'A' <= buf[i] && buf[i] <= 'Z') {
67198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            mScript = SCRIPT_TAG(buf[i], buf[i + 1], buf[i + 2], buf[i + 3]);
68198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        }
69198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    }
70198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    mSubScriptBits = scriptToSubScriptBits(mScript);
71e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui
72e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    if (mScript == SCRIPT_TAG('Z', 's', 'y', 'e')) {
73e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        mEmojiStyle = EMSTYLE_EMOJI;
74e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    } else if (mScript == SCRIPT_TAG('Z', 's', 'y', 'm')) {
75e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        mEmojiStyle = EMSTYLE_TEXT;
76e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    }
77e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    // 10 is the length of "-u-em-text", which is the shortest emoji subtag,
78e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    // unnecessary comparison can be avoided if total length is smaller than 10.
79e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    const size_t kMinSubtagLength = 10;
80e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    if (length < kMinSubtagLength) {
81e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        return;
82e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    }
83e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui
84e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    static const char kPrefix[] = "-u-em-";
85e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    const char *pos = std::search(buf, buf + length, kPrefix, kPrefix + strlen(kPrefix));
86e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    if (pos == buf + length) {
87e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        return;
88e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    }
89e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    pos += strlen(kPrefix);
90e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    const size_t remainingLength = length - (pos - buf);
91e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    if (isEmojiSubtag(pos, remainingLength, "emoji", 5)){
92e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        mEmojiStyle = EMSTYLE_EMOJI;
93e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    } else if (isEmojiSubtag(pos, remainingLength, "text", 4)){
94e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        mEmojiStyle = EMSTYLE_TEXT;
95e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    } else if (isEmojiSubtag(pos, remainingLength, "default", 7)){
96e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui        mEmojiStyle = EMSTYLE_DEFAULT;
97e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui    }
98198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka}
99198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
100198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka//static
101198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonakauint8_t FontLanguage::scriptToSubScriptBits(uint32_t script) {
102198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    uint8_t subScriptBits = 0u;
103198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    switch (script) {
104533a01ea8438bb102b0dbc71f6c4ef356b260ed5Seigo Nonaka        case SCRIPT_TAG('B', 'o', 'p', 'o'):
105533a01ea8438bb102b0dbc71f6c4ef356b260ed5Seigo Nonaka            subScriptBits = kBopomofoFlag;
106533a01ea8438bb102b0dbc71f6c4ef356b260ed5Seigo Nonaka            break;
107198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('H', 'a', 'n', 'g'):
108198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kHangulFlag;
109198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
110533a01ea8438bb102b0dbc71f6c4ef356b260ed5Seigo Nonaka        case SCRIPT_TAG('H', 'a', 'n', 'b'):
111533a01ea8438bb102b0dbc71f6c4ef356b260ed5Seigo Nonaka            // Bopomofo is almost exclusively used in Taiwan.
112533a01ea8438bb102b0dbc71f6c4ef356b260ed5Seigo Nonaka            subScriptBits = kHanFlag | kBopomofoFlag;
113533a01ea8438bb102b0dbc71f6c4ef356b260ed5Seigo Nonaka            break;
114198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('H', 'a', 'n', 'i'):
115198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kHanFlag;
116198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
117198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('H', 'a', 'n', 's'):
118198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kHanFlag | kSimplifiedChineseFlag;
119198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
120198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('H', 'a', 'n', 't'):
121198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kHanFlag | kTraditionalChineseFlag;
122198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
123198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('H', 'i', 'r', 'a'):
124198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kHiraganaFlag;
125198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
126198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('H', 'r', 'k', 't'):
127198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kKatakanaFlag | kHiraganaFlag;
128198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
129198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('J', 'p', 'a', 'n'):
130198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kHanFlag | kKatakanaFlag | kHiraganaFlag;
131198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
132198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('K', 'a', 'n', 'a'):
133198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kKatakanaFlag;
134198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
135198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        case SCRIPT_TAG('K', 'o', 'r', 'e'):
136198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            subScriptBits = kHanFlag | kHangulFlag;
137198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka            break;
138198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    }
139198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    return subScriptBits;
140198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka}
141198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
142198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonakastd::string FontLanguage::getString() const {
143198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    if (mLanguage == 0ul) {
144198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka        return "und";
145198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    }
146198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    char buf[16];
147198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    size_t i = 0;
148198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    buf[i++] = mLanguage & 0xFF ;
149198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    buf[i++] = (mLanguage >> 8) & 0xFF;
150198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    char third_letter = (mLanguage >> 16) & 0xFF;
151198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    if (third_letter != 0) buf[i++] = third_letter;
152198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    if (mScript != 0) {
153198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka      buf[i++] = '-';
154198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka      buf[i++] = (mScript >> 24) & 0xFFu;
155198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka      buf[i++] = (mScript >> 16) & 0xFFu;
156198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka      buf[i++] = (mScript >> 8) & 0xFFu;
157198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka      buf[i++] = mScript & 0xFFu;
158198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    }
159198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    return std::string(buf, i);
160198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka}
161198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
1626f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonakabool FontLanguage::isEqualScript(const FontLanguage& other) const {
163198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    return other.mScript == mScript;
164198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka}
165198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
166f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka// static
167f3afe92def0fff022889fd036d68451223aac146Seigo Nonakabool FontLanguage::supportsScript(uint8_t providedBits, uint8_t requestedBits) {
168f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    return requestedBits != 0 && (providedBits & requestedBits) == requestedBits;
1696f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka}
1706f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka
171198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonakabool FontLanguage::supportsHbScript(hb_script_t script) const {
172198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    static_assert(SCRIPT_TAG('J', 'p', 'a', 'n') == HB_TAG('J', 'p', 'a', 'n'),
173198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka                  "The Minikin script and HarfBuzz hb_script_t have different encodings.");
174198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka    if (script == mScript) return true;
175f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    return supportsScript(mSubScriptBits, scriptToSubScriptBits(script));
176198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka}
177198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
178f3afe92def0fff022889fd036d68451223aac146Seigo Nonakaint FontLanguage::calcScoreFor(const FontLanguages& supported) const {
179f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    int score = 0;
180f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    for (size_t i = 0; i < supported.size(); ++i) {
181f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        if (isEqualScript(supported[i]) ||
182f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka                supportsScript(supported[i].mSubScriptBits, mSubScriptBits)) {
183f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka            if (mLanguage == supported[i].mLanguage) {
184f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka                return 2;
185f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka            } else {
186f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka                score = 1;
187f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka            }
188f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        }
189f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    }
190f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka
191f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    if (score == 1) {
192f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        return score;
193f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    }
194f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka
195f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    if (supportsScript(supported.getUnionOfSubScriptBits(), mSubScriptBits)) {
196f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        // Gives score of 2 only if the language matches all of the font languages except for the
197f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        // exact match case handled above.
198f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        return (mLanguage == supported[0].mLanguage && supported.isAllTheSameLanguage()) ? 2 : 1;
199f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    }
200f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka
201f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    return 0;
202f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka}
203f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka
204f3afe92def0fff022889fd036d68451223aac146Seigo NonakaFontLanguages::FontLanguages(std::vector<FontLanguage>&& languages)
205f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    : mLanguages(std::move(languages)) {
206f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    if (mLanguages.empty()) {
207f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        return;
208f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    }
209f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka
210f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    const FontLanguage& lang = mLanguages[0];
211f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka
212f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    mIsAllTheSameLanguage = true;
213f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    mUnionOfSubScriptBits = lang.mSubScriptBits;
214f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka    for (size_t i = 1; i < mLanguages.size(); ++i) {
215f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        mUnionOfSubScriptBits |= mLanguages[i].mSubScriptBits;
216f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        if (mIsAllTheSameLanguage && lang.mLanguage != mLanguages[i].mLanguage) {
217f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka            mIsAllTheSameLanguage = false;
218f3afe92def0fff022889fd036d68451223aac146Seigo Nonaka        }
2196f9966ea7c1910fd780cf7779cc59701c9b98a2bSeigo Nonaka    }
220198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka}
221198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka
222198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka#undef SCRIPT_TAG
22314e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka}  // namespace minikin
224