Move enum types to hb-common.h
[profile/ivi/org.tizen.video-player.git] / src / hb-common.c
1 /*
2  * Copyright (C) 2009,2010  Red Hat, Inc.
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  *
24  * Red Hat Author(s): Behdad Esfahbod
25  */
26
27 #include "hb-private.h"
28
29 HB_BEGIN_DECLS
30
31
32 /* hb_tag_t */
33
34 hb_tag_t
35 hb_tag_from_string (const char *s)
36 {
37   char tag[4];
38   unsigned int i;
39
40   if (!s)
41     return HB_TAG_NONE;
42
43   for (i = 0; i < 4 && s[i]; i++)
44     tag[i] = s[i];
45   for (; i < 4; i++)
46     tag[i] = ' ';
47
48   return HB_TAG_CHAR4 (tag);
49 }
50
51
52 /* hb_language_t */
53
54 struct _hb_language_t {
55   const char s[1];
56 };
57
58 static const char canon_map[256] = {
59    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
60    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
61    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
62   '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
63   '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
64   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
65    0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
66   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
67 };
68
69 static hb_bool_t
70 lang_equal (const void *v1,
71             const void *v2)
72 {
73   const unsigned char *p1 = v1;
74   const unsigned char *p2 = v2;
75
76   while (canon_map[*p1] && canon_map[*p1] == canon_map[*p2])
77     {
78       p1++, p2++;
79     }
80
81   return (canon_map[*p1] == canon_map[*p2]);
82 }
83
84 #if 0
85 static unsigned int
86 lang_hash (const void *key)
87 {
88   const unsigned char *p = key;
89   unsigned int h = 0;
90   while (canon_map[*p])
91     {
92       h = (h << 5) - h + canon_map[*p];
93       p++;
94     }
95
96   return h;
97 }
98 #endif
99
100
101 hb_language_t
102 hb_language_from_string (const char *str)
103 {
104   static unsigned int num_langs;
105   static unsigned int num_alloced;
106   static hb_language_t *langs;
107   unsigned int i;
108   unsigned char *p;
109
110   /* TODO Use a hash table or something */
111
112   if (!str || !*str)
113     return NULL;
114
115   for (i = 0; i < num_langs; i++)
116     if (lang_equal (str, langs[i]->s))
117       return langs[i];
118
119   if (unlikely (num_langs == num_alloced)) {
120     unsigned int new_alloced = 2 * (8 + num_alloced);
121     hb_language_t *new_langs = realloc (langs, new_alloced * sizeof (langs[0]));
122     if (!new_langs)
123       return NULL;
124     num_alloced = new_alloced;
125     langs = new_langs;
126   }
127
128   langs[i] = (hb_language_t) strdup (str);
129   for (p = (unsigned char *) langs[i]->s; *p; p++)
130     *p = canon_map[*p];
131
132   num_langs++;
133
134   return langs[i];
135 }
136
137 const char *
138 hb_language_to_string (hb_language_t language)
139 {
140   return language->s;
141 }
142
143
144 /* hb_script_t */
145
146 static const hb_tag_t script_to_iso15924_tag[] =
147 {
148   HB_TAG('Z','y','y','y'),      /* HB_SCRIPT_COMMON */
149   HB_TAG('Q','a','a','i'),      /* HB_SCRIPT_INHERITED */
150   HB_TAG('A','r','a','b'),      /* HB_SCRIPT_ARABIC */
151   HB_TAG('A','r','m','n'),      /* HB_SCRIPT_ARMENIAN */
152   HB_TAG('B','e','n','g'),      /* HB_SCRIPT_BENGALI */
153   HB_TAG('B','o','p','o'),      /* HB_SCRIPT_BOPOMOFO */
154   HB_TAG('C','h','e','r'),      /* HB_SCRIPT_CHEROKEE */
155   HB_TAG('Q','a','a','c'),      /* HB_SCRIPT_COPTIC */
156   HB_TAG('C','y','r','l'),      /* HB_SCRIPT_CYRILLIC */
157   HB_TAG('D','s','r','t'),      /* HB_SCRIPT_DESERET */
158   HB_TAG('D','e','v','a'),      /* HB_SCRIPT_DEVANAGARI */
159   HB_TAG('E','t','h','i'),      /* HB_SCRIPT_ETHIOPIC */
160   HB_TAG('G','e','o','r'),      /* HB_SCRIPT_GEORGIAN */
161   HB_TAG('G','o','t','h'),      /* HB_SCRIPT_GOTHIC */
162   HB_TAG('G','r','e','k'),      /* HB_SCRIPT_GREEK */
163   HB_TAG('G','u','j','r'),      /* HB_SCRIPT_GUJARATI */
164   HB_TAG('G','u','r','u'),      /* HB_SCRIPT_GURMUKHI */
165   HB_TAG('H','a','n','i'),      /* HB_SCRIPT_HAN */
166   HB_TAG('H','a','n','g'),      /* HB_SCRIPT_HANGUL */
167   HB_TAG('H','e','b','r'),      /* HB_SCRIPT_HEBREW */
168   HB_TAG('H','i','r','a'),      /* HB_SCRIPT_HIRAGANA */
169   HB_TAG('K','n','d','a'),      /* HB_SCRIPT_KANNADA */
170   HB_TAG('K','a','n','a'),      /* HB_SCRIPT_KATAKANA */
171   HB_TAG('K','h','m','r'),      /* HB_SCRIPT_KHMER */
172   HB_TAG('L','a','o','o'),      /* HB_SCRIPT_LAO */
173   HB_TAG('L','a','t','n'),      /* HB_SCRIPT_LATIN */
174   HB_TAG('M','l','y','m'),      /* HB_SCRIPT_MALAYALAM */
175   HB_TAG('M','o','n','g'),      /* HB_SCRIPT_MONGOLIAN */
176   HB_TAG('M','y','m','r'),      /* HB_SCRIPT_MYANMAR */
177   HB_TAG('O','g','a','m'),      /* HB_SCRIPT_OGHAM */
178   HB_TAG('I','t','a','l'),      /* HB_SCRIPT_OLD_ITALIC */
179   HB_TAG('O','r','y','a'),      /* HB_SCRIPT_ORIYA */
180   HB_TAG('R','u','n','r'),      /* HB_SCRIPT_RUNIC */
181   HB_TAG('S','i','n','h'),      /* HB_SCRIPT_SINHALA */
182   HB_TAG('S','y','r','c'),      /* HB_SCRIPT_SYRIAC */
183   HB_TAG('T','a','m','l'),      /* HB_SCRIPT_TAMIL */
184   HB_TAG('T','e','l','u'),      /* HB_SCRIPT_TELUGU */
185   HB_TAG('T','h','a','a'),      /* HB_SCRIPT_THAANA */
186   HB_TAG('T','h','a','i'),      /* HB_SCRIPT_THAI */
187   HB_TAG('T','i','b','t'),      /* HB_SCRIPT_TIBETAN */
188   HB_TAG('C','a','n','s'),      /* HB_SCRIPT_CANADIAN_ABORIGINAL */
189   HB_TAG('Y','i','i','i'),      /* HB_SCRIPT_YI */
190   HB_TAG('T','g','l','g'),      /* HB_SCRIPT_TAGALOG */
191   HB_TAG('H','a','n','o'),      /* HB_SCRIPT_HANUNOO */
192   HB_TAG('B','u','h','d'),      /* HB_SCRIPT_BUHID */
193   HB_TAG('T','a','g','b'),      /* HB_SCRIPT_TAGBANWA */
194
195   /* Unicode-4.0 additions */
196   HB_TAG('B','r','a','i'),      /* HB_SCRIPT_BRAILLE */
197   HB_TAG('C','p','r','t'),      /* HB_SCRIPT_CYPRIOT */
198   HB_TAG('L','i','m','b'),      /* HB_SCRIPT_LIMBU */
199   HB_TAG('O','s','m','a'),      /* HB_SCRIPT_OSMANYA */
200   HB_TAG('S','h','a','w'),      /* HB_SCRIPT_SHAVIAN */
201   HB_TAG('L','i','n','b'),      /* HB_SCRIPT_LINEAR_B */
202   HB_TAG('T','a','l','e'),      /* HB_SCRIPT_TAI_LE */
203   HB_TAG('U','g','a','r'),      /* HB_SCRIPT_UGARITIC */
204
205   /* Unicode-4.1 additions */
206   HB_TAG('T','a','l','u'),      /* HB_SCRIPT_NEW_TAI_LUE */
207   HB_TAG('B','u','g','i'),      /* HB_SCRIPT_BUGINESE */
208   HB_TAG('G','l','a','g'),      /* HB_SCRIPT_GLAGOLITIC */
209   HB_TAG('T','f','n','g'),      /* HB_SCRIPT_TIFINAGH */
210   HB_TAG('S','y','l','o'),      /* HB_SCRIPT_SYLOTI_NAGRI */
211   HB_TAG('X','p','e','o'),      /* HB_SCRIPT_OLD_PERSIAN */
212   HB_TAG('K','h','a','r'),      /* HB_SCRIPT_KHAROSHTHI */
213
214   /* Unicode-5.0 additions */
215   HB_TAG('Z','z','z','z'),      /* HB_SCRIPT_UNKNOWN */
216   HB_TAG('B','a','l','i'),      /* HB_SCRIPT_BALINESE */
217   HB_TAG('X','s','u','x'),      /* HB_SCRIPT_CUNEIFORM */
218   HB_TAG('P','h','n','x'),      /* HB_SCRIPT_PHOENICIAN */
219   HB_TAG('P','h','a','g'),      /* HB_SCRIPT_PHAGS_PA */
220   HB_TAG('N','k','o','o'),      /* HB_SCRIPT_NKO */
221
222   /* Unicode-5.1 additions */
223   HB_TAG('K','a','l','i'),      /* HB_SCRIPT_KAYAH_LI */
224   HB_TAG('L','e','p','c'),      /* HB_SCRIPT_LEPCHA */
225   HB_TAG('R','j','n','g'),      /* HB_SCRIPT_REJANG */
226   HB_TAG('S','u','n','d'),      /* HB_SCRIPT_SUNDANESE */
227   HB_TAG('S','a','u','r'),      /* HB_SCRIPT_SAURASHTRA */
228   HB_TAG('C','h','a','m'),      /* HB_SCRIPT_CHAM */
229   HB_TAG('O','l','c','k'),      /* HB_SCRIPT_OL_CHIKI */
230   HB_TAG('V','a','i','i'),      /* HB_SCRIPT_VAI */
231   HB_TAG('C','a','r','i'),      /* HB_SCRIPT_CARIAN */
232   HB_TAG('L','y','c','i'),      /* HB_SCRIPT_LYCIAN */
233   HB_TAG('L','y','d','i'),      /* HB_SCRIPT_LYDIAN */
234
235   /* Unicode-5.2 additions */
236   HB_TAG('A','v','s','t'),      /* HB_SCRIPT_AVESTAN */
237   HB_TAG('B','a','m','u'),      /* HB_SCRIPT_BAMUM */
238   HB_TAG('E','g','y','p'),      /* HB_SCRIPT_EGYPTIAN_HIEROGLYPHS */
239   HB_TAG('A','r','m','i'),      /* HB_SCRIPT_IMPERIAL_ARAMAIC */
240   HB_TAG('P','h','l','i'),      /* HB_SCRIPT_INSCRIPTIONAL_PAHLAVI */
241   HB_TAG('P','r','t','i'),      /* HB_SCRIPT_INSCRIPTIONAL_PARTHIAN */
242   HB_TAG('J','a','v','a'),      /* HB_SCRIPT_JAVANESE */
243   HB_TAG('K','t','h','i'),      /* HB_SCRIPT_KAITHI */
244   HB_TAG('L','i','s','u'),      /* HB_SCRIPT_LISU */
245   HB_TAG('M','t','e','i'),      /* HB_SCRIPT_MEETEI_MAYEK */
246   HB_TAG('S','a','r','b'),      /* HB_SCRIPT_OLD_SOUTH_ARABIAN */
247   HB_TAG('O','r','k','h'),      /* HB_SCRIPT_OLD_TURKIC */
248   HB_TAG('S','a','m','r'),      /* HB_SCRIPT_SAMARITAN */
249   HB_TAG('L','a','n','a'),      /* HB_SCRIPT_TAI_THAM */
250   HB_TAG('T','a','v','t'),      /* HB_SCRIPT_TAI_VIET */
251
252   /* Unicode-6.0 additions */
253   HB_TAG('B','a','t','k'),      /* HB_SCRIPT_BATAK */
254   HB_TAG('B','r','a','h'),      /* HB_SCRIPT_BRAHMI */
255   HB_TAG('M','a','n','d')       /* HB_SCRIPT_MANDAIC */
256 };
257
258 struct tag_script_pair {
259   hb_tag_t tag;
260   hb_script_t script;
261 };
262 static const struct tag_script_pair script_from_iso15924_tag[] =
263 {
264   {HB_TAG('A','r','a','b'), HB_SCRIPT_ARABIC},
265   {HB_TAG('A','r','m','i'), HB_SCRIPT_IMPERIAL_ARAMAIC},
266   {HB_TAG('A','r','m','n'), HB_SCRIPT_ARMENIAN},
267   {HB_TAG('A','v','s','t'), HB_SCRIPT_AVESTAN},
268   {HB_TAG('B','a','l','i'), HB_SCRIPT_BALINESE},
269   {HB_TAG('B','a','m','u'), HB_SCRIPT_BAMUM},
270   {HB_TAG('B','a','t','k'), HB_SCRIPT_BATAK},
271   {HB_TAG('B','e','n','g'), HB_SCRIPT_BENGALI},
272   {HB_TAG('B','o','p','o'), HB_SCRIPT_BOPOMOFO},
273   {HB_TAG('B','r','a','h'), HB_SCRIPT_BRAHMI},
274   {HB_TAG('B','r','a','i'), HB_SCRIPT_BRAILLE},
275   {HB_TAG('B','u','g','i'), HB_SCRIPT_BUGINESE},
276   {HB_TAG('B','u','h','d'), HB_SCRIPT_BUHID},
277   {HB_TAG('C','a','n','s'), HB_SCRIPT_CANADIAN_ABORIGINAL},
278   {HB_TAG('C','a','r','i'), HB_SCRIPT_CARIAN},
279   {HB_TAG('C','h','a','m'), HB_SCRIPT_CHAM},
280   {HB_TAG('C','h','e','r'), HB_SCRIPT_CHEROKEE},
281   {HB_TAG('C','p','r','t'), HB_SCRIPT_CYPRIOT},
282   {HB_TAG('C','y','r','l'), HB_SCRIPT_CYRILLIC},
283   {HB_TAG('C','y','r','s'), HB_SCRIPT_CYRILLIC},
284   {HB_TAG('D','e','v','a'), HB_SCRIPT_DEVANAGARI},
285   {HB_TAG('D','s','r','t'), HB_SCRIPT_DESERET},
286   {HB_TAG('E','g','y','p'), HB_SCRIPT_EGYPTIAN_HIEROGLYPHS},
287   {HB_TAG('E','t','h','i'), HB_SCRIPT_ETHIOPIC},
288   {HB_TAG('G','e','o','a'), HB_SCRIPT_GEORGIAN},
289   {HB_TAG('G','e','o','n'), HB_SCRIPT_GEORGIAN},
290   {HB_TAG('G','e','o','r'), HB_SCRIPT_GEORGIAN},
291   {HB_TAG('G','l','a','g'), HB_SCRIPT_GLAGOLITIC},
292   {HB_TAG('G','o','t','h'), HB_SCRIPT_GOTHIC},
293   {HB_TAG('G','r','e','k'), HB_SCRIPT_GREEK},
294   {HB_TAG('G','u','j','r'), HB_SCRIPT_GUJARATI},
295   {HB_TAG('G','u','r','u'), HB_SCRIPT_GURMUKHI},
296   {HB_TAG('H','a','n','g'), HB_SCRIPT_HANGUL},
297   {HB_TAG('H','a','n','i'), HB_SCRIPT_HAN},
298   {HB_TAG('H','a','n','o'), HB_SCRIPT_HANUNOO},
299   {HB_TAG('H','e','b','r'), HB_SCRIPT_HEBREW},
300   {HB_TAG('H','i','r','a'), HB_SCRIPT_HIRAGANA},
301   {HB_TAG('I','t','a','l'), HB_SCRIPT_OLD_ITALIC},
302   {HB_TAG('J','a','v','a'), HB_SCRIPT_JAVANESE},
303   {HB_TAG('K','a','l','i'), HB_SCRIPT_KAYAH_LI},
304   {HB_TAG('K','a','n','a'), HB_SCRIPT_KATAKANA},
305   {HB_TAG('K','h','a','r'), HB_SCRIPT_KHAROSHTHI},
306   {HB_TAG('K','h','m','r'), HB_SCRIPT_KHMER},
307   {HB_TAG('K','n','d','a'), HB_SCRIPT_KANNADA},
308   {HB_TAG('K','t','h','i'), HB_SCRIPT_KAITHI},
309   {HB_TAG('L','a','n','a'), HB_SCRIPT_TAI_THAM},
310   {HB_TAG('L','a','o','o'), HB_SCRIPT_LAO},
311   {HB_TAG('L','a','t','f'), HB_SCRIPT_LATIN},
312   {HB_TAG('L','a','t','g'), HB_SCRIPT_LATIN},
313   {HB_TAG('L','a','t','n'), HB_SCRIPT_LATIN},
314   {HB_TAG('L','e','p','c'), HB_SCRIPT_LEPCHA},
315   {HB_TAG('L','i','m','b'), HB_SCRIPT_LIMBU},
316   {HB_TAG('L','i','n','b'), HB_SCRIPT_LINEAR_B},
317   {HB_TAG('L','i','s','u'), HB_SCRIPT_LISU},
318   {HB_TAG('L','y','c','i'), HB_SCRIPT_LYCIAN},
319   {HB_TAG('L','y','d','i'), HB_SCRIPT_LYDIAN},
320   {HB_TAG('M','a','n','d'), HB_SCRIPT_MANDAIC},
321   {HB_TAG('M','l','y','m'), HB_SCRIPT_MALAYALAM},
322   {HB_TAG('M','o','n','g'), HB_SCRIPT_MONGOLIAN},
323   {HB_TAG('M','t','e','i'), HB_SCRIPT_MEETEI_MAYEK},
324   {HB_TAG('M','y','m','r'), HB_SCRIPT_MYANMAR},
325   {HB_TAG('N','k','o','o'), HB_SCRIPT_NKO},
326   {HB_TAG('O','g','a','m'), HB_SCRIPT_OGHAM},
327   {HB_TAG('O','l','c','k'), HB_SCRIPT_OL_CHIKI},
328   {HB_TAG('O','r','k','h'), HB_SCRIPT_OLD_TURKIC},
329   {HB_TAG('O','r','y','a'), HB_SCRIPT_ORIYA},
330   {HB_TAG('O','s','m','a'), HB_SCRIPT_OSMANYA},
331   {HB_TAG('P','h','a','g'), HB_SCRIPT_PHAGS_PA},
332   {HB_TAG('P','h','l','i'), HB_SCRIPT_INSCRIPTIONAL_PAHLAVI},
333   {HB_TAG('P','h','n','x'), HB_SCRIPT_PHOENICIAN},
334   {HB_TAG('P','r','t','i'), HB_SCRIPT_INSCRIPTIONAL_PARTHIAN},
335   {HB_TAG('Q','a','a','c'), HB_SCRIPT_COPTIC},
336   {HB_TAG('Q','a','a','i'), HB_SCRIPT_INHERITED},
337   {HB_TAG('R','j','n','g'), HB_SCRIPT_REJANG},
338   {HB_TAG('R','u','n','r'), HB_SCRIPT_RUNIC},
339   {HB_TAG('S','a','m','r'), HB_SCRIPT_SAMARITAN},
340   {HB_TAG('S','a','r','b'), HB_SCRIPT_OLD_SOUTH_ARABIAN},
341   {HB_TAG('S','a','u','r'), HB_SCRIPT_SAURASHTRA},
342   {HB_TAG('S','h','a','w'), HB_SCRIPT_SHAVIAN},
343   {HB_TAG('S','i','n','h'), HB_SCRIPT_SINHALA},
344   {HB_TAG('S','u','n','d'), HB_SCRIPT_SUNDANESE},
345   {HB_TAG('S','y','l','o'), HB_SCRIPT_SYLOTI_NAGRI},
346   {HB_TAG('S','y','r','c'), HB_SCRIPT_SYRIAC},
347   {HB_TAG('S','y','r','e'), HB_SCRIPT_SYRIAC},
348   {HB_TAG('S','y','r','n'), HB_SCRIPT_SYRIAC},
349   {HB_TAG('T','a','g','b'), HB_SCRIPT_TAGBANWA},
350   {HB_TAG('T','a','l','e'), HB_SCRIPT_TAI_LE},
351   {HB_TAG('T','a','l','u'), HB_SCRIPT_NEW_TAI_LUE},
352   {HB_TAG('T','a','m','l'), HB_SCRIPT_TAMIL},
353   {HB_TAG('T','a','v','t'), HB_SCRIPT_TAI_VIET},
354   {HB_TAG('T','e','l','u'), HB_SCRIPT_TELUGU},
355   {HB_TAG('T','f','n','g'), HB_SCRIPT_TIFINAGH},
356   {HB_TAG('T','g','l','g'), HB_SCRIPT_TAGALOG},
357   {HB_TAG('T','h','a','a'), HB_SCRIPT_THAANA},
358   {HB_TAG('T','h','a','i'), HB_SCRIPT_THAI},
359   {HB_TAG('T','i','b','t'), HB_SCRIPT_TIBETAN},
360   {HB_TAG('U','g','a','r'), HB_SCRIPT_UGARITIC},
361   {HB_TAG('V','a','i','i'), HB_SCRIPT_VAI},
362   {HB_TAG('X','p','e','o'), HB_SCRIPT_OLD_PERSIAN},
363   {HB_TAG('X','s','u','x'), HB_SCRIPT_CUNEIFORM},
364   {HB_TAG('Y','i','i','i'), HB_SCRIPT_YI},
365   {HB_TAG('Z','y','y','y'), HB_SCRIPT_COMMON},
366   {HB_TAG('Z','z','z','z'), HB_SCRIPT_UNKNOWN}
367 };
368
369 static int
370 _tag_cmp (hb_tag_t *pa, hb_tag_t *pb)
371 {
372   hb_tag_t a = *pa, b = *pb;
373   return a < b ? -1 : a == b ? 0 : +1;
374 }
375
376
377 hb_script_t
378 hb_script_from_iso15924_tag (hb_tag_t tag)
379 {
380   const struct tag_script_pair *pair;
381
382   /* Be lenient, adjust case (one capital letter followed by three small letters) */
383   tag = (tag & 0xDFDFDFDF) | 0x00202020;
384
385   pair = (const struct tag_script_pair *) bsearch (&tag,
386                                                    script_from_iso15924_tag,
387                                                    ARRAY_LENGTH (script_from_iso15924_tag),
388                                                    sizeof (script_from_iso15924_tag[0]),
389                                                    (hb_compare_func_t) _tag_cmp);
390
391   if (pair)
392     return pair->script;
393
394   /* If it looks right, just use the tag as a script */
395   if (((uint32_t) tag & 0xE0E0E0E0) == 0x40606060)
396     return (hb_script_t) tag;
397
398   /* Otherwise, return unknown */
399   return HB_SCRIPT_UNKNOWN;
400 }
401
402 hb_script_t
403 hb_script_from_string (const char *s)
404 {
405   return hb_script_from_iso15924_tag (hb_tag_from_string (s));
406 }
407
408 hb_tag_t
409 hb_script_to_iso15924_tag (hb_script_t script)
410 {
411   if (likely ((unsigned int) script < ARRAY_LENGTH (script_to_iso15924_tag)))
412     return script_to_iso15924_tag[script];
413
414   /* if script is of the right shape (one capital letter followed by three small letters),
415    * return as is. */
416   if (((uint32_t) script & 0xE0E0E0E0) == 0x40606060)
417     return (hb_tag_t) script;
418
419   /* Otherwise, we don't know what that is */
420   return script_to_iso15924_tag[HB_SCRIPT_UNKNOWN];
421 }
422
423
424 #define LTR HB_DIRECTION_LTR
425 #define RTL HB_DIRECTION_RTL
426 const hb_direction_t horiz_dir[] =
427 {
428   LTR,  /* Zyyy */
429   LTR,  /* Qaai */
430   RTL,  /* Arab */
431   LTR,  /* Armn */
432   LTR,  /* Beng */
433   LTR,  /* Bopo */
434   LTR,  /* Cher */
435   LTR,  /* Qaac */
436   LTR,  /* Cyrl (Cyrs) */
437   LTR,  /* Dsrt */
438   LTR,  /* Deva */
439   LTR,  /* Ethi */
440   LTR,  /* Geor (Geon, Geoa) */
441   LTR,  /* Goth */
442   LTR,  /* Grek */
443   LTR,  /* Gujr */
444   LTR,  /* Guru */
445   LTR,  /* Hani */
446   LTR,  /* Hang */
447   RTL,  /* Hebr */
448   LTR,  /* Hira */
449   LTR,  /* Knda */
450   LTR,  /* Kana */
451   LTR,  /* Khmr */
452   LTR,  /* Laoo */
453   LTR,  /* Latn (Latf, Latg) */
454   LTR,  /* Mlym */
455   LTR,  /* Mong */
456   LTR,  /* Mymr */
457   LTR,  /* Ogam */
458   LTR,  /* Ital */
459   LTR,  /* Orya */
460   LTR,  /* Runr */
461   LTR,  /* Sinh */
462   RTL,  /* Syrc (Syrj, Syrn, Syre) */
463   LTR,  /* Taml */
464   LTR,  /* Telu */
465   RTL,  /* Thaa */
466   LTR,  /* Thai */
467   LTR,  /* Tibt */
468   LTR,  /* Cans */
469   LTR,  /* Yiii */
470   LTR,  /* Tglg */
471   LTR,  /* Hano */
472   LTR,  /* Buhd */
473   LTR,  /* Tagb */
474
475   /* Unicode-4.0 additions */
476   LTR,  /* Brai */
477   RTL,  /* Cprt */
478   LTR,  /* Limb */
479   LTR,  /* Osma */
480   LTR,  /* Shaw */
481   LTR,  /* Linb */
482   LTR,  /* Tale */
483   LTR,  /* Ugar */
484
485   /* Unicode-4.1 additions */
486   LTR,  /* Talu */
487   LTR,  /* Bugi */
488   LTR,  /* Glag */
489   LTR,  /* Tfng */
490   LTR,  /* Sylo */
491   LTR,  /* Xpeo */
492   LTR,  /* Khar */
493
494   /* Unicode-5.0 additions */
495   LTR,  /* Zzzz */
496   LTR,  /* Bali */
497   LTR,  /* Xsux */
498   RTL,  /* Phnx */
499   LTR,  /* Phag */
500   RTL,  /* Nkoo */
501
502   /* Unicode-5.1 additions */
503   LTR,  /* Kali */
504   LTR,  /* Lepc */
505   LTR,  /* Rjng */
506   LTR,  /* Sund */
507   LTR,  /* Saur */
508   LTR,  /* Cham */
509   LTR,  /* Olck */
510   LTR,  /* Vaii */
511   LTR,  /* Cari */
512   LTR,  /* Lyci */
513   LTR,  /* Lydi */
514
515   /* Unicode-5.2 additions */
516   RTL,  /* Avst */
517   LTR,  /* Bamu */
518   LTR,  /* Egyp */
519   RTL,  /* Armi */
520   RTL,  /* Phli */
521   RTL,  /* Prti */
522   LTR,  /* Java */
523   LTR,  /* Kthi */
524   LTR,  /* Lisu */
525   LTR,  /* Mtei */
526   RTL,  /* Sarb */
527   RTL,  /* Orkh */
528   RTL,  /* Samr */
529   LTR,  /* Lana */
530   LTR,  /* Tavt */
531
532   /* Unicode-6.0 additions */
533   LTR,  /* Batk */
534   LTR,  /* Brah */
535   RTL   /* Mand */
536 };
537 #undef LTR
538 #undef RTL
539
540 hb_direction_t
541 hb_script_get_horizontal_direction (hb_script_t script)
542 {
543   if (unlikely ((unsigned int) script >= ARRAY_LENGTH (horiz_dir)))
544     return HB_DIRECTION_LTR;
545
546   return horiz_dir[script];
547 }
548
549
550 HB_END_DECLS