| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright © 2009 Red Hat, Inc. | 2 * Copyright © 2009 Red Hat, Inc. |
| 3 * Copyright © 2011 Google, Inc. | 3 * Copyright © 2011 Google, Inc. |
| 4 * | 4 * |
| 5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
| 6 * | 6 * |
| 7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
| 8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
| 9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
| 10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 case HB_SCRIPT_YI: return HB_TAG('y','i',' ',' '); | 50 case HB_SCRIPT_YI: return HB_TAG('y','i',' ',' '); |
| 51 /* Unicode-5.0 additions */ | 51 /* Unicode-5.0 additions */ |
| 52 case HB_SCRIPT_NKO: return HB_TAG('n','k','o',' '); | 52 case HB_SCRIPT_NKO: return HB_TAG('n','k','o',' '); |
| 53 /* Unicode-5.1 additions */ | 53 /* Unicode-5.1 additions */ |
| 54 case HB_SCRIPT_VAI: return HB_TAG('v','a','i',' '); | 54 case HB_SCRIPT_VAI: return HB_TAG('v','a','i',' '); |
| 55 /* Unicode-5.2 additions */ | 55 /* Unicode-5.2 additions */ |
| 56 /* Unicode-6.0 additions */ | 56 /* Unicode-6.0 additions */ |
| 57 } | 57 } |
| 58 | 58 |
| 59 /* Else, just change first char to lowercase and return */ | 59 /* Else, just change first char to lowercase and return */ |
| 60 return ((hb_tag_t) script) | 0x20000000; | 60 return ((hb_tag_t) script) | 0x20000000u; |
| 61 } | 61 } |
| 62 | 62 |
| 63 static hb_script_t | 63 static hb_script_t |
| 64 hb_ot_old_tag_to_script (hb_tag_t tag) | 64 hb_ot_old_tag_to_script (hb_tag_t tag) |
| 65 { | 65 { |
| 66 if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT)) | 66 if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT)) |
| 67 return HB_SCRIPT_INVALID; | 67 return HB_SCRIPT_INVALID; |
| 68 | 68 |
| 69 /* This side of the conversion is fully algorithmic. */ | 69 /* This side of the conversion is fully algorithmic. */ |
| 70 | 70 |
| 71 /* Any spaces at the end of the tag are replaced by repeating the last | 71 /* Any spaces at the end of the tag are replaced by repeating the last |
| 72 * letter. Eg 'nko ' -> 'Nkoo' */ | 72 * letter. Eg 'nko ' -> 'Nkoo' */ |
| 73 if (unlikely ((tag & 0x0000FF00) == 0x00002000)) | 73 if (unlikely ((tag & 0x0000FF00u) == 0x00002000u)) |
| 74 tag |= (tag >> 8) & 0x0000FF00; /* Copy second letter to third */ | 74 tag |= (tag >> 8) & 0x0000FF00u; /* Copy second letter to third */ |
| 75 if (unlikely ((tag & 0x000000FF) == 0x00000020)) | 75 if (unlikely ((tag & 0x000000FFu) == 0x00000020u)) |
| 76 tag |= (tag >> 8) & 0x000000FF; /* Copy third letter to fourth */ | 76 tag |= (tag >> 8) & 0x000000FFu; /* Copy third letter to fourth */ |
| 77 | 77 |
| 78 /* Change first char to uppercase and return */ | 78 /* Change first char to uppercase and return */ |
| 79 return (hb_script_t) (tag & ~0x20000000); | 79 return (hb_script_t) (tag & ~0x20000000u); |
| 80 } | 80 } |
| 81 | 81 |
| 82 static hb_tag_t | 82 static hb_tag_t |
| 83 hb_ot_new_tag_from_script (hb_script_t script) | 83 hb_ot_new_tag_from_script (hb_script_t script) |
| 84 { | 84 { |
| 85 switch ((hb_tag_t) script) { | 85 switch ((hb_tag_t) script) { |
| 86 case HB_SCRIPT_BENGALI: return HB_TAG('b','n','g','2'); | 86 case HB_SCRIPT_BENGALI: return HB_TAG('b','n','g','2'); |
| 87 case HB_SCRIPT_DEVANAGARI: return HB_TAG('d','e','v','2'); | 87 case HB_SCRIPT_DEVANAGARI: return HB_TAG('d','e','v','2'); |
| 88 case HB_SCRIPT_GUJARATI: return HB_TAG('g','j','r','2'); | 88 case HB_SCRIPT_GUJARATI: return HB_TAG('g','j','r','2'); |
| 89 case HB_SCRIPT_GURMUKHI: return HB_TAG('g','u','r','2'); | 89 case HB_SCRIPT_GURMUKHI: return HB_TAG('g','u','r','2'); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 new_tag = hb_ot_new_tag_from_script (script); | 139 new_tag = hb_ot_new_tag_from_script (script); |
| 140 if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) { | 140 if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) { |
| 141 *script_tag_2 = *script_tag_1; | 141 *script_tag_2 = *script_tag_1; |
| 142 *script_tag_1 = new_tag; | 142 *script_tag_1 = new_tag; |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 | 145 |
| 146 hb_script_t | 146 hb_script_t |
| 147 hb_ot_tag_to_script (hb_tag_t tag) | 147 hb_ot_tag_to_script (hb_tag_t tag) |
| 148 { | 148 { |
| 149 if (unlikely ((tag & 0x000000FF) == '2')) | 149 if (unlikely ((tag & 0x000000FFu) == '2')) |
| 150 return hb_ot_new_tag_to_script (tag); | 150 return hb_ot_new_tag_to_script (tag); |
| 151 | 151 |
| 152 return hb_ot_old_tag_to_script (tag); | 152 return hb_ot_old_tag_to_script (tag); |
| 153 } | 153 } |
| 154 | 154 |
| 155 | 155 |
| 156 /* hb_language_t */ | 156 /* hb_language_t */ |
| 157 | 157 |
| 158 typedef struct { | 158 typedef struct { |
| 159 char language[6]; | 159 char language[4]; |
| 160 hb_tag_t tag; | 160 hb_tag_t tag; |
| 161 } LangTag; | 161 } LangTag; |
| 162 | 162 |
| 163 /* | 163 /* |
| 164 * Complete list at: | 164 * Complete list at: |
| 165 * http://www.microsoft.com/typography/otspec/languagetags.htm | 165 * http://www.microsoft.com/typography/otspec/languagetags.htm |
| 166 * | 166 * |
| 167 * Generated by intersecting the OpenType language tag list from | 167 * Generated by intersecting the OpenType language tag list from |
| 168 * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from | 168 * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from |
| 169 * 2008-08-04, matching on name, and finally adjusted manually. | 169 * 2008-08-04, matching on name, and finally adjusted manually. |
| (...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 756 /*{"??", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */ | 756 /*{"??", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */ |
| 757 /*{"tnz?/tog?/toi?", HB_TAG('T','N','G',' ')},*/ /* Tonga */ | 757 /*{"tnz?/tog?/toi?", HB_TAG('T','N','G',' ')},*/ /* Tonga */ |
| 758 /*{"enh?/yrk?", HB_TAG('T','N','E',' ')},*/ /* Tundra Nenets */ | 758 /*{"enh?/yrk?", HB_TAG('T','N','E',' ')},*/ /* Tundra Nenets */ |
| 759 /*{"??", HB_TAG('W','C','R',' ')},*/ /* West-Cree */ | 759 /*{"??", HB_TAG('W','C','R',' ')},*/ /* West-Cree */ |
| 760 /*{"cre?", HB_TAG('Y','C','R',' ')},*/ /* Y-Cree */ | 760 /*{"cre?", HB_TAG('Y','C','R',' ')},*/ /* Y-Cree */ |
| 761 /*{"??", HB_TAG('Y','I','C',' ')},*/ /* Yi Classic */ | 761 /*{"??", HB_TAG('Y','I','C',' ')},*/ /* Yi Classic */ |
| 762 /*{"ii?/Yiii?", HB_TAG('Y','I','M',' ')},*/ /* Yi Modern */ | 762 /*{"ii?/Yiii?", HB_TAG('Y','I','M',' ')},*/ /* Yi Modern */ |
| 763 /*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */ | 763 /*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */ |
| 764 }; | 764 }; |
| 765 | 765 |
| 766 static const LangTag ot_languages_zh[] = { | 766 typedef struct { |
| 767 char language[8]; |
| 768 hb_tag_t tag; |
| 769 } LangTagLong; |
| 770 static const LangTagLong ot_languages_zh[] = { |
| 767 {"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */ | 771 {"zh-cn", HB_TAG('Z','H','S',' ')}, /* Chinese (China) */ |
| 768 {"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ | 772 {"zh-hk", HB_TAG('Z','H','H',' ')}, /* Chinese (Hong Kong) */ |
| 769 {"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */ | 773 {"zh-mo", HB_TAG('Z','H','T',' ')}, /* Chinese (Macao) */ |
| 770 {"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */ | 774 {"zh-sg", HB_TAG('Z','H','S',' ')}, /* Chinese (Singapore) */ |
| 771 {"zh-tw",» HB_TAG('Z','H','T',' ')} » /* Chinese (Taiwan) */ | 775 {"zh-tw",» HB_TAG('Z','H','T',' ')},» /* Chinese (Taiwan) */ |
| 776 {"zh-hans",» HB_TAG('Z','H','S',' ')},» /* Chinese (Simplified) */ |
| 777 {"zh-hant",» HB_TAG('Z','H','T',' ')},» /* Chinese (Traditional) */ |
| 772 }; | 778 }; |
| 773 | 779 |
| 774 static int | 780 static int |
| 775 lang_compare_first_component (const char *a, | 781 lang_compare_first_component (const char *a, |
| 776 const char *b) | 782 const char *b) |
| 777 { | 783 { |
| 778 unsigned int da, db; | 784 unsigned int da, db; |
| 779 const char *p; | 785 const char *p; |
| 780 | 786 |
| 781 p = strchr (a, '-'); | 787 p = strchr (a, '-'); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 793 unsigned int len = strlen (spec); | 799 unsigned int len = strlen (spec); |
| 794 | 800 |
| 795 return strncmp (lang_str, spec, len) == 0 && | 801 return strncmp (lang_str, spec, len) == 0 && |
| 796 (lang_str[len] == '\0' || lang_str[len] == '-'); | 802 (lang_str[len] == '\0' || lang_str[len] == '-'); |
| 797 } | 803 } |
| 798 | 804 |
| 799 hb_tag_t | 805 hb_tag_t |
| 800 hb_ot_tag_from_language (hb_language_t language) | 806 hb_ot_tag_from_language (hb_language_t language) |
| 801 { | 807 { |
| 802 const char *lang_str, *s; | 808 const char *lang_str, *s; |
| 803 const LangTag *lang_tag; | |
| 804 | 809 |
| 805 if (language == HB_LANGUAGE_INVALID) | 810 if (language == HB_LANGUAGE_INVALID) |
| 806 return HB_OT_TAG_DEFAULT_LANGUAGE; | 811 return HB_OT_TAG_DEFAULT_LANGUAGE; |
| 807 | 812 |
| 808 lang_str = hb_language_to_string (language); | 813 lang_str = hb_language_to_string (language); |
| 809 | 814 |
| 810 s = strstr (lang_str, "x-hbot"); | 815 s = strstr (lang_str, "x-hbot"); |
| 811 if (s) { | 816 if (s) { |
| 812 char tag[4]; | 817 char tag[4]; |
| 813 int i; | 818 int i; |
| 814 s += 6; | 819 s += 6; |
| 815 for (i = 0; i < 4 && ISALPHA (s[i]); i++) | 820 for (i = 0; i < 4 && ISALPHA (s[i]); i++) |
| 816 tag[i] = TOUPPER (s[i]); | 821 tag[i] = TOUPPER (s[i]); |
| 817 if (i) { | 822 if (i) { |
| 818 for (; i < 4; i++) | 823 for (; i < 4; i++) |
| 819 tag[i] = ' '; | 824 tag[i] = ' '; |
| 820 return HB_TAG_CHAR4 (tag); | 825 return HB_TAG_CHAR4 (tag); |
| 821 } | 826 } |
| 822 } | 827 } |
| 823 | 828 |
| 824 /* Find a language matching in the first component */ | 829 /* Find a language matching in the first component */ |
| 825 lang_tag = (LangTag *) bsearch (lang_str, ot_languages, | 830 { |
| 826 » » » » ARRAY_LENGTH (ot_languages), sizeof (LangTag), | 831 const LangTag *lang_tag; |
| 827 » » » » (hb_compare_func_t) lang_compare_first_compone
nt); | 832 lang_tag = (LangTag *) bsearch (lang_str, ot_languages, |
| 828 if (lang_tag) | 833 » » » » ARRAY_LENGTH (ot_languages), sizeof (LangTag
), |
| 829 return lang_tag->tag; | 834 » » » » (hb_compare_func_t) lang_compare_first_compo
nent); |
| 835 if (lang_tag) |
| 836 return lang_tag->tag; |
| 837 } |
| 830 | 838 |
| 831 /* Otherwise, check the Chinese ones */ | 839 /* Otherwise, check the Chinese ones */ |
| 832 if (0 == lang_compare_first_component (lang_str, "zh")) | 840 if (0 == lang_compare_first_component (lang_str, "zh")) |
| 833 { | 841 { |
| 834 unsigned int i; | 842 unsigned int i; |
| 835 | 843 |
| 836 for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++) | 844 for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++) |
| 837 { | 845 { |
| 846 const LangTagLong *lang_tag; |
| 838 lang_tag = &ot_languages_zh[i]; | 847 lang_tag = &ot_languages_zh[i]; |
| 839 if (lang_matches (lang_tag->language, lang_str)) | 848 if (lang_matches (lang_str, lang_tag->language)) |
| 840 return lang_tag->tag; | 849 return lang_tag->tag; |
| 841 } | 850 } |
| 842 | 851 |
| 843 /* Otherwise just return 'ZHS ' */ | 852 /* Otherwise just return 'ZHS ' */ |
| 844 return HB_TAG('Z','H','S',' '); | 853 return HB_TAG('Z','H','S',' '); |
| 845 } | 854 } |
| 846 | 855 |
| 847 s = strchr (lang_str, '-'); | 856 s = strchr (lang_str, '-'); |
| 848 if (!s) | 857 if (!s) |
| 849 s = lang_str + strlen (lang_str); | 858 s = lang_str + strlen (lang_str); |
| 850 if (s - lang_str == 3) { | 859 if (s - lang_str == 3) { |
| 851 /* Assume it's ISO-639-3 and upper-case and use it. */ | 860 /* Assume it's ISO-639-3 and upper-case and use it. */ |
| 852 return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000; | 861 return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u; |
| 853 } | 862 } |
| 854 | 863 |
| 855 return HB_OT_TAG_DEFAULT_LANGUAGE; | 864 return HB_OT_TAG_DEFAULT_LANGUAGE; |
| 856 } | 865 } |
| 857 | 866 |
| 858 hb_language_t | 867 hb_language_t |
| 859 hb_ot_tag_to_language (hb_tag_t tag) | 868 hb_ot_tag_to_language (hb_tag_t tag) |
| 860 { | 869 { |
| 861 unsigned int i; | 870 unsigned int i; |
| 862 | 871 |
| 863 if (tag == HB_OT_TAG_DEFAULT_LANGUAGE) | 872 if (tag == HB_OT_TAG_DEFAULT_LANGUAGE) |
| 864 return NULL; | 873 return NULL; |
| 865 | 874 |
| 866 for (i = 0; i < ARRAY_LENGTH (ot_languages); i++) | 875 for (i = 0; i < ARRAY_LENGTH (ot_languages); i++) |
| 867 if (ot_languages[i].tag == tag) | 876 if (ot_languages[i].tag == tag) |
| 868 return hb_language_from_string (ot_languages[i].language, -1); | 877 return hb_language_from_string (ot_languages[i].language, -1); |
| 869 | 878 |
| 870 /* If tag starts with ZH, it's Chinese */ | 879 /* If tag starts with ZH, it's Chinese */ |
| 871 if ((tag & 0xFFFF0000) == 0x5A480000) { | 880 if ((tag & 0xFFFF0000u) == 0x5A480000u) { |
| 872 switch (tag) { | 881 switch (tag) { |
| 873 case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1)
; /* Hong Kong */ | 882 case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1)
; /* Hong Kong */ |
| 874 default: { | 883 case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -
1); /* Simplified */ |
| 875 /* Encode the tag... */ | 884 case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -
1); /* Traditional */ |
| 876 » unsigned char buf[14] = "zh-x-hbot"; | 885 default: break; /* Fall through */ |
| 877 » buf[9] = tag >> 24; | |
| 878 » buf[10] = (tag >> 16) & 0xFF; | |
| 879 » buf[11] = (tag >> 8) & 0xFF; | |
| 880 » buf[12] = tag & 0xFF; | |
| 881 » if (buf[12] == 0x20) | |
| 882 » buf[12] = '\0'; | |
| 883 » buf[13] = '\0'; | |
| 884 » return hb_language_from_string ((char *) buf, -1); | |
| 885 } | |
| 886 } | 886 } |
| 887 } | 887 } |
| 888 | 888 |
| 889 /* Else return a custom language in the form of "x-hbotABCD" */ | 889 /* Else return a custom language in the form of "x-hbotABCD" */ |
| 890 { | 890 { |
| 891 unsigned char buf[11] = "x-hbot"; | 891 unsigned char buf[11] = "x-hbot"; |
| 892 buf[6] = tag >> 24; | 892 buf[6] = tag >> 24; |
| 893 buf[7] = (tag >> 16) & 0xFF; | 893 buf[7] = (tag >> 16) & 0xFF; |
| 894 buf[8] = (tag >> 8) & 0xFF; | 894 buf[8] = (tag >> 8) & 0xFF; |
| 895 buf[9] = tag & 0xFF; | 895 buf[9] = tag & 0xFF; |
| 896 if (buf[9] == 0x20) | 896 if (buf[9] == 0x20) |
| 897 buf[9] = '\0'; | 897 buf[9] = '\0'; |
| 898 buf[10] = '\0'; | 898 buf[10] = '\0'; |
| 899 return hb_language_from_string ((char *) buf, -1); | 899 return hb_language_from_string ((char *) buf, -1); |
| 900 } | 900 } |
| 901 } | 901 } |
| 902 | 902 |
| 903 | 903 |
| OLD | NEW |