Git init
[external/pango1.0.git] / pango / pango-ot-tag.c
1 /* Pango
2  * pango-ot-tag.h:
3  *
4  * Copyright (C) 2007 Red Hat Software
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include "pango-ot.h"
25
26 typedef union {
27   char string[4];
28   guint32 integer;
29 } Tag;
30
31 /*
32  * complete list at:
33  * http://www.microsoft.com/typography/developers/opentype/scripttags.aspx
34  */
35 static const Tag ot_scripts[] = {
36   {"DFLT"},     /* PANGO_SCRIPT_COMMON */
37   {"DFLT"},     /* PANGO_SCRIPT_INHERITED */
38   {"arab"},     /* PANGO_SCRIPT_ARABIC */
39   {"armn"},     /* PANGO_SCRIPT_ARMENIAN */
40   {"beng"},     /* PANGO_SCRIPT_BENGALI */
41   {"bopo"},     /* PANGO_SCRIPT_BOPOMOFO */
42   {"cher"},     /* PANGO_SCRIPT_CHEROKEE */
43   {"copt"},     /* PANGO_SCRIPT_COPTIC */
44   {"cyrl"},     /* PANGO_SCRIPT_CYRILLIC */
45   {"dsrt"},     /* PANGO_SCRIPT_DESERET */
46   {"deva"},     /* PANGO_SCRIPT_DEVANAGARI */
47   {"ethi"},     /* PANGO_SCRIPT_ETHIOPIC */
48   {"geor"},     /* PANGO_SCRIPT_GEORGIAN */
49   {"goth"},     /* PANGO_SCRIPT_GOTHIC */
50   {"grek"},     /* PANGO_SCRIPT_GREEK */
51   {"gujr"},     /* PANGO_SCRIPT_GUJARATI */
52   {"guru"},     /* PANGO_SCRIPT_GURMUKHI */
53   {"hani"},     /* PANGO_SCRIPT_HAN */
54   {"hang"},     /* PANGO_SCRIPT_HANGUL */
55   {"hebr"},     /* PANGO_SCRIPT_HEBREW */
56   {"kana"},     /* PANGO_SCRIPT_HIRAGANA */
57   {"knda"},     /* PANGO_SCRIPT_KANNADA */
58   {"kana"},     /* PANGO_SCRIPT_KATAKANA */
59   {"khmr"},     /* PANGO_SCRIPT_KHMER */
60   {"lao "},     /* PANGO_SCRIPT_LAO */
61   {"latn"},     /* PANGO_SCRIPT_LATIN */
62   {"mlym"},     /* PANGO_SCRIPT_MALAYALAM */
63   {"mong"},     /* PANGO_SCRIPT_MONGOLIAN */
64   {"mymr"},     /* PANGO_SCRIPT_MYANMAR */
65   {"ogam"},     /* PANGO_SCRIPT_OGHAM */
66   {"ital"},     /* PANGO_SCRIPT_OLD_ITALIC */
67   {"orya"},     /* PANGO_SCRIPT_ORIYA */
68   {"runr"},     /* PANGO_SCRIPT_RUNIC */
69   {"sinh"},     /* PANGO_SCRIPT_SINHALA */
70   {"syrc"},     /* PANGO_SCRIPT_SYRIAC */
71   {"taml"},     /* PANGO_SCRIPT_TAMIL */
72   {"telu"},     /* PANGO_SCRIPT_TELUGU */
73   {"thaa"},     /* PANGO_SCRIPT_THAANA */
74   {"thai"},     /* PANGO_SCRIPT_THAI */
75   {"tibt"},     /* PANGO_SCRIPT_TIBETAN */
76   {"cans"},     /* PANGO_SCRIPT_CANADIAN_ABORIGINAL */
77   {"yi  "},     /* PANGO_SCRIPT_YI */
78   {"tglg"},     /* PANGO_SCRIPT_TAGALOG */
79   {"hano"},     /* PANGO_SCRIPT_HANUNOO */
80   {"buhd"},     /* PANGO_SCRIPT_BUHID */
81   {"tagb"},     /* PANGO_SCRIPT_TAGBANWA */
82   {"brai"},     /* PANGO_SCRIPT_BRAILLE */
83   {"cprt"},     /* PANGO_SCRIPT_CYPRIOT */
84   {"limb"},     /* PANGO_SCRIPT_LIMBU */
85   {"osma"},     /* PANGO_SCRIPT_OSMANYA */
86   {"shaw"},     /* PANGO_SCRIPT_SHAVIAN */
87   {"linb"},     /* PANGO_SCRIPT_LINEAR_B */
88   {"tale"},     /* PANGO_SCRIPT_TAI_LE */
89   {"ugar"},     /* PANGO_SCRIPT_UGARITIC */
90   {"talu"},     /* PANGO_SCRIPT_NEW_TAI_LUE */
91   {"bugi"},     /* PANGO_SCRIPT_BUGINESE */
92   {"glag"},     /* PANGO_SCRIPT_GLAGOLITIC */
93   {"tfng"},     /* PANGO_SCRIPT_TIFINAGH */
94   {"sylo"},     /* PANGO_SCRIPT_SYLOTI_NAGRI */
95   {"xpeo"},     /* PANGO_SCRIPT_OLD_PERSIAN */
96   {"khar"},     /* PANGO_SCRIPT_KHAROSHTHI */
97   {"DFLT"},     /* PANGO_SCRIPT_UNKNOWN */
98   {"bali"},     /* PANGO_SCRIPT_BALINESE */
99   {"xsux"},     /* PANGO_SCRIPT_CUNEIFORM */
100   {"phnx"},     /* PANGO_SCRIPT_PHOENICIAN */
101   {"phag"},     /* PANGO_SCRIPT_PHAGS_PA */
102   {"nko "}      /* PANGO_SCRIPT_NKO */
103 };
104
105 /**
106  * pango_ot_tag_from_script:
107  * @script: A #PangoScript
108  *
109  * Finds the OpenType script tag corresponding to @script.
110  *
111  * The %PANGO_SCRIPT_COMMON, %PANGO_SCRIPT_INHERITED, and
112  * %PANGO_SCRIPT_UNKNOWN scripts are mapped to the OpenType
113  * 'DFLT' script tag that is also defined as
114  * %PANGO_OT_TAG_DEFAULT_SCRIPT.
115  *
116  * Note that multiple #PangoScript values may map to the same
117  * OpenType script tag.  In particular, %PANGO_SCRIPT_HIRAGANA
118  * and %PANGO_SCRIPT_KATAKANA both map to the OT tag 'kana'.
119  *
120  * Return value: #PangoOTTag corresponding to @script or
121  * %PANGO_OT_TAG_DEFAULT_SCRIPT if none found.
122  *
123  * Since: 1.18
124  **/
125 PangoOTTag
126 pango_ot_tag_from_script (PangoScript script)
127 {
128   g_return_val_if_fail (script >= 0, PANGO_OT_TAG_DEFAULT_SCRIPT);
129
130   if ((guint)script >= G_N_ELEMENTS (ot_scripts))
131     return PANGO_OT_TAG_DEFAULT_SCRIPT;
132
133   return GUINT32_FROM_BE (ot_scripts[script].integer);
134 }
135
136 /**
137  * pango_ot_tag_to_script:
138  * @script_tag: A #PangoOTTag OpenType script tag
139  *
140  * Finds the #PangoScript corresponding to @script_tag.
141  *
142  * The 'DFLT' script tag is mapped to %PANGO_SCRIPT_COMMON.
143  *
144  * Note that an OpenType script tag may correspond to multiple
145  * #PangoScript values.  In such cases, the #PangoScript value
146  * with the smallest value is returned.
147  * In particular, %PANGO_SCRIPT_HIRAGANA
148  * and %PANGO_SCRIPT_KATAKANA both map to the OT tag 'kana'.
149  * This function will return %PANGO_SCRIPT_HIRAGANA for
150  * 'kana'.
151  *
152  * Return value: #PangoScript corresponding to @script_tag or
153  * %PANGO_SCRIPT_UNKNOWN if none found.
154  *
155  * Since: 1.18
156  **/
157 PangoScript
158 pango_ot_tag_to_script (PangoOTTag script_tag)
159 {
160   PangoScript i;
161   guint32 be_tag = GUINT32_TO_BE (script_tag);
162
163   for (i = 0; i < (PangoScript) G_N_ELEMENTS (ot_scripts); i++)
164     {
165       guint32 tag = ot_scripts[i].integer;
166
167       if (tag == be_tag)
168         return i;
169     }
170
171   return PANGO_SCRIPT_UNKNOWN;
172 }
173
174
175 typedef struct {
176   char language[6];
177   Tag tag;
178 } LangTag;
179
180 /*
181  * complete list at:
182  * http://www.microsoft.com/OpenType/OTSpec/languagetags.htm
183  *
184  * Generated by intersecting the OpenType language tag list from
185  * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from
186  * 2008/08/04, matching on name, and finally adjusted manually.
187  *
188  * Many items still missing.  Those are commented out at the end.
189  * Keep sorted for bsearch.
190  */
191 static const LangTag ot_languages[] = {
192   {"aa",        {"AFR "}},      /* Afar */
193   {"ab",        {"ABK "}},      /* Abkhazian */
194   {"abq",       {"ABA "}},      /* Abaza */
195   {"ady",       {"ADY "}},      /* Adyghe */
196   {"af",        {"AFK "}},      /* Afrikaans */
197   {"aiw",       {"ARI "}},      /* Aari */
198   {"am",        {"AMH "}},      /* Amharic */
199   {"ar",        {"ARA "}},      /* Arabic */
200   {"arn",       {"MAP "}},      /* Mapudungun */
201   {"as",        {"ASM "}},      /* Assamese */
202   {"av",        {"AVR "}},      /* Avaric */
203   {"awa",       {"AWA "}},      /* Awadhi */
204   {"ay",        {"AYM "}},      /* Aymara */
205   {"az",        {"AZE "}},      /* Azerbaijani */
206   {"ba",        {"BSH "}},      /* Bashkir */
207   {"bal",       {"BLI "}},      /* Baluchi */
208   {"bcq",       {"BCH "}},      /* Bench */
209   {"bem",       {"BEM "}},      /* Bemba (Zambia) */
210   {"bfq",       {"BAD "}},      /* Badaga */
211   {"bft",       {"BLT "}},      /* Balti */
212   {"bg",        {"BGR "}},      /* Bulgarian */
213   {"bhb",       {"BHI "}},      /* Bhili */
214   {"bho",       {"BHO "}},      /* Bhojpuri */
215   {"bik",       {"BIK "}},      /* Bikol */
216   {"bin",       {"EDO "}},      /* Bini */
217   {"bm",        {"BMB "}},      /* Bambara */
218   {"bn",        {"BEN "}},      /* Bengali */
219   {"bo",        {"TIB "}},      /* Tibetan */
220   {"br",        {"BRE "}},      /* Breton */
221   {"brh",       {"BRH "}},      /* Brahui */
222   {"bs",        {"BOS "}},      /* Bosnian */
223   {"btb",       {"BTI "}},      /* Beti (Cameroon) */
224   {"ca",        {"CAT "}},      /* Catalan */
225   {"ce",        {"CHE "}},      /* Chechen */
226   {"ceb",       {"CEB "}},      /* Cebuano */
227   {"chp",       {"CHP "}},      /* Chipewyan */
228   {"chr",       {"CHR "}},      /* Cherokee */
229   {"cop",       {"COP "}},      /* Coptic */
230   {"cr",        {"CRE "}},      /* Cree */
231   {"crh",       {"CRT "}},      /* Crimean Tatar */
232   {"crm",       {"MCR "}},      /* Moose Cree */
233   {"crx",       {"CRR "}},      /* Carrier */
234   {"cs",        {"CSY "}},      /* Czech */
235   {"cu",        {"CSL "}},      /* Church Slavic */
236   {"cv",        {"CHU "}},      /* Chuvash */
237   {"cwd",       {"DCR "}},      /* Woods Cree */
238   {"cy",        {"WEL "}},      /* Welsh */
239   {"da",        {"DAN "}},      /* Danish */
240   {"dap",       {"NIS "}},      /* Nisi (India) */
241   {"dar",       {"DAR "}},      /* Dargwa */
242   {"de",        {"DEU "}},      /* German */
243   {"din",       {"DNK "}},      /* Dinka */
244   {"dng",       {"DUN "}},      /* Dungan */
245   {"doi",       {"DGR "}},      /* Dogri */
246   {"dsb",       {"LSB "}},      /* Lower Sorbian */
247   {"dv",        {"DIV "}},      /* Dhivehi */
248   {"dz",        {"DZN "}},      /* Dzongkha */
249   {"ee",        {"EWE "}},      /* Ewe */
250   {"efi",       {"EFI "}},      /* Efik */
251   {"el",        {"ELL "}},      /* Modern Greek (1453-) */
252   {"en",        {"ENG "}},      /* English */
253   {"eo",        {"NTO "}},      /* Esperanto */
254   {"eot",       {"BTI "}},      /* Beti (Côte d'Ivoire) */
255   {"es",        {"ESP "}},      /* Spanish */
256   {"et",        {"ETI "}},      /* Estonian */
257   {"eu",        {"EUQ "}},      /* Basque */
258   {"eve",       {"EVN "}},      /* Even */
259   {"evn",       {"EVK "}},      /* Evenki */
260   {"fa",        {"FAR "}},      /* Persian */
261   {"ff",        {"FUL "}},      /* Fulah */
262   {"fi",        {"FIN "}},      /* Finnish */
263   {"fil",       {"PIL "}},      /* Filipino */
264   {"fj",        {"FJI "}},      /* Fijian */
265   {"fo",        {"FOS "}},      /* Faroese */
266   {"fon",       {"FON "}},      /* Fon */
267   {"fr",        {"FRA "}},      /* French */
268   {"fur",       {"FRL "}},      /* Friulian */
269   {"fy",        {"FRI "}},      /* Western Frisian */
270   {"ga",        {"IRI "}},      /* Irish */
271   {"gaa",       {"GAD "}},      /* Ga */
272   {"gag",       {"GAG "}},      /* Gagauz */
273   {"gbm",       {"GAW "}},      /* Garhwali */
274   {"gd",        {"GAE "}},      /* Scottish Gaelic */
275   {"gl",        {"GAL "}},      /* Galician */
276   {"gld",       {"NAN "}},      /* Nanai */
277   {"gn",        {"GUA "}},      /* Guarani */
278   {"gon",       {"GON "}},      /* Gondi */
279   {"grt",       {"GRO "}},      /* Garo */
280   {"gu",        {"GUJ "}},      /* Gujarati */
281   {"guk",       {"GMZ "}},      /* Gumuz */
282   {"gv",        {"MNX "}},      /* Manx Gaelic */
283   {"ha",        {"HAU "}},      /* Hausa */
284   {"har",       {"HRI "}},      /* Harari */
285   {"he",        {"IWR "}},      /* Hebrew */
286   {"hi",        {"HIN "}},      /* Hindi */
287   {"hil",       {"HIL "}},      /* Hiligaynon */
288   {"hoc",       {"HO  "}},      /* Ho */
289   {"hr",        {"HRV "}},      /* Croatian */
290   {"hsb",       {"USB "}},      /* Upper Sorbian */
291   {"ht",        {"HAI "}},      /* Haitian */
292   {"hu",        {"HUN "}},      /* Hungarian */
293   {"hy",        {"HYE "}},      /* Armenian */
294   {"id",        {"IND "}},      /* Indonesian */
295   {"ig",        {"IBO "}},      /* Igbo */
296   {"igb",       {"EBI "}},      /* Ebira */
297   {"inh",       {"ING "}},      /* Ingush */
298   {"is",        {"ISL "}},      /* Icelandic */
299   {"it",        {"ITA "}},      /* Italian */
300   {"iu",        {"INU "}},      /* Inuktitut */
301   {"ja",        {"JAN "}},      /* Japanese */
302   {"jv",        {"JAV "}},      /* Javanese */
303   {"ka",        {"KAT "}},      /* Georgian */
304   {"kam",       {"KMB "}},      /* Kamba (Kenya) */
305   {"kbd",       {"KAB "}},      /* Kabardian */
306   {"kdr",       {"KRM "}},      /* Karaim */
307   {"kdt",       {"KUY "}},      /* Kuy */
308   {"kfr",       {"KAC "}},      /* Kachchi */
309   {"kfy",       {"KMN "}},      /* Kumaoni */
310   {"kha",       {"KSI "}},      /* Khasi */
311   {"khw",       {"KHW "}},      /* Khowar */
312   {"ki",        {"KIK "}},      /* Kikuyu */
313   {"kk",        {"KAZ "}},      /* Kazakh */
314   {"kl",        {"GRN "}},      /* Kalaallisut */
315   {"kln",       {"KAL "}},      /* Kalenjin */
316   {"km",        {"KHM "}},      /* Central Khmer */
317   {"kmw",       {"KMO "}},      /* Komo (Democratic Republic of Congo) */
318   {"kn",        {"KAN "}},      /* Kannada */
319   {"ko",        {"KOR "}},      /* Korean */
320   {"koi",       {"KOP "}},      /* Komi-Permyak */
321   {"kok",       {"KOK "}},      /* Konkani */
322   {"kpe",       {"KPL "}},      /* Kpelle */
323   {"kpv",       {"KOZ "}},      /* Komi-Zyrian */
324   {"kpy",       {"KYK "}},      /* Koryak */
325   {"kqy",       {"KRT "}},      /* Koorete */
326   {"kr",        {"KNR "}},      /* Kanuri */
327   {"kri",       {"KRI "}},      /* Krio */
328   {"krl",       {"KRL "}},      /* Karelian */
329   {"kru",       {"KUU "}},      /* Kurukh */
330   {"ks",        {"KSH "}},      /* Kashmiri */
331   {"ku",        {"KUR "}},      /* Kurdish */
332   {"kum",       {"KUM "}},      /* Kumyk */
333   {"kvd",       {"KUI "}},      /* Kui (Indonesia) */
334   {"kxu",       {"KUI "}},      /* Kui (India) */
335   {"ky",        {"KIR "}},      /* Kirghiz */
336   {"la",        {"LAT "}},      /* Latin */
337   {"lad",       {"JUD "}},      /* Ladino */
338   {"lb",        {"LTZ "}},      /* Luxembourgish */
339   {"lbe",       {"LAK "}},      /* Lak */
340   {"lbj",       {"LDK "}},      /* Ladakhi */
341   {"lif",       {"LMB "}},      /* Limbu */
342   {"lld",       {"LAD "}},      /* Ladin */
343   {"ln",        {"LIN "}},      /* Lingala */
344   {"lo",        {"LAO "}},      /* Lao */
345   {"lt",        {"LTH "}},      /* Lithuanian */
346   {"luo",       {"LUO "}},      /* Luo (Kenya and Tanzania) */
347   {"luw",       {"LUO "}},      /* Luo (Cameroon) */
348   {"lv",        {"LVI "}},      /* Latvian */
349   {"lzz",       {"LAZ "}},      /* Laz */
350   {"mai",       {"MTH "}},      /* Maithili */
351   {"mdc",       {"MLE "}},      /* Male (Papua New Guinea) */
352   {"mdf",       {"MOK "}},      /* Moksha */
353   {"mdy",       {"MLE "}},      /* Male (Ethiopia) */
354   {"men",       {"MDE "}},      /* Mende (Sierra Leone) */
355   {"mg",        {"MLG "}},      /* Malagasy */
356   {"mi",        {"MRI "}},      /* Maori */
357   {"mk",        {"MKD "}},      /* Macedonian */
358   {"ml",        {"MLR "}},      /* Malayalam */
359   {"mn",        {"MNG "}},      /* Mongolian */
360   {"mnc",       {"MCH "}},      /* Manchu */
361   {"mni",       {"MNI "}},      /* Manipuri */
362   {"mnk",       {"MND "}},      /* Mandinka */
363   {"mns",       {"MAN "}},      /* Mansi */
364   {"mnw",       {"MON "}},      /* Mon */
365   {"mo",        {"MOL "}},      /* Moldavian */
366   {"moh",       {"MOH "}},      /* Mohawk */
367   {"mpe",       {"MAJ "}},      /* Majang */
368   {"mr",        {"MAR "}},      /* Marathi */
369   {"ms",        {"MLY "}},      /* Malay */
370   {"mt",        {"MTS "}},      /* Maltese */
371   {"mwr",       {"MAW "}},      /* Marwari */
372   {"my",        {"BRM "}},      /* Burmese */
373   {"mym",       {"MEN "}},      /* Me'en */
374   {"myv",       {"ERZ "}},      /* Erzya */
375   {"nb",        {"NOR "}},      /* Norwegian BokmÃ¥l */
376   {"nco",       {"SIB "}},      /* Sibe */
377   {"ne",        {"NEP "}},      /* Nepali */
378   {"new",       {"NEW "}},      /* Newari */
379   {"ng",        {"NDG "}},      /* Ndonga */
380   {"ngl",       {"LMW "}},      /* Lomwe */
381   {"niu",       {"NIU "}},      /* Niuean */
382   {"niv",       {"GIL "}},      /* Gilyak */
383   {"nl",        {"NLD "}},      /* Dutch */
384   {"nn",        {"NYN "}},      /* Norwegian Nynorsk */
385   {"no",        {"NOR "}},      /* Norwegian (deprecated) */
386   {"nog",       {"NOG "}},      /* Nogai */
387   {"nqo",       {"NKO "}},      /* N'Ko */
388   {"nsk",       {"NAS "}},      /* Naskapi */
389   {"ny",        {"CHI "}},      /* Nyanja */
390   {"oc",        {"OCI "}},      /* Occitan (post 1500) */
391   {"oj",        {"OJB "}},      /* Ojibwa */
392   {"om",        {"ORO "}},      /* Oromo */
393   {"or",        {"ORI "}},      /* Oriya */
394   {"os",        {"OSS "}},      /* Ossetian */
395   {"pa",        {"PAN "}},      /* Panjabi */
396   {"pi",        {"PAL "}},      /* Pali */
397   {"pl",        {"PLK "}},      /* Polish */
398   {"plp",       {"PAP "}},      /* Palpa */
399   {"prs",       {"DRI "}},      /* Dari */
400   {"ps",        {"PAS "}},      /* Pushto */
401   {"pt",        {"PTG "}},      /* Portuguese */
402   {"raj",       {"RAJ "}},      /* Rajasthani */
403   {"ria",       {"RIA "}},      /* Riang (India) */
404   {"ril",       {"RIA "}},      /* Riang (Myanmar) */
405   {"ro",        {"ROM "}},      /* Romanian */
406   {"rom",       {"ROY "}},      /* Romany */
407   {"ru",        {"RUS "}},      /* Russian */
408   {"rue",       {"RSY "}},      /* Rusyn */
409   {"sa",        {"SAN "}},      /* Sanskrit */
410   {"sah",       {"YAK "}},      /* Yakut */
411   {"sat",       {"SAT "}},      /* Santali */
412   {"sck",       {"SAD "}},      /* Sadri */
413   {"sd",        {"SND "}},      /* Sindhi */
414   {"se",        {"NSM "}},      /* Northern Sami */
415   {"seh",       {"SNA "}},      /* Sena */
416   {"sel",       {"SEL "}},      /* Selkup */
417   {"sg",        {"SGO "}},      /* Sango */
418   {"shn",       {"SHN "}},      /* Shan */
419   {"si",        {"SNH "}},      /* Sinhala */
420   {"sid",       {"SID "}},      /* Sidamo */
421   {"sjd",       {"KSM "}},      /* Kildin Sami */
422   {"sk",        {"SKY "}},      /* Slovak */
423   {"skr",       {"SRK "}},      /* Seraiki */
424   {"sl",        {"SLV "}},      /* Slovenian */
425   {"sm",        {"SMO "}},      /* Samoan */
426   {"sma",       {"SSM "}},      /* Southern Sami */
427   {"smj",       {"LSM "}},      /* Lule Sami */
428   {"smn",       {"ISM "}},      /* Inari Sami */
429   {"sms",       {"SKS "}},      /* Skolt Sami */
430   {"snk",       {"SNK "}},      /* Soninke */
431   {"so",        {"SML "}},      /* Somali */
432   {"sq",        {"SQI "}},      /* Albanian */
433   {"sr",        {"SRB "}},      /* Serbian */
434   {"srr",       {"SRR "}},      /* Serer */
435   {"suq",       {"SUR "}},      /* Suri */
436   {"sv",        {"SVE "}},      /* Swedish */
437   {"sva",       {"SVA "}},      /* Svan */
438   {"sw",        {"SWK "}},      /* Swahili */
439   {"swb",       {"CMR "}},      /* Comorian */
440   {"syr",       {"SYR "}},      /* Syriac */
441   {"ta",        {"TAM "}},      /* Tamil */
442   {"tcy",       {"TUL "}},      /* Tulu */
443   {"te",        {"TEL "}},      /* Telugu */
444   {"tg",        {"TAJ "}},      /* Tajik */
445   {"th",        {"THA "}},      /* Thai */
446   {"ti",        {"TGY "}},      /* Tigrinya */
447   {"tig",       {"TGR "}},      /* Tigre */
448   {"tk",        {"TKM "}},      /* Turkmen */
449   {"tn",        {"TNA "}},      /* Tswana */
450   {"tnz",       {"TNG "}},      /* Tonga (Thailand) */
451   {"to",        {"TNG "}},      /* Tonga (Tonga Islands) */
452   {"tog",       {"TNG "}},      /* Tonga (Nyasa) */
453   {"toi",       {"TNG "}},      /* Tonga (Zambia) */
454   {"tr",        {"TRK "}},      /* Turkish */
455   {"ts",        {"TSG "}},      /* Tsonga */
456   {"tt",        {"TAT "}},      /* Tatar */
457   {"tw",        {"TWI "}},      /* Twi */
458   {"ty",        {"THT "}},      /* Tahitian */
459   {"udm",       {"UDM "}},      /* Udmurt */
460   {"ug",        {"UYG "}},      /* Uighur */
461   {"uk",        {"UKR "}},      /* Ukrainian */
462   {"unr",       {"MUN "}},      /* Mundari */
463   {"ur",        {"URD "}},      /* Urdu */
464   {"uz",        {"UZB "}},      /* Uzbek */
465   {"ve",        {"VEN "}},      /* Venda */
466   {"vi",        {"VIT "}},      /* Vietnamese */
467   {"wbm",       {"WA  "}},      /* Wa */
468   {"wbr",       {"WAG "}},      /* Wagdi */
469   {"wo",        {"WLF "}},      /* Wolof */
470   {"xal",       {"KLM "}},      /* Kalmyk */
471   {"xh",        {"XHS "}},      /* Xhosa */
472   {"xom",       {"KMO "}},      /* Komo (Sudan) */
473   {"xsl",       {"SSL "}},      /* South Slavey */
474   {"yi",        {"JII "}},      /* Yiddish */
475   {"yo",        {"YBA "}},      /* Yoruba */
476   {"yso",       {"NIS "}},      /* Nisi (China) */
477   {"zh-cn",     {"ZHS "}},      /* Chinese (China) */
478   {"zh-hk",     {"ZHH "}},      /* Chinese (Hong Kong) */
479   {"zh-mo",     {"ZHT "}},      /* Chinese (Macao) */
480   {"zh-sg",     {"ZHS "}},      /* Chinese (Singapore) */
481   {"zh-tw",     {"ZHT "}},      /* Chinese (Taiwan) */
482   {"zne",       {"ZND "}},      /* Zande */
483   {"zu",        {"ZUL "}}       /* Zulu */
484
485   /* I couldn't find the language id for these */
486
487 /*{"??",        {"AGW "}},*/    /* Agaw */
488 /*{"??",        {"ALS "}},*/    /* Alsatian */
489 /*{"??",        {"ALT "}},*/    /* Altai */
490 /*{"??",        {"ARK "}},*/    /* Arakanese */
491 /*{"??",        {"ATH "}},*/    /* Athapaskan */
492 /*{"??",        {"BAG "}},*/    /* Baghelkhandi */
493 /*{"??",        {"BAL "}},*/    /* Balkar */
494 /*{"??",        {"BAU "}},*/    /* Baule */
495 /*{"??",        {"BBR "}},*/    /* Berber */
496 /*{"??",        {"BCR "}},*/    /* Bible Cree */
497 /*{"??",        {"BEL "}},*/    /* Belarussian */
498 /*{"??",        {"BIL "}},*/    /* Bilen */
499 /*{"??",        {"BKF "}},*/    /* Blackfoot */
500 /*{"??",        {"BLN "}},*/    /* Balante */
501 /*{"??",        {"BML "}},*/    /* Bamileke */
502 /*{"??",        {"BRI "}},*/    /* Braj Bhasha */
503 /*{"??",        {"CHG "}},*/    /* Chaha Gurage */
504 /*{"??",        {"CHH "}},*/    /* Chattisgarhi */
505 /*{"??",        {"CHK "}},*/    /* Chukchi */
506 /*{"??",        {"DJR "}},*/    /* Djerma */
507 /*{"??",        {"DNG "}},*/    /* Dangme */
508 /*{"??",        {"ECR "}},*/    /* Eastern Cree */
509 /*{"??",        {"FAN "}},*/    /* French Antillean */
510 /*{"??",        {"FLE "}},*/    /* Flemish */
511 /*{"??",        {"FNE "}},*/    /* Forest Nenets */
512 /*{"??",        {"FTA "}},*/    /* Futa */
513 /*{"??",        {"GAR "}},*/    /* Garshuni */
514 /*{"??",        {"GEZ "}},*/    /* Ge'ez */
515 /*{"??",        {"HAL "}},*/    /* Halam */
516 /*{"??",        {"HAR "}},*/    /* Harauti */
517 /*{"??",        {"HAW "}},*/    /* Hawaiin */
518 /*{"??",        {"HBN "}},*/    /* Hammer-Banna */
519 /*{"??",        {"HMA "}},*/    /* High Mari */
520 /*{"??",        {"HND "}},*/    /* Hindko */
521 /*{"??",        {"IJO "}},*/    /* Ijo */
522 /*{"??",        {"ILO "}},*/    /* Ilokano */
523 /*{"??",        {"IRT "}},*/    /* Irish Traditional */
524 /*{"??",        {"JUL "}},*/    /* Jula */
525 /*{"??",        {"KAR "}},*/    /* Karachay */
526 /*{"??",        {"KEB "}},*/    /* Kebena */
527 /*{"??",        {"KGE "}},*/    /* Khutsuri Georgian */
528 /*{"??",        {"KHA "}},*/    /* Khakass */
529 /*{"??",        {"KHK "}},*/    /* Khanty-Kazim */
530 /*{"??",        {"KHS "}},*/    /* Khanty-Shurishkar */
531 /*{"??",        {"KHV "}},*/    /* Khanty-Vakhi */
532 /*{"??",        {"KIS "}},*/    /* Kisii */
533 /*{"??",        {"KKN "}},*/    /* Kokni */
534 /*{"??",        {"KMS "}},*/    /* Komso */
535 /*{"??",        {"KOD "}},*/    /* Kodagu */
536 /*{"??",        {"KOH "}},*/    /* Korean Old Hangul */
537 /*{"??",        {"KON "}},*/    /* Kikongo */
538 /*{"??",        {"KRK "}},*/    /* Karakalpak */
539 /*{"??",        {"KRN "}},*/    /* Karen */
540 /*{"??",        {"KUL "}},*/    /* Kulvi */
541 /*{"??",        {"LAH "}},*/    /* Lahuli */
542 /*{"??",        {"LAM "}},*/    /* Lambani */
543 /*{"??",        {"LCR "}},*/    /* L-Cree */
544 /*{"??",        {"LEZ "}},*/    /* Lezgi */
545 /*{"??",        {"LMA "}},*/    /* Low Mari */
546 /*{"??",        {"LUB "}},*/    /* Luba */
547 /*{"??",        {"LUG "}},*/    /* Luganda */
548 /*{"??",        {"LUH "}},*/    /* Luhya */
549 /*{"??",        {"MAK "}},*/    /* Makua */
550 /*{"??",        {"MAL "}},*/    /* Malayalam Traditional */
551 /*{"??",        {"MBN "}},*/    /* Mbundu */
552 /*{"??",        {"MIZ "}},*/    /* Mizo */
553 /*{"??",        {"MLN "}},*/    /* Malinke */
554 /*{"??",        {"MNK "}},*/    /* Maninka */
555 /*{"??",        {"MOR "}},*/    /* Moroccan */
556 /*{"??",        {"NAG "}},*/    /* Naga-Assamese */
557 /*{"??",        {"NCR "}},*/    /* N-Cree */
558 /*{"??",        {"NDB "}},*/    /* Ndebele */
559 /*{"??",        {"NGR "}},*/    /* Nagari */
560 /*{"??",        {"NHC "}},*/    /* Norway House Cree */
561 /*{"??",        {"NKL "}},*/    /* Nkole */
562 /*{"??",        {"NTA "}},*/    /* Northern Tai */
563 /*{"??",        {"OCR "}},*/    /* Oji-Cree */
564 /*{"??",        {"PAA "}},*/    /* Palestinian Aramaic */
565 /*{"??",        {"PGR "}},*/    /* Polytonic Greek */
566 /*{"??",        {"PLG "}},*/    /* Palaung */
567 /*{"??",        {"QIN "}},*/    /* Chin */
568 /*{"??",        {"RBU "}},*/    /* Russian Buriat */
569 /*{"??",        {"RCR "}},*/    /* R-Cree */
570 /*{"??",        {"RMS "}},*/    /* Rhaeto-Romanic */
571 /*{"??",        {"RUA "}},*/    /* Ruanda */
572 /*{"??",        {"SAY "}},*/    /* Sayisi */
573 /*{"??",        {"SEK "}},*/    /* Sekota */
574 /*{"??",        {"SIG "}},*/    /* Silte Gurage */
575 /*{"??",        {"SLA "}},*/    /* Slavey */
576 /*{"??",        {"SOG "}},*/    /* Sodo Gurage */
577 /*{"??",        {"SOT "}},*/    /* Sotho */
578 /*{"??",        {"SWA "}},*/    /* Swadaya Aramaic */
579 /*{"??",        {"SWZ "}},*/    /* Swazi */
580 /*{"??",        {"SXT "}},*/    /* Sutu */
581 /*{"??",        {"TAB "}},*/    /* Tabasaran */
582 /*{"??",        {"TCR "}},*/    /* TH-Cree */
583 /*{"??",        {"TGN "}},*/    /* Tongan */
584 /*{"??",        {"TMN "}},*/    /* Temne */
585 /*{"??",        {"TNE "}},*/    /* Tundra Nenets */
586 /*{"??",        {"TOD "}},*/    /* Todo */
587 /*{"??",        {"TUA "}},*/    /* Turoyo Aramaic */
588 /*{"??",        {"TUV "}},*/    /* Tuvin */
589 /*{"??",        {"WCR "}},*/    /* West-Cree */
590 /*{"??",        {"XBD "}},*/    /* Tai Lue */
591 /*{"??",        {"YCR "}},*/    /* Y-Cree */
592 /*{"??",        {"YIC "}},*/    /* Yi Classic */
593 /*{"??",        {"YIM "}},*/    /* Yi Modern */
594 /*{"??",        {"ZHP "}},*/    /* Chinese Phonetic */
595 };
596
597 static int
598 lang_compare_first_component (gconstpointer pa,
599                               gconstpointer pb)
600 {
601   const char *a = pa, *b = pb;
602   unsigned int da, db;
603   const char *p;
604
605   p = strstr (a, "-");
606   da = p ? (unsigned int) (p - a) : strlen (a);
607
608   p = strstr (b, "-");
609   db = p ? (unsigned int) (p - b) : strlen (b);
610    
611   return strncmp (a, b, MAX (da, db));
612 }
613
614 /**
615  * pango_ot_tag_from_language:
616  * @language: A #PangoLanguage, or %NULL
617  *
618  * Finds the OpenType language-system tag best describing @language.
619  *
620  * Return value: #PangoOTTag best matching @language or
621  * %PANGO_OT_TAG_DEFAULT_LANGUAGE if none found or if @language
622  * is %NULL.
623  *
624  * Since: 1.18
625  **/
626 PangoOTTag
627 pango_ot_tag_from_language (PangoLanguage *language)
628 {
629   const char *lang_str;
630   LangTag *lang_tag;
631
632   if (language == NULL)
633     return PANGO_OT_TAG_DEFAULT_LANGUAGE;
634
635   lang_str = pango_language_to_string (language);
636
637   /* find a language matching in the first component */
638   lang_tag = bsearch (lang_str, ot_languages,
639                       G_N_ELEMENTS (ot_languages), sizeof (LangTag),
640                       lang_compare_first_component);
641
642   /* we now need to find the best language matching */
643   if (lang_tag)
644     {
645       gboolean found = FALSE;
646
647       /* go to the final one matching in the first component */
648       while (lang_tag + 1 < ot_languages + G_N_ELEMENTS (ot_languages) &&
649              lang_compare_first_component (lang_str, lang_tag + 1) == 0)
650         lang_tag++;
651
652       /* go back, find which one matches completely */
653       while (lang_tag >= ot_languages &&
654              lang_compare_first_component (lang_str, lang_tag) == 0)
655         {
656           if (pango_language_matches (language, lang_tag->language))
657             {
658               found = TRUE;
659               break;
660             }
661
662           lang_tag--;
663         }
664
665       if (!found)
666         lang_tag = NULL;
667     }
668
669   if (lang_tag)
670     return GUINT32_FROM_BE (lang_tag->tag.integer);
671
672   return PANGO_OT_TAG_DEFAULT_LANGUAGE;
673 }
674
675 /**
676  * pango_ot_tag_to_language:
677  * @language_tag: A #PangoOTTag OpenType language-system tag
678  *
679  * Finds a #PangoLanguage corresponding to @language_tag.
680  *
681  * Return value: #PangoLanguage best matching @language_tag or
682  * #PangoLanguage corresponding to the string "xx" if none found.
683  *
684  * Since: 1.18
685  **/
686 PangoLanguage *
687 pango_ot_tag_to_language (PangoOTTag language_tag)
688 {
689   int i;
690   guint32 be_tag = GUINT32_TO_BE (language_tag);
691
692   for (i = 0; i < (int) G_N_ELEMENTS (ot_languages); i++)
693     {
694       guint32 tag = ot_languages[i].tag.integer;
695
696       if (tag == be_tag)
697         return pango_language_from_string (ot_languages[i].language);
698     }
699
700   return pango_language_from_string ("xx");
701 }