15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2009 Red Hat, Inc. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2009 Keith Stribley 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2011 Google, Inc. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This is part of HarfBuzz, a text shaping library. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Red Hat Author(s): Behdad Esfahbod 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-private.hh" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-icu.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-unicode-private.hh" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unicode/uchar.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unicode/unorm.h> 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unicode/ustring.h> 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unicode/uversion.h> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_script_t 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_script_to_script (UScriptCode script) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (script == USCRIPT_INVALID_CODE)) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HB_SCRIPT_INVALID; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_script_from_string (uscript_getShortName (script), -1); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UScriptCode 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_script_from_script (hb_script_t script) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (script == HB_SCRIPT_INVALID)) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USCRIPT_INVALID_CODE; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned int i = 0; i < USCRIPT_CODE_LIMIT; i++) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (hb_icu_script_to_script ((UScriptCode) i) == script)) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (UScriptCode) i; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USCRIPT_UNKNOWN; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static hb_unicode_combining_class_t 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_unicode_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t unicode, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data HB_UNUSED) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (hb_unicode_combining_class_t) u_getCombiningClass (unicode); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned int 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs HB_UNUSED, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t unicode, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data HB_UNUSED) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (u_getIntPropertyValue(unicode, UCHAR_EAST_ASIAN_WIDTH)) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_EA_WIDE: 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_EA_FULLWIDTH: 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 2; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_EA_NEUTRAL: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_EA_AMBIGUOUS: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_EA_HALFWIDTH: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_EA_NARROW: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static hb_unicode_general_category_t 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_unicode_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t unicode, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data HB_UNUSED) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (u_getIntPropertyValue(unicode, UCHAR_GENERAL_CATEGORY)) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_UNASSIGNED: return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_UPPERCASE_LETTER: return HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_LOWERCASE_LETTER: return HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_TITLECASE_LETTER: return HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_MODIFIER_LETTER: return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_OTHER_LETTER: return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_NON_SPACING_MARK: return HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_ENCLOSING_MARK: return HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_COMBINING_SPACING_MARK: return HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_DECIMAL_DIGIT_NUMBER: return HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_LETTER_NUMBER: return HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_OTHER_NUMBER: return HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_SPACE_SEPARATOR: return HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_LINE_SEPARATOR: return HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_PARAGRAPH_SEPARATOR: return HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_CONTROL_CHAR: return HB_UNICODE_GENERAL_CATEGORY_CONTROL; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_FORMAT_CHAR: return HB_UNICODE_GENERAL_CATEGORY_FORMAT; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_PRIVATE_USE_CHAR: return HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_SURROGATE: return HB_UNICODE_GENERAL_CATEGORY_SURROGATE; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_DASH_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_START_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_END_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_CONNECTOR_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_OTHER_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_MATH_SYMBOL: return HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_CURRENCY_SYMBOL: return HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_MODIFIER_SYMBOL: return HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_OTHER_SYMBOL: return HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_INITIAL_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case U_FINAL_PUNCTUATION: return HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static hb_codepoint_t 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_unicode_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t unicode, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data HB_UNUSED) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return u_charMirror(unicode); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static hb_script_t 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_unicode_script (hb_unicode_funcs_t *ufuncs HB_UNUSED, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t unicode, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data HB_UNUSED) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UScriptCode scriptCode = uscript_getScript(unicode, &status); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (U_FAILURE (status))) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HB_SCRIPT_UNKNOWN; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_icu_script_to_script (scriptCode); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if U_ICU_VERSION_MAJOR_NUM >= 49 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const UNormalizer2 *normalizer; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static hb_bool_t 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t a, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t b, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t *ab, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data HB_UNUSED) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if U_ICU_VERSION_MAJOR_NUM >= 49 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UChar32 ret = unorm2_composePair (normalizer, a, b); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) return false; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ab = ret; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We don't ifdef-out the fallback code such that compiler always 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sees it and makes sure it's compilable. */ 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UChar utf16[4], normalized[5]; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int len; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_bool_t ret, err; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UErrorCode icu_err; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = 0; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = false; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err) return false; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err) return false; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu_err = U_ZERO_ERROR; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = unorm_normalize (utf16, len, UNORM_NFC, 0, normalized, ARRAY_LENGTH (normalized), &icu_err); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (U_FAILURE (icu_err)) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u_countChar32 (normalized, len) == 1) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_GET_UNSAFE (normalized, 0, *ab); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = true; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = false; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static hb_bool_t 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t ab, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t *a, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t *b, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data HB_UNUSED) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if U_ICU_VERSION_MAJOR_NUM >= 49 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UChar decomposed[4]; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UErrorCode icu_err = U_ZERO_ERROR; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = unorm2_getRawDecomposition (normalizer, ab, decomposed, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ARRAY_LENGTH (decomposed), &icu_err); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (U_FAILURE (icu_err) || len < 0) return false; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = u_countChar32 (decomposed, len); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len == 1) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_GET_UNSAFE (decomposed, 0, *a); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *b = 0; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *a != ab; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (len == 2) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len =0; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_NEXT_UNSAFE (decomposed, len, *a); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_NEXT_UNSAFE (decomposed, len, *b); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We don't ifdef-out the fallback code such that compiler always 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sees it and makes sure it's compilable. */ 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1]; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int len; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_bool_t ret, err; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UErrorCode icu_err; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This function is a monster! Maybe it wasn't a good idea adding a 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * pairwise decompose API... */ 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Watchout for the dragons. Err, watchout for macros changing len. */ 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = 0; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = false; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err) return false; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu_err = U_ZERO_ERROR; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = unorm_normalize (utf16, len, UNORM_NFD, 0, normalized, ARRAY_LENGTH (normalized), &icu_err); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (U_FAILURE (icu_err)) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = u_countChar32 (normalized, len); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len == 1) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_GET_UNSAFE (normalized, 0, *a); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *b = 0; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = *a != ab; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (len == 2) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len =0; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_NEXT_UNSAFE (normalized, len, *a); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_NEXT_UNSAFE (normalized, len, *b); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Here's the ugly part: if ab decomposes to a single character and 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that character decomposes again, we have to detect that and undo 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the second part :-(. */ 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UChar recomposed[20]; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu_err = U_ZERO_ERROR; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unorm_normalize (normalized, len, UNORM_NFC, 0, recomposed, ARRAY_LENGTH (recomposed), &icu_err); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (U_FAILURE (icu_err)) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t c; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_GET_UNSAFE (recomposed, 0, c); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (c != *a && c != ab) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *a = c; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *b = 0; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = true; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If decomposed to more than two characters, take the last one, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and recompose the rest to get the first component. */ 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_PREV_UNSAFE (normalized, len, *b); /* Changes len in-place. */ 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UChar recomposed[18 * 2]; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu_err = U_ZERO_ERROR; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = unorm_normalize (normalized, len, UNORM_NFC, 0, recomposed, ARRAY_LENGTH (recomposed), &icu_err); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (U_FAILURE (icu_err)) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We expect that recomposed has exactly one character now. */ 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (u_countChar32 (recomposed, len) != 1)) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_GET_UNSAFE (recomposed, 0, *a); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = true; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned int 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t u, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_codepoint_t *decomposed, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data HB_UNUSED) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1]; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int len; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32_t utf32_len; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_bool_t err; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UErrorCode icu_err; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Copy @u into a UTF-16 array to be passed to ICU. */ 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = 0; 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) err = false; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), u, err); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Normalise the codepoint using NFKD mode. */ 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu_err = U_ZERO_ERROR; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = unorm_normalize (utf16, len, UNORM_NFKD, 0, normalized, ARRAY_LENGTH (normalized), &icu_err); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icu_err) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Convert the decomposed form from UTF-16 to UTF-32. */ 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icu_err = U_ZERO_ERROR; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_strToUTF32 ((UChar32*) decomposed, HB_UNICODE_MAX_DECOMPOSITION_LEN, &utf32_len, normalized, len, &icu_err); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icu_err) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return utf32_len; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_unicode_funcs_t * 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_icu_get_unicode_funcs (void) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const hb_unicode_funcs_t _hb_icu_unicode_funcs = { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HB_OBJECT_HEADER_STATIC, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, /* parent */ 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, /* immutable */ 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_icu_unicode_##name, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef HB_UNICODE_FUNC_IMPLEMENT 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if U_ICU_VERSION_MAJOR_NUM >= 49 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!hb_atomic_ptr_get (&normalizer)) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UErrorCode icu_err = U_ZERO_ERROR; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We ignore failure in getNFCInstace(). */ 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err)); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 373