17839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/*
27839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Copyright 2013 Google Inc.
37839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *
47839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
57839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * found in the LICENSE file.
67839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
77839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
87839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkOTTable_name.h"
97839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkEndian.h"
117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkString.h"
127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkTSearch.h"
137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkTemplates.h"
147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkUtils.h"
157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkUnichar SkUTF16BE_NextUnichar(const uint16_t** srcPtr) {
177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT(srcPtr && *srcPtr);
187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const uint16_t* src = *srcPtr;
207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkUnichar c = SkEndian_SwapBE16(*src++);
217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT(!SkUTF16_IsLowSurrogate(c));
237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (SkUTF16_IsHighSurrogate(c)) {
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        unsigned c2 = SkEndian_SwapBE16(*src++);
257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkASSERT(SkUTF16_IsLowSurrogate(c2));
267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    *srcPtr = src;
307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return c;
317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void SkStringFromUTF16BE(const uint16_t* utf16be, size_t length, SkString& utf8) {
347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT(utf16be != NULL);
357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    utf8.reset();
377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t numberOf16BitValues = length / 2;
387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const uint16_t* end = utf16be + numberOf16BitValues;
397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    while (utf16be < end) {
407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        utf8.appendUnichar(SkUTF16BE_NextUnichar(&utf16be));
417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/** UnicodeFromMacRoman[macRomanPoint - 0x80] -> unicodeCodePoint.
457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  Derived from http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMAN.TXT .
467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  In MacRoman the first 128 code points match ASCII code points.
477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  This maps the second 128 MacRoman code points to unicode code points.
487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic uint16_t UnicodeFromMacRoman[0x80] = {
507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1,
517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8,
527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3,
537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC,
547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF,
557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8,
567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211,
577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8,
587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB,
597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153,
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA,
617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02,
627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1,
637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4,
647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC,
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7,
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger};
677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void SkStringFromMacRoman(const uint8_t* macRoman, size_t length, SkString& utf8) {
697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    utf8.reset();
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (size_t i = 0; i < length; ++i) {
71910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        utf8.appendUnichar(macRoman[i] < 0x80 ? macRoman[i]
72910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                              : UnicodeFromMacRoman[macRoman[i] - 0x80]);
737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic struct BCP47FromLanguageId {
777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    uint16_t languageID;
787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const char* bcp47;
797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/** The Mac and Windows values do not conflict, so this is currently one single table. */
817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerBCP47FromLanguageID[] = {
827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /** A mapping from Mac Language Designators to BCP 47 codes.
837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  The following list was constructed more or less manually.
847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Apple now uses BCP 47 (post OSX10.4), so there will be no new entries.
857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {0, "en"}, //English
877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {1, "fr"}, //French
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {2, "de"}, //German
897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {3, "it"}, //Italian
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {4, "nl"}, //Dutch
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {5, "sv"}, //Swedish
927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {6, "es"}, //Spanish
937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {7, "da"}, //Danish
947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {8, "pt"}, //Portuguese
957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {9, "nb"}, //Norwegian
967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {10, "he"}, //Hebrew
977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {11, "ja"}, //Japanese
987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {12, "ar"}, //Arabic
997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {13, "fi"}, //Finnish
1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {14, "el"}, //Greek
1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {15, "is"}, //Icelandic
1027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {16, "mt"}, //Maltese
1037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {17, "tr"}, //Turkish
1047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {18, "hr"}, //Croatian
1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {19, "zh-Hant"}, //Chinese (Traditional)
1067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {20, "ur"}, //Urdu
1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {21, "hi"}, //Hindi
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {22, "th"}, //Thai
1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {23, "ko"}, //Korean
1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {24, "lt"}, //Lithuanian
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {25, "pl"}, //Polish
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {26, "hu"}, //Hungarian
1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {27, "et"}, //Estonian
1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {28, "lv"}, //Latvian
1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {29, "se"}, //Sami
1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {30, "fo"}, //Faroese
1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {31, "fa"}, //Farsi (Persian)
1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {32, "ru"}, //Russian
1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {33, "zh-Hans"}, //Chinese (Simplified)
1207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {34, "nl"}, //Dutch
1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {35, "ga"}, //Irish(Gaelic)
1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {36, "sq"}, //Albanian
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {37, "ro"}, //Romanian
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {38, "cs"}, //Czech
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {39, "sk"}, //Slovak
1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {40, "sl"}, //Slovenian
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {41, "yi"}, //Yiddish
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {42, "sr"}, //Serbian
1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {43, "mk"}, //Macedonian
1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {44, "bg"}, //Bulgarian
1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {45, "uk"}, //Ukrainian
1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {46, "be"}, //Byelorussian
1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {47, "uz"}, //Uzbek
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {48, "kk"}, //Kazakh
1357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {49, "az-Cyrl"}, //Azerbaijani (Cyrillic)
1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {50, "az-Arab"}, //Azerbaijani (Arabic)
1377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {51, "hy"}, //Armenian
1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {52, "ka"}, //Georgian
1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {53, "mo"}, //Moldavian
1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {54, "ky"}, //Kirghiz
1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {55, "tg"}, //Tajiki
1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {56, "tk"}, //Turkmen
1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {57, "mn-Mong"}, //Mongolian (Traditional)
1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {58, "mn-Cyrl"}, //Mongolian (Cyrillic)
1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {59, "ps"}, //Pashto
1467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {60, "ku"}, //Kurdish
1477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {61, "ks"}, //Kashmiri
1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {62, "sd"}, //Sindhi
1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {63, "bo"}, //Tibetan
1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {64, "ne"}, //Nepali
1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {65, "sa"}, //Sanskrit
1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {66, "mr"}, //Marathi
1537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {67, "bn"}, //Bengali
1547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {68, "as"}, //Assamese
1557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {69, "gu"}, //Gujarati
1567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {70, "pa"}, //Punjabi
1577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {71, "or"}, //Oriya
1587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {72, "ml"}, //Malayalam
1597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {73, "kn"}, //Kannada
1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {74, "ta"}, //Tamil
1617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {75, "te"}, //Telugu
1627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {76, "si"}, //Sinhalese
1637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {77, "my"}, //Burmese
1647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {78, "km"}, //Khmer
1657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {79, "lo"}, //Lao
1667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {80, "vi"}, //Vietnamese
1677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {81, "id"}, //Indonesian
1687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {82, "tl"}, //Tagalog
1697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {83, "ms-Latn"}, //Malay (Roman)
1707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {84, "ms-Arab"}, //Malay (Arabic)
1717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {85, "am"}, //Amharic
1727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {86, "ti"}, //Tigrinya
1737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {87, "om"}, //Oromo
1747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {88, "so"}, //Somali
1757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {89, "sw"}, //Swahili
1767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {90, "rw"}, //Kinyarwanda/Ruanda
1777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {91, "rn"}, //Rundi
1787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {92, "ny"}, //Nyanja/Chewa
1797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {93, "mg"}, //Malagasy
1807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {94, "eo"}, //Esperanto
1817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {128, "cy"}, //Welsh
1827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {129, "eu"}, //Basque
1837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {130, "ca"}, //Catalan
1847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {131, "la"}, //Latin
1857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {132, "qu"}, //Quechua
1867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {133, "gn"}, //Guarani
1877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {134, "ay"}, //Aymara
1887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {135, "tt"}, //Tatar
1897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {136, "ug"}, //Uighur
1907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {137, "dz"}, //Dzongkha
1917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {138, "jv-Latn"}, //Javanese (Roman)
1927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {139, "su-Latn"}, //Sundanese (Roman)
1937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {140, "gl"}, //Galician
1947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {141, "af"}, //Afrikaans
1957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {142, "br"}, //Breton
1967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {143, "iu"}, //Inuktitut
1977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {144, "gd"}, //Scottish (Gaelic)
1987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {145, "gv"}, //Manx (Gaelic)
1997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {146, "ga"}, //Irish (Gaelic with Lenition)
2007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {147, "to"}, //Tongan
2017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {148, "el"}, //Greek (Polytonic) Note: ISO 15924 does not have an equivalent script name.
2027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {149, "kl"}, //Greenlandic
2037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {150, "az-Latn"}, //Azerbaijani (Roman)
2047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    {151, "nn"}, //Nynorsk
2057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /** A mapping from Windows LCID to BCP 47 codes.
2077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  This list is the sorted, curated output of tools/win_lcid.cpp.
2087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Note that these are sorted by value for quick binary lookup, and not logically by lsb.
2097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  The 'bare' language ids (e.g. 0x0001 for Arabic) are ommitted
2107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  as they do not appear as valid language ids in the OpenType specification.
2117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
2127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0401, "ar-SA" }, //Arabic
2137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0402, "bg-BG" }, //Bulgarian
2147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0403, "ca-ES" }, //Catalan
2157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0404, "zh-TW" }, //Chinese (Traditional)
2167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0405, "cs-CZ" }, //Czech
2177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0406, "da-DK" }, //Danish
2187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0407, "de-DE" }, //German
2197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0408, "el-GR" }, //Greek
2207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0409, "en-US" }, //English
2217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x040a, "es-ES_tradnl" }, //Spanish
2227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x040b, "fi-FI" }, //Finnish
2237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x040c, "fr-FR" }, //French
2247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x040d, "he-IL" }, //Hebrew
2257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x040d, "he" }, //Hebrew
2267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x040e, "hu-HU" }, //Hungarian
2277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x040e, "hu" }, //Hungarian
2287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x040f, "is-IS" }, //Icelandic
2297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0410, "it-IT" }, //Italian
2307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0411, "ja-JP" }, //Japanese
2317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0412, "ko-KR" }, //Korean
2327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0413, "nl-NL" }, //Dutch
2337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0414, "nb-NO" }, //Norwegian (Bokm�l)
2347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0415, "pl-PL" }, //Polish
2357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0416, "pt-BR" }, //Portuguese
2367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0417, "rm-CH" }, //Romansh
2377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0418, "ro-RO" }, //Romanian
2387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0419, "ru-RU" }, //Russian
2397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x041a, "hr-HR" }, //Croatian
2407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x041b, "sk-SK" }, //Slovak
2417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x041c, "sq-AL" }, //Albanian
2427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x041d, "sv-SE" }, //Swedish
2437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x041e, "th-TH" }, //Thai
2447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x041f, "tr-TR" }, //Turkish
2457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0420, "ur-PK" }, //Urdu
2467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0421, "id-ID" }, //Indonesian
2477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0422, "uk-UA" }, //Ukrainian
2487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0423, "be-BY" }, //Belarusian
2497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0424, "sl-SI" }, //Slovenian
2507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0425, "et-EE" }, //Estonian
2517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0426, "lv-LV" }, //Latvian
2527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0427, "lt-LT" }, //Lithuanian
2537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0428, "tg-Cyrl-TJ" }, //Tajik (Cyrillic)
2547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0429, "fa-IR" }, //Persian
2557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x042a, "vi-VN" }, //Vietnamese
2567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x042b, "hy-AM" }, //Armenian
2577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x042c, "az-Latn-AZ" }, //Azeri (Latin)
2587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x042d, "eu-ES" }, //Basque
2597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x042e, "hsb-DE" }, //Upper Sorbian
2607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x042f, "mk-MK" }, //Macedonian (FYROM)
2617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0432, "tn-ZA" }, //Setswana
2627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0434, "xh-ZA" }, //isiXhosa
2637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0435, "zu-ZA" }, //isiZulu
2647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0436, "af-ZA" }, //Afrikaans
2657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0437, "ka-GE" }, //Georgian
2667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0438, "fo-FO" }, //Faroese
2677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0439, "hi-IN" }, //Hindi
2687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x043a, "mt-MT" }, //Maltese
2697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x043b, "se-NO" }, //Sami (Northern)
2707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x043e, "ms-MY" }, //Malay
2717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x043f, "kk-KZ" }, //Kazakh
2727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0440, "ky-KG" }, //Kyrgyz
2737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0441, "sw-KE" }, //Kiswahili
2747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0442, "tk-TM" }, //Turkmen
2757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0443, "uz-Latn-UZ" }, //Uzbek (Latin)
2767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0443, "uz" }, //Uzbek
2777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0444, "tt-RU" }, //Tatar
2787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0445, "bn-IN" }, //Bengali
2797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0446, "pa-IN" }, //Punjabi
2807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0447, "gu-IN" }, //Gujarati
2817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0448, "or-IN" }, //Oriya
2827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0449, "ta-IN" }, //Tamil
2837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x044a, "te-IN" }, //Telugu
2847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x044b, "kn-IN" }, //Kannada
2857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x044c, "ml-IN" }, //Malayalam
2867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x044d, "as-IN" }, //Assamese
2877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x044e, "mr-IN" }, //Marathi
2887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x044f, "sa-IN" }, //Sanskrit
2897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0450, "mn-Cyrl" }, //Mongolian (Cyrillic)
2907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0451, "bo-CN" }, //Tibetan
2917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0452, "cy-GB" }, //Welsh
2927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0453, "km-KH" }, //Khmer
2937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0454, "lo-LA" }, //Lao
2947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0456, "gl-ES" }, //Galician
2957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0457, "kok-IN" }, //Konkani
2967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x045a, "syr-SY" }, //Syriac
2977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x045b, "si-LK" }, //Sinhala
2987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x045d, "iu-Cans-CA" }, //Inuktitut (Syllabics)
2997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x045e, "am-ET" }, //Amharic
3007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0461, "ne-NP" }, //Nepali
3017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0462, "fy-NL" }, //Frisian
3027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0463, "ps-AF" }, //Pashto
3037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0464, "fil-PH" }, //Filipino
3047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0465, "dv-MV" }, //Divehi
3057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0468, "ha-Latn-NG" }, //Hausa (Latin)
3067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x046a, "yo-NG" }, //Yoruba
3077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x046b, "quz-BO" }, //Quechua
3087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x046c, "nso-ZA" }, //Sesotho sa Leboa
3097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x046d, "ba-RU" }, //Bashkir
3107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x046e, "lb-LU" }, //Luxembourgish
3117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x046f, "kl-GL" }, //Greenlandic
3127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0470, "ig-NG" }, //Igbo
3137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0478, "ii-CN" }, //Yi
3147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x047a, "arn-CL" }, //Mapudungun
3157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x047c, "moh-CA" }, //Mohawk
3167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x047e, "br-FR" }, //Breton
3177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0480, "ug-CN" }, //Uyghur
3187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0481, "mi-NZ" }, //Maori
3197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0482, "oc-FR" }, //Occitan
3207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0483, "co-FR" }, //Corsican
3217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0484, "gsw-FR" }, //Alsatian
3227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0485, "sah-RU" }, //Yakut
3237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0486, "qut-GT" }, //K'iche
3247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0487, "rw-RW" }, //Kinyarwanda
3257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0488, "wo-SN" }, //Wolof
3267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x048c, "prs-AF" }, //Dari
3277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0491, "gd-GB" }, //Scottish Gaelic
3287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0801, "ar-IQ" }, //Arabic
3297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0804, "zh-Hans" }, //Chinese (Simplified)
3307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0807, "de-CH" }, //German
3317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0809, "en-GB" }, //English
3327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x080a, "es-MX" }, //Spanish
3337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x080c, "fr-BE" }, //French
3347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0810, "it-CH" }, //Italian
3357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0813, "nl-BE" }, //Dutch
3367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0814, "nn-NO" }, //Norwegian (Nynorsk)
3377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0816, "pt-PT" }, //Portuguese
3387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x081a, "sr-Latn-CS" }, //Serbian (Latin)
3397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x081d, "sv-FI" }, //Swedish
3407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x082c, "az-Cyrl-AZ" }, //Azeri (Cyrillic)
3417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x082e, "dsb-DE" }, //Lower Sorbian
3427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x082e, "dsb" }, //Lower Sorbian
3437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x083b, "se-SE" }, //Sami (Northern)
3447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x083c, "ga-IE" }, //Irish
3457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x083e, "ms-BN" }, //Malay
3467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0843, "uz-Cyrl-UZ" }, //Uzbek (Cyrillic)
3477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0845, "bn-BD" }, //Bengali
3487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0850, "mn-Mong-CN" }, //Mongolian (Traditional Mongolian)
3497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x085d, "iu-Latn-CA" }, //Inuktitut (Latin)
3507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x085f, "tzm-Latn-DZ" }, //Tamazight (Latin)
3517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x086b, "quz-EC" }, //Quechua
3527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c01, "ar-EG" }, //Arabic
3537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c04, "zh-Hant" }, //Chinese (Traditional)
3547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c07, "de-AT" }, //German
3557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c09, "en-AU" }, //English
3567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c0a, "es-ES" }, //Spanish
3577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c0c, "fr-CA" }, //French
3587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c1a, "sr-Cyrl-CS" }, //Serbian (Cyrillic)
3597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c3b, "se-FI" }, //Sami (Northern)
3607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x0c6b, "quz-PE" }, //Quechua
3617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1001, "ar-LY" }, //Arabic
3627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1004, "zh-SG" }, //Chinese (Simplified)
3637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1007, "de-LU" }, //German
3647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1009, "en-CA" }, //English
3657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x100a, "es-GT" }, //Spanish
3667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x100c, "fr-CH" }, //French
3677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x101a, "hr-BA" }, //Croatian (Latin)
3687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x103b, "smj-NO" }, //Sami (Lule)
3697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1401, "ar-DZ" }, //Arabic
3707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1404, "zh-MO" }, //Chinese (Traditional)
3717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1407, "de-LI" }, //German
3727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1409, "en-NZ" }, //English
3737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x140a, "es-CR" }, //Spanish
3747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x140c, "fr-LU" }, //French
3757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x141a, "bs-Latn-BA" }, //Bosnian (Latin)
3767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x141a, "bs" }, //Bosnian
3777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x143b, "smj-SE" }, //Sami (Lule)
3787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x143b, "smj" }, //Sami (Lule)
3797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1801, "ar-MA" }, //Arabic
3807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1809, "en-IE" }, //English
3817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x180a, "es-PA" }, //Spanish
3827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x180c, "fr-MC" }, //French
3837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x181a, "sr-Latn-BA" }, //Serbian (Latin)
3847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x183b, "sma-NO" }, //Sami (Southern)
3857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1c01, "ar-TN" }, //Arabic
3867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1c09, "en-ZA" }, //English
3877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1c0a, "es-DO" }, //Spanish
3887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1c1a, "sr-Cyrl-BA" }, //Serbian (Cyrillic)
3897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1c3b, "sma-SE" }, //Sami (Southern)
3907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x1c3b, "sma" }, //Sami (Southern)
3917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2001, "ar-OM" }, //Arabic
3927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2009, "en-JM" }, //English
3937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x200a, "es-VE" }, //Spanish
3947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x201a, "bs-Cyrl-BA" }, //Bosnian (Cyrillic)
3957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x201a, "bs-Cyrl" }, //Bosnian (Cyrillic)
3967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x203b, "sms-FI" }, //Sami (Skolt)
3977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x203b, "sms" }, //Sami (Skolt)
3987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2401, "ar-YE" }, //Arabic
3997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2409, "en-029" }, //English
4007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x240a, "es-CO" }, //Spanish
4017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x241a, "sr-Latn-RS" }, //Serbian (Latin)
4027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x243b, "smn-FI" }, //Sami (Inari)
4037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2801, "ar-SY" }, //Arabic
4047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2809, "en-BZ" }, //English
4057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x280a, "es-PE" }, //Spanish
4067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x281a, "sr-Cyrl-RS" }, //Serbian (Cyrillic)
4077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2c01, "ar-JO" }, //Arabic
4087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2c09, "en-TT" }, //English
4097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2c0a, "es-AR" }, //Spanish
4107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x2c1a, "sr-Latn-ME" }, //Serbian (Latin)
4117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x3001, "ar-LB" }, //Arabic
4127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x3009, "en-ZW" }, //English
4137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x300a, "es-EC" }, //Spanish
4147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x301a, "sr-Cyrl-ME" }, //Serbian (Cyrillic)
4157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x3401, "ar-KW" }, //Arabic
4167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x3409, "en-PH" }, //English
4177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x340a, "es-CL" }, //Spanish
4187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x3801, "ar-AE" }, //Arabic
4197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x380a, "es-UY" }, //Spanish
4207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x3c01, "ar-BH" }, //Arabic
4217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x3c0a, "es-PY" }, //Spanish
4227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x4001, "ar-QA" }, //Arabic
4237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x4009, "en-IN" }, //English
4247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x400a, "es-BO" }, //Spanish
4257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x4409, "en-MY" }, //English
4267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x440a, "es-SV" }, //Spanish
4277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x4809, "en-SG" }, //English
4287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x480a, "es-HN" }, //Spanish
4297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x4c0a, "es-NI" }, //Spanish
4307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x500a, "es-PR" }, //Spanish
4317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    { 0x540a, "es-US" }, //Spanish
4327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger};
4337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
4347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergernamespace {
4357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool BCP47FromLanguageIdLess(const BCP47FromLanguageId& a, const BCP47FromLanguageId& b) {
4367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return a.languageID < b.languageID;
4377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
4387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
4397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
4407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool SkOTTableName::Iterator::next(SkOTTableName::Iterator::Record& record) {
4417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const size_t nameRecordsCount = SkEndian_SwapBE16(fName.count);
4427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const SkOTTableName::Record* nameRecords = SkTAfter<const SkOTTableName::Record>(&fName);
4437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const SkOTTableName::Record* nameRecord;
4447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
4457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Find the next record which matches the requested type.
4467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    do {
4477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (fIndex >= nameRecordsCount) {
4487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            return false;
4497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
4507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
4517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        nameRecord = &nameRecords[fIndex];
4527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        ++fIndex;
4537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } while (fType != -1 && nameRecord->nameID.fontSpecific != fType);
4547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
455e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    record.type = nameRecord->nameID.fontSpecific;
456e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
4577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const uint16_t stringTableOffset = SkEndian_SwapBE16(fName.stringOffset);
4587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const char* stringTable = SkTAddOffset<const char>(&fName, stringTableOffset);
4597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
4607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Decode the name into UTF-8.
4617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const uint16_t nameOffset = SkEndian_SwapBE16(nameRecord->offset);
4627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const uint16_t nameLength = SkEndian_SwapBE16(nameRecord->length);
4637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const char* nameString = SkTAddOffset<const char>(stringTable, nameOffset);
4647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    switch (nameRecord->platformID.value) {
4657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        case SkOTTableName::Record::PlatformID::Windows:
466e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            if (SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2
467e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                   != nameRecord->encodingID.windows.value
468e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                && SkOTTableName::Record::EncodingID::Windows::UnicodeUCS4
469e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                   != nameRecord->encodingID.windows.value
470e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                && SkOTTableName::Record::EncodingID::Windows::Symbol
471e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                   != nameRecord->encodingID.windows.value)
472e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            {
473e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                record.name.reset();
474e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                break;
475e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            }
4767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        case SkOTTableName::Record::PlatformID::Unicode:
4777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        case SkOTTableName::Record::PlatformID::ISO:
4787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkStringFromUTF16BE((const uint16_t*)nameString, nameLength, record.name);
4797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            break;
4807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
4817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        case SkOTTableName::Record::PlatformID::Macintosh:
482e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // TODO: need better decoding, especially on Mac.
483e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            if (SkOTTableName::Record::EncodingID::Macintosh::Roman
484e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                != nameRecord->encodingID.macintosh.value)
485e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            {
486e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                record.name.reset();
487e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                break;
488e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            }
4897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkStringFromMacRoman((const uint8_t*)nameString, nameLength, record.name);
4907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            break;
4917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
4927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        case SkOTTableName::Record::PlatformID::Custom:
4937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            // These should never appear in a 'name' table.
4947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        default:
4957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkASSERT(false);
4967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            record.name.reset();
4977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            break;
4987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
4997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
5007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Determine the language.
5017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const uint16_t languageID = SkEndian_SwapBE16(nameRecord->languageID.languageTagID);
5027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
5037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Handle format 1 languages.
5047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (SkOTTableName::format_1 == fName.format && languageID >= 0x8000) {
5057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const uint16_t languageTagRecordIndex = languageID - 0x8000;
5067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
5077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const SkOTTableName::Format1Ext* format1ext =
5087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkTAfter<const SkOTTableName::Format1Ext>(nameRecords, nameRecordsCount);
5097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
510e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (languageTagRecordIndex < SkEndian_SwapBE16(format1ext->langTagCount)) {
5117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            const SkOTTableName::Format1Ext::LangTagRecord* languageTagRecord =
5127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                SkTAfter<const SkOTTableName::Format1Ext::LangTagRecord>(format1ext);
5137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
5147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            uint16_t offset = SkEndian_SwapBE16(languageTagRecord[languageTagRecordIndex].offset);
5157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            uint16_t length = SkEndian_SwapBE16(languageTagRecord[languageTagRecordIndex].length);
5167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            const uint16_t* string = SkTAddOffset<const uint16_t>(stringTable, offset);
5177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkStringFromUTF16BE(string, length, record.language);
5187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            return true;
5197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
5207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
5217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
5227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Handle format 0 languages, translating them into BCP 47.
5237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const BCP47FromLanguageId target = { languageID, "" };
5247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int languageIndex = SkTSearch<BCP47FromLanguageId, BCP47FromLanguageIdLess>(
5257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        BCP47FromLanguageID, SK_ARRAY_COUNT(BCP47FromLanguageID), target, sizeof(target));
5267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (languageIndex >= 0) {
5277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        record.language = BCP47FromLanguageID[languageIndex].bcp47;
5287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return true;
5297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
5307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
5317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Unknown language, return the BCP 47 code 'und' for 'undetermined'.
5327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    record.language = "und";
5337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return true;
5347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
535