1 /* 2 * Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "hb-private.hh" 18 19 #include "hb-unicode-private.hh" 20 21 #include "ucdn.h" 22 23 static const hb_script_t ucdn_script_translate[] = 24 { 25 HB_SCRIPT_COMMON, 26 HB_SCRIPT_LATIN, 27 HB_SCRIPT_GREEK, 28 HB_SCRIPT_CYRILLIC, 29 HB_SCRIPT_ARMENIAN, 30 HB_SCRIPT_HEBREW, 31 HB_SCRIPT_ARABIC, 32 HB_SCRIPT_SYRIAC, 33 HB_SCRIPT_THAANA, 34 HB_SCRIPT_DEVANAGARI, 35 HB_SCRIPT_BENGALI, 36 HB_SCRIPT_GURMUKHI, 37 HB_SCRIPT_GUJARATI, 38 HB_SCRIPT_ORIYA, 39 HB_SCRIPT_TAMIL, 40 HB_SCRIPT_TELUGU, 41 HB_SCRIPT_KANNADA, 42 HB_SCRIPT_MALAYALAM, 43 HB_SCRIPT_SINHALA, 44 HB_SCRIPT_THAI, 45 HB_SCRIPT_LAO, 46 HB_SCRIPT_TIBETAN, 47 HB_SCRIPT_MYANMAR, 48 HB_SCRIPT_GEORGIAN, 49 HB_SCRIPT_HANGUL, 50 HB_SCRIPT_ETHIOPIC, 51 HB_SCRIPT_CHEROKEE, 52 HB_SCRIPT_CANADIAN_SYLLABICS, 53 HB_SCRIPT_OGHAM, 54 HB_SCRIPT_RUNIC, 55 HB_SCRIPT_KHMER, 56 HB_SCRIPT_MONGOLIAN, 57 HB_SCRIPT_HIRAGANA, 58 HB_SCRIPT_KATAKANA, 59 HB_SCRIPT_BOPOMOFO, 60 HB_SCRIPT_HAN, 61 HB_SCRIPT_YI, 62 HB_SCRIPT_OLD_ITALIC, 63 HB_SCRIPT_GOTHIC, 64 HB_SCRIPT_DESERET, 65 HB_SCRIPT_INHERITED, 66 HB_SCRIPT_TAGALOG, 67 HB_SCRIPT_HANUNOO, 68 HB_SCRIPT_BUHID, 69 HB_SCRIPT_TAGBANWA, 70 HB_SCRIPT_LIMBU, 71 HB_SCRIPT_TAI_LE, 72 HB_SCRIPT_LINEAR_B, 73 HB_SCRIPT_UGARITIC, 74 HB_SCRIPT_SHAVIAN, 75 HB_SCRIPT_OSMANYA, 76 HB_SCRIPT_CYPRIOT, 77 HB_SCRIPT_BRAILLE, 78 HB_SCRIPT_BUGINESE, 79 HB_SCRIPT_COPTIC, 80 HB_SCRIPT_NEW_TAI_LUE, 81 HB_SCRIPT_GLAGOLITIC, 82 HB_SCRIPT_TIFINAGH, 83 HB_SCRIPT_SYLOTI_NAGRI, 84 HB_SCRIPT_OLD_PERSIAN, 85 HB_SCRIPT_KHAROSHTHI, 86 HB_SCRIPT_BALINESE, 87 HB_SCRIPT_CUNEIFORM, 88 HB_SCRIPT_PHOENICIAN, 89 HB_SCRIPT_PHAGS_PA, 90 HB_SCRIPT_NKO, 91 HB_SCRIPT_SUNDANESE, 92 HB_SCRIPT_LEPCHA, 93 HB_SCRIPT_OL_CHIKI, 94 HB_SCRIPT_VAI, 95 HB_SCRIPT_SAURASHTRA, 96 HB_SCRIPT_KAYAH_LI, 97 HB_SCRIPT_REJANG, 98 HB_SCRIPT_LYCIAN, 99 HB_SCRIPT_CARIAN, 100 HB_SCRIPT_LYDIAN, 101 HB_SCRIPT_CHAM, 102 HB_SCRIPT_TAI_THAM, 103 HB_SCRIPT_TAI_VIET, 104 HB_SCRIPT_AVESTAN, 105 HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, 106 HB_SCRIPT_SAMARITAN, 107 HB_SCRIPT_LISU, 108 HB_SCRIPT_BAMUM, 109 HB_SCRIPT_JAVANESE, 110 HB_SCRIPT_MEETEI_MAYEK, 111 HB_SCRIPT_IMPERIAL_ARAMAIC, 112 HB_SCRIPT_OLD_SOUTH_ARABIAN, 113 HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, 114 HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, 115 HB_SCRIPT_OLD_TURKIC, 116 HB_SCRIPT_KAITHI, 117 HB_SCRIPT_BATAK, 118 HB_SCRIPT_BRAHMI, 119 HB_SCRIPT_MANDAIC, 120 HB_SCRIPT_CHAKMA, 121 HB_SCRIPT_MEROITIC_CURSIVE, 122 HB_SCRIPT_MEROITIC_HIEROGLYPHS, 123 HB_SCRIPT_MIAO, 124 HB_SCRIPT_SHARADA, 125 HB_SCRIPT_SORA_SOMPENG, 126 HB_SCRIPT_TAKRI, 127 HB_SCRIPT_UNKNOWN, 128 HB_SCRIPT_BASSA_VAH, 129 HB_SCRIPT_CAUCASIAN_ALBANIAN, 130 HB_SCRIPT_DUPLOYAN, 131 HB_SCRIPT_ELBASAN, 132 HB_SCRIPT_GRANTHA, 133 HB_SCRIPT_KHOJKI, 134 HB_SCRIPT_KHUDAWADI, 135 HB_SCRIPT_LINEAR_A, 136 HB_SCRIPT_MAHAJANI, 137 HB_SCRIPT_MANICHAEAN, 138 HB_SCRIPT_MENDE_KIKAKUI, 139 HB_SCRIPT_MODI, 140 HB_SCRIPT_MRO, 141 HB_SCRIPT_NABATAEAN, 142 HB_SCRIPT_OLD_NORTH_ARABIAN, 143 HB_SCRIPT_OLD_PERMIC, 144 HB_SCRIPT_PAHAWH_HMONG, 145 HB_SCRIPT_PALMYRENE, 146 HB_SCRIPT_PAU_CIN_HAU, 147 HB_SCRIPT_PSALTER_PAHLAVI, 148 HB_SCRIPT_SIDDHAM, 149 HB_SCRIPT_TIRHUTA, 150 HB_SCRIPT_WARANG_CITI, 151 HB_SCRIPT_AHOM, 152 HB_SCRIPT_ANATOLIAN_HIEROGLYPHS, 153 HB_SCRIPT_HATRAN, 154 HB_SCRIPT_MULTANI, 155 HB_SCRIPT_OLD_HUNGARIAN, 156 HB_SCRIPT_SIGNWRITING, 157 HB_SCRIPT_ADLAM, 158 HB_SCRIPT_BHAIKSUKI, 159 HB_SCRIPT_MARCHEN, 160 HB_SCRIPT_NEWA, 161 HB_SCRIPT_OSAGE, 162 HB_SCRIPT_TANGUT, 163 HB_SCRIPT_MASARAM_GONDI, 164 HB_SCRIPT_NUSHU, 165 HB_SCRIPT_SOYOMBO, 166 HB_SCRIPT_ZANABAZAR_SQUARE, 167 HB_SCRIPT_DOGRA, 168 HB_SCRIPT_GUNJALA_GONDI, 169 HB_SCRIPT_HANIFI_ROHINGYA, 170 HB_SCRIPT_MAKASAR, 171 HB_SCRIPT_MEDEFAIDRIN, 172 HB_SCRIPT_OLD_SOGDIAN, 173 HB_SCRIPT_SOGDIAN, 174 }; 175 176 static hb_unicode_combining_class_t 177 hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs HB_UNUSED, 178 hb_codepoint_t unicode, 179 void *user_data HB_UNUSED) 180 { 181 return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode); 182 } 183 184 static unsigned int 185 hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs HB_UNUSED, 186 hb_codepoint_t unicode, 187 void *user_data HB_UNUSED) 188 { 189 int w = ucdn_get_east_asian_width(unicode); 190 return (w == UCDN_EAST_ASIAN_F || w == UCDN_EAST_ASIAN_W) ? 2 : 1; 191 } 192 193 static hb_unicode_general_category_t 194 hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED, 195 hb_codepoint_t unicode, 196 void *user_data HB_UNUSED) 197 { 198 return (hb_unicode_general_category_t)ucdn_get_general_category(unicode); 199 } 200 201 static hb_codepoint_t 202 hb_ucdn_mirroring(hb_unicode_funcs_t *ufuncs HB_UNUSED, 203 hb_codepoint_t unicode, 204 void *user_data HB_UNUSED) 205 { 206 return ucdn_mirror(unicode); 207 } 208 209 static hb_script_t 210 hb_ucdn_script(hb_unicode_funcs_t *ufuncs HB_UNUSED, 211 hb_codepoint_t unicode, 212 void *user_data HB_UNUSED) 213 { 214 return ucdn_script_translate[ucdn_get_script(unicode)]; 215 } 216 217 static hb_bool_t 218 hb_ucdn_compose(hb_unicode_funcs_t *ufuncs HB_UNUSED, 219 hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab, 220 void *user_data HB_UNUSED) 221 { 222 return ucdn_compose(ab, a, b); 223 } 224 225 static hb_bool_t 226 hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs HB_UNUSED, 227 hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b, 228 void *user_data HB_UNUSED) 229 { 230 return ucdn_decompose(ab, a, b); 231 } 232 233 static unsigned int 234 hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED, 235 hb_codepoint_t u, hb_codepoint_t *decomposed, 236 void *user_data HB_UNUSED) 237 { 238 return ucdn_compat_decompose(u, decomposed); 239 } 240 241 static hb_unicode_funcs_t *static_ucdn_funcs = nullptr; 242 243 #ifdef HB_USE_ATEXIT 244 static 245 void free_static_ucdn_funcs (void) 246 { 247 retry: 248 hb_unicode_funcs_t *ucdn_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs); 249 if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, ucdn_funcs, nullptr)) 250 goto retry; 251 252 hb_unicode_funcs_destroy (ucdn_funcs); 253 } 254 #endif 255 256 extern "C" HB_INTERNAL 257 hb_unicode_funcs_t * 258 hb_ucdn_get_unicode_funcs (void) 259 { 260 retry: 261 hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs); 262 263 if (unlikely (!funcs)) 264 { 265 funcs = hb_unicode_funcs_create (nullptr); 266 267 #define HB_UNICODE_FUNC_IMPLEMENT(name) \ 268 hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr); 269 HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS 270 #undef HB_UNICODE_FUNC_IMPLEMENT 271 272 hb_unicode_funcs_make_immutable (funcs); 273 274 if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) { 275 hb_unicode_funcs_destroy (funcs); 276 goto retry; 277 } 278 279 #ifdef HB_USE_ATEXIT 280 atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */ 281 #endif 282 }; 283 284 return hb_unicode_funcs_reference (funcs); 285 }