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