OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2012 Google, Inc. | 2 * Copyright © 2012 Google, Inc. |
3 * | 3 * |
4 * This is part of HarfBuzz, a text shaping library. | 4 * This is part of HarfBuzz, a text shaping library. |
5 * | 5 * |
6 * Permission is hereby granted, without written agreement and without | 6 * Permission is hereby granted, without written agreement and without |
7 * license or royalty fees, to use, copy, modify, and distribute this | 7 * license or royalty fees, to use, copy, modify, and distribute this |
8 * software and its documentation for any purpose, provided that the | 8 * software and its documentation for any purpose, provided that the |
9 * above copyright notice and the following two paragraphs appear in | 9 * above copyright notice and the following two paragraphs appear in |
10 * all copies of this software. | 10 * all copies of this software. |
(...skipping 13 matching lines...) Expand all Loading... |
24 * Google Author(s): Behdad Esfahbod | 24 * Google Author(s): Behdad Esfahbod |
25 */ | 25 */ |
26 | 26 |
27 #ifndef HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH | 27 #ifndef HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH |
28 #define HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH | 28 #define HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH |
29 | 29 |
30 #include "hb-private.hh" | 30 #include "hb-private.hh" |
31 | 31 |
32 | 32 |
33 #include "hb-ot-shape-complex-private.hh" | 33 #include "hb-ot-shape-complex-private.hh" |
| 34 #include "hb-ot-shape-private.hh" /* XXX Remove */ |
34 | 35 |
35 | 36 |
36 /* buffer var allocations */ | 37 /* buffer var allocations */ |
37 #define indic_category() complex_var_persistent_u8_0() /* indic_category_t */ | 38 #define indic_category() complex_var_u8_0() /* indic_category_t */ |
38 #define indic_position() complex_var_persistent_u8_1() /* indic_matra_category_t
*/ | 39 #define indic_position() complex_var_u8_1() /* indic_matra_category_t */ |
| 40 |
39 | 41 |
40 #define INDIC_TABLE_ELEMENT_TYPE uint8_t | 42 #define INDIC_TABLE_ELEMENT_TYPE uint8_t |
41 | 43 |
42 /* Cateories used in the OpenType spec: | 44 /* Cateories used in the OpenType spec: |
43 * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx | 45 * https://www.microsoft.com/typography/otfntdev/devanot/shaping.aspx |
44 */ | 46 */ |
45 /* Note: This enum is duplicated in the -machine.rl source file. | 47 /* Note: This enum is duplicated in the -machine.rl source file. |
46 * Not sure how to avoid duplication. */ | 48 * Not sure how to avoid duplication. */ |
47 enum indic_category_t { | 49 enum indic_category_t { |
48 OT_X = 0, | 50 OT_X = 0, |
49 OT_C, | 51 OT_C, |
50 OT_Ra, /* Not explicitly listed in the OT spec, but used in the grammar. */ | |
51 OT_V, | 52 OT_V, |
52 OT_N, | 53 OT_N, |
53 OT_H, | 54 OT_H, |
54 OT_ZWNJ, | 55 OT_ZWNJ, |
55 OT_ZWJ, | 56 OT_ZWJ, |
56 OT_M, | 57 OT_M, |
57 OT_SM, | 58 OT_SM, |
58 OT_VD, | 59 OT_VD, |
59 OT_A, | 60 OT_A, |
60 OT_NBSP, | 61 OT_NBSP, |
61 OT_DOTTEDCIRCLE /* Not in the spec, but special in Uniscribe. /Very very/ spec
ial! */ | 62 OT_DOTTEDCIRCLE, /* Not in the spec, but special in Uniscribe. /Very very/ spe
cial! */ |
| 63 OT_RS, /* Register Shifter, used in Khmer OT spec */ |
| 64 OT_Coeng, |
| 65 OT_Repha, |
| 66 OT_Ra /* Not explicitly listed in the OT spec, but used in the grammar. */ |
62 }; | 67 }; |
63 | 68 |
64 /* Visual positions in a syllable from left to right. */ | 69 /* Visual positions in a syllable from left to right. */ |
65 enum indic_position_t { | 70 enum indic_position_t { |
| 71 POS_START, |
| 72 |
66 POS_RA_TO_BECOME_REPH, | 73 POS_RA_TO_BECOME_REPH, |
67 POS_PRE_M, | 74 POS_PRE_M, |
68 POS_PRE_C, | 75 POS_PRE_C, |
| 76 |
69 POS_BASE_C, | 77 POS_BASE_C, |
| 78 POS_AFTER_MAIN, |
| 79 |
70 POS_ABOVE_C, | 80 POS_ABOVE_C, |
| 81 |
| 82 POS_BEFORE_SUB, |
71 POS_BELOW_C, | 83 POS_BELOW_C, |
72 POS_ABOVE_M, | 84 POS_AFTER_SUB, |
73 POS_BELOW_M, | 85 |
| 86 POS_BEFORE_POST, |
74 POS_POST_C, | 87 POS_POST_C, |
75 POS_POST_M, | 88 POS_AFTER_POST, |
76 POS_SMVD | 89 |
| 90 POS_FINAL_C, |
| 91 POS_SMVD, |
| 92 |
| 93 POS_END |
77 }; | 94 }; |
78 | 95 |
79 /* Categories used in IndicSyllabicCategory.txt from UCD. */ | 96 /* Categories used in IndicSyllabicCategory.txt from UCD. */ |
80 enum indic_syllabic_category_t { | 97 enum indic_syllabic_category_t { |
81 INDIC_SYLLABIC_CATEGORY_OTHER = OT_X, | 98 INDIC_SYLLABIC_CATEGORY_OTHER = OT_X, |
82 | 99 |
83 INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_X, | 100 INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_X, |
84 INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM, | 101 INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM, |
85 INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C, | 102 INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C, |
86 INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C, | 103 INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C, |
87 INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_C, | 104 INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_C, |
88 INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C, | 105 INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C, |
89 INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_C, | 106 INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_C, |
90 INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP, | 107 INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP, |
91 INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_C, | 108 INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_C, |
92 INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA» = OT_C, | 109 INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA» = OT_Repha, |
93 INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X, | 110 INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X, |
94 INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N, | 111 INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N, |
95 INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER» = OT_X, | 112 INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER» = OT_RS, |
96 INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X, | 113 INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X, |
97 INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_X, | 114 INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_X, |
98 INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H, | 115 INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H, |
99 INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM, | 116 INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM, |
100 INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V, | 117 INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V, |
101 INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M, | 118 INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M, |
102 INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V | 119 INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V |
103 }; | 120 }; |
104 | 121 |
105 /* Categories used in IndicSMatraCategory.txt from UCD */ | 122 /* Categories used in IndicSMatraCategory.txt from UCD */ |
106 enum indic_matra_category_t { | 123 enum indic_matra_category_t { |
107 INDIC_MATRA_CATEGORY_NOT_APPLICABLE» » = POS_BASE_C, | 124 INDIC_MATRA_CATEGORY_NOT_APPLICABLE» » = POS_END, |
108 | 125 |
109 INDIC_MATRA_CATEGORY_LEFT» » » = POS_PRE_M, | 126 INDIC_MATRA_CATEGORY_LEFT» » » = POS_PRE_C, |
110 INDIC_MATRA_CATEGORY_TOP» » » = POS_ABOVE_M, | 127 INDIC_MATRA_CATEGORY_TOP» » » = POS_ABOVE_C, |
111 INDIC_MATRA_CATEGORY_BOTTOM» » » = POS_BELOW_M, | 128 INDIC_MATRA_CATEGORY_BOTTOM» » » = POS_BELOW_C, |
112 INDIC_MATRA_CATEGORY_RIGHT» » » = POS_POST_M, | 129 INDIC_MATRA_CATEGORY_RIGHT» » » = POS_POST_C, |
113 | 130 |
114 /* We don't really care much about these since we decompose them | 131 /* These should resolve to the position of the last part of the split sequence
. */ |
115 * in the generic pre-shaping layer. They will only be used if | 132 INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT»» = INDIC_MATRA_CATEGORY_RIGHT, |
116 * the font does not cover the decomposition. In which case, we | 133 INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT» » = INDIC_MATRA_CATEGORY_RIGHT, |
117 * define these as aliases to the place we want the split-matra | 134 INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM» » = INDIC_MATRA_CATEGORY_BOTTOM, |
118 * glyph to show up. Quite arbitrary. | 135 INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT»= INDIC_MATRA_CATEGORY_RIGHT, |
119 * | 136 INDIC_MATRA_CATEGORY_TOP_AND_LEFT» » = INDIC_MATRA_CATEGORY_TOP, |
120 * TODO: There are some split matras without Unicode decompositions. | 137 INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT» = INDIC_MATRA_CATEGORY_RIGHT, |
121 * We have to figure out what to do with them. | 138 INDIC_MATRA_CATEGORY_TOP_AND_RIGHT» » = INDIC_MATRA_CATEGORY_RIGHT, |
122 */ | |
123 INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT»» = POS_POST_M, | |
124 INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT» » = POS_PRE_M, | |
125 INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM» » = POS_BELOW_M, | |
126 INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT»= POS_POST_M, | |
127 INDIC_MATRA_CATEGORY_TOP_AND_LEFT» » = POS_PRE_M, | |
128 INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT» = POS_PRE_M, | |
129 INDIC_MATRA_CATEGORY_TOP_AND_RIGHT» » = POS_POST_M, | |
130 | 139 |
131 INDIC_MATRA_CATEGORY_INVISIBLE = INDIC_MATRA_CATEGORY_NOT_APPLI
CABLE, | 140 INDIC_MATRA_CATEGORY_INVISIBLE = INDIC_MATRA_CATEGORY_NOT_APPLI
CABLE, |
132 INDIC_MATRA_CATEGORY_OVERSTRUCK = INDIC_MATRA_CATEGORY_NOT_APPLI
CABLE, | 141 INDIC_MATRA_CATEGORY_OVERSTRUCK = INDIC_MATRA_CATEGORY_NOT_APPLI
CABLE, |
133 INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = INDIC_MATRA_CATEGORY_NOT_APPLI
CABLE | 142 INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = INDIC_MATRA_CATEGORY_NOT_APPLI
CABLE |
134 }; | 143 }; |
135 | 144 |
136 /* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and th
e comma operation | 145 /* Note: We use ASSERT_STATIC_EXPR_ZERO() instead of ASSERT_STATIC_EXPR() and th
e comma operation |
137 * because gcc fails to optimize the latter and fills the table in at runtime. *
/ | 146 * because gcc fails to optimize the latter and fills the table in at runtime. *
/ |
138 #define INDIC_COMBINE_CATEGORIES(S,M) \ | 147 #define INDIC_COMBINE_CATEGORIES(S,M) \ |
139 (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || (S == IN
DIC_SYLLABIC_CATEGORY_VIRAMA || S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT)) +
\ | 148 (ASSERT_STATIC_EXPR_ZERO (M == INDIC_MATRA_CATEGORY_NOT_APPLICABLE || (S == IN
DIC_SYLLABIC_CATEGORY_VIRAMA || S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT)) +
\ |
140 ASSERT_STATIC_EXPR_ZERO (S < 16 && M < 16) + \ | 149 ASSERT_STATIC_EXPR_ZERO (S < 16 && M < 16) + \ |
141 ((M << 4) | S)) | 150 ((M << 4) | S)) |
142 | 151 |
143 | 152 |
144 #include "hb-ot-shape-complex-indic-table.hh" | 153 #include "hb-ot-shape-complex-indic-table.hh" |
145 | 154 |
146 /* XXX | 155 |
147 * This is a hack for now. We should: | 156 #define IN_HALF_BLOCK(u, Base) (((u) & ~0x7F) == (Base)) |
148 * 1. Move this data into the main Indic table, | 157 |
149 * and/or | 158 #define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900)) |
150 * 2. Probe font lookups to determine consonant positions. | 159 #define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980)) |
151 */ | 160 #define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00)) |
152 static const struct consonant_position_t { | 161 #define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80)) |
153 hb_codepoint_t u; | 162 #define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00)) |
154 indic_position_t position; | 163 #define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80)) |
155 } consonant_positions[] = { | 164 #define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00)) |
156 {0x0930, POS_BELOW_C}, | 165 #define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80)) |
157 {0x09AC, POS_BELOW_C}, | 166 #define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00)) |
158 {0x09AF, POS_POST_C}, | 167 #define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80)) |
159 {0x09B0, POS_BELOW_C}, | 168 #define IS_KHMR(u) (IN_HALF_BLOCK (u, 0x1780)) |
160 {0x09F0, POS_BELOW_C}, | 169 |
161 {0x0A2F, POS_POST_C}, | 170 |
162 {0x0A30, POS_BELOW_C}, | 171 #define MATRA_POS_LEFT(u)» POS_PRE_M |
163 {0x0A35, POS_BELOW_C}, | 172 #define MATRA_POS_RIGHT(u)» ( \ |
164 {0x0A39, POS_BELOW_C}, | 173 » » » » IS_DEVA(u) ? POS_AFTER_SUB : \ |
165 {0x0AB0, POS_BELOW_C}, | 174 » » » » IS_BENG(u) ? POS_AFTER_POST : \ |
166 {0x0B24, POS_BELOW_C}, | 175 » » » » IS_GURU(u) ? POS_AFTER_POST : \ |
167 {0x0B28, POS_BELOW_C}, | 176 » » » » IS_GUJR(u) ? POS_AFTER_POST : \ |
168 {0x0B2C, POS_BELOW_C}, | 177 » » » » IS_ORYA(u) ? POS_AFTER_POST : \ |
169 {0x0B2D, POS_BELOW_C}, | 178 » » » » IS_TAML(u) ? POS_AFTER_POST : \ |
170 {0x0B2E, POS_BELOW_C}, | 179 » » » » IS_TELU(u) ? (u <= 0x0C42 ? POS_BEFORE_SUB : P
OS_AFTER_SUB) : \ |
171 {0x0B2F, POS_POST_C}, | 180 » » » » IS_KNDA(u) ? (u < 0x0CC3 || u > 0xCD6 ? POS_BE
FORE_SUB : POS_AFTER_SUB) : \ |
172 {0x0B30, POS_BELOW_C}, | 181 » » » » IS_MLYM(u) ? POS_AFTER_POST : \ |
173 {0x0B32, POS_BELOW_C}, | 182 » » » » IS_SINH(u) ? POS_AFTER_SUB : \ |
174 {0x0B33, POS_BELOW_C}, | 183 » » » » IS_KHMR(u) ? POS_AFTER_POST : \ |
175 {0x0B5F, POS_POST_C}, | 184 » » » » /*default*/ POS_AFTER_SUB \ |
176 {0x0B71, POS_BELOW_C}, | 185 » » » » ) |
177 {0x0C15, POS_BELOW_C}, | 186 #define MATRA_POS_TOP(u)» ( /* BENG and MLYM don't have top matras. */ \ |
178 {0x0C16, POS_BELOW_C}, | 187 » » » » IS_DEVA(u) ? POS_AFTER_SUB : \ |
179 {0x0C17, POS_BELOW_C}, | 188 » » » » IS_GURU(u) ? POS_AFTER_POST : /* Deviate from
spec */ \ |
180 {0x0C18, POS_BELOW_C}, | 189 » » » » IS_GUJR(u) ? POS_AFTER_SUB : \ |
181 {0x0C19, POS_BELOW_C}, | 190 » » » » IS_ORYA(u) ? POS_AFTER_MAIN : \ |
182 {0x0C1A, POS_BELOW_C}, | 191 » » » » IS_TAML(u) ? POS_AFTER_SUB : \ |
183 {0x0C1B, POS_BELOW_C}, | 192 » » » » IS_TELU(u) ? POS_BEFORE_SUB : \ |
184 {0x0C1C, POS_BELOW_C}, | 193 » » » » IS_KNDA(u) ? POS_BEFORE_SUB : \ |
185 {0x0C1D, POS_BELOW_C}, | 194 » » » » IS_SINH(u) ? POS_AFTER_SUB : \ |
186 {0x0C1E, POS_BELOW_C}, | 195 » » » » IS_KHMR(u) ? POS_AFTER_POST : \ |
187 {0x0C1F, POS_BELOW_C}, | 196 » » » » /*default*/ POS_AFTER_SUB \ |
188 {0x0C20, POS_BELOW_C}, | 197 » » » » ) |
189 {0x0C21, POS_BELOW_C}, | 198 #define MATRA_POS_BOTTOM(u)» ( \ |
190 {0x0C22, POS_BELOW_C}, | 199 » » » » IS_DEVA(u) ? POS_AFTER_SUB : \ |
191 {0x0C23, POS_BELOW_C}, | 200 » » » » IS_BENG(u) ? POS_AFTER_SUB : \ |
192 {0x0C24, POS_BELOW_C}, | 201 » » » » IS_GURU(u) ? POS_AFTER_POST : \ |
193 {0x0C25, POS_BELOW_C}, | 202 » » » » IS_GUJR(u) ? POS_AFTER_POST : \ |
194 {0x0C26, POS_BELOW_C}, | 203 » » » » IS_ORYA(u) ? POS_AFTER_SUB : \ |
195 {0x0C27, POS_BELOW_C}, | 204 » » » » IS_TAML(u) ? POS_AFTER_POST : \ |
196 {0x0C28, POS_BELOW_C}, | 205 » » » » IS_TELU(u) ? POS_BEFORE_SUB : \ |
197 {0x0C2A, POS_BELOW_C}, | 206 » » » » IS_KNDA(u) ? POS_BEFORE_SUB : \ |
198 {0x0C2B, POS_BELOW_C}, | 207 » » » » IS_MLYM(u) ? POS_AFTER_POST : \ |
199 {0x0C2C, POS_BELOW_C}, | 208 » » » » IS_SINH(u) ? POS_AFTER_SUB : \ |
200 {0x0C2D, POS_BELOW_C}, | 209 » » » » IS_KHMR(u) ? POS_AFTER_POST : \ |
201 {0x0C2E, POS_BELOW_C}, | 210 » » » » /*default*/ POS_AFTER_SUB \ |
202 {0x0C2F, POS_BELOW_C}, | 211 » » » » ) |
203 {0x0C30, POS_BELOW_C}, | 212 |
204 {0x0C32, POS_BELOW_C}, | 213 |
205 {0x0C33, POS_BELOW_C}, | 214 static inline indic_position_t |
206 {0x0C35, POS_BELOW_C}, | 215 matra_position (hb_codepoint_t u, indic_position_t side) |
207 {0x0C36, POS_BELOW_C}, | 216 { |
208 {0x0C37, POS_BELOW_C}, | 217 switch ((int) side) |
209 {0x0C38, POS_BELOW_C}, | 218 { |
210 {0x0C39, POS_BELOW_C}, | 219 case POS_PRE_C:» return MATRA_POS_LEFT (u); |
211 {0x0C95, POS_BELOW_C}, | 220 case POS_POST_C:» return MATRA_POS_RIGHT (u); |
212 {0x0C96, POS_BELOW_C}, | 221 case POS_ABOVE_C:» return MATRA_POS_TOP (u); |
213 {0x0C97, POS_BELOW_C}, | 222 case POS_BELOW_C:» return MATRA_POS_BOTTOM (u); |
214 {0x0C98, POS_BELOW_C}, | 223 }; |
215 {0x0C99, POS_BELOW_C}, | 224 abort (); |
216 {0x0C9A, POS_BELOW_C}, | 225 } |
217 {0x0C9B, POS_BELOW_C}, | 226 |
218 {0x0C9C, POS_BELOW_C}, | 227 |
219 {0x0C9D, POS_BELOW_C}, | |
220 {0x0C9E, POS_BELOW_C}, | |
221 {0x0C9F, POS_BELOW_C}, | |
222 {0x0CA0, POS_BELOW_C}, | |
223 {0x0CA1, POS_BELOW_C}, | |
224 {0x0CA2, POS_BELOW_C}, | |
225 {0x0CA3, POS_BELOW_C}, | |
226 {0x0CA4, POS_BELOW_C}, | |
227 {0x0CA5, POS_BELOW_C}, | |
228 {0x0CA6, POS_BELOW_C}, | |
229 {0x0CA7, POS_BELOW_C}, | |
230 {0x0CA8, POS_BELOW_C}, | |
231 {0x0CAA, POS_BELOW_C}, | |
232 {0x0CAB, POS_BELOW_C}, | |
233 {0x0CAC, POS_BELOW_C}, | |
234 {0x0CAD, POS_BELOW_C}, | |
235 {0x0CAE, POS_BELOW_C}, | |
236 {0x0CAF, POS_BELOW_C}, | |
237 {0x0CB0, POS_BELOW_C}, | |
238 {0x0CB2, POS_BELOW_C}, | |
239 {0x0CB3, POS_BELOW_C}, | |
240 {0x0CB5, POS_BELOW_C}, | |
241 {0x0CB6, POS_BELOW_C}, | |
242 {0x0CB7, POS_BELOW_C}, | |
243 {0x0CB8, POS_BELOW_C}, | |
244 {0x0CB9, POS_BELOW_C}, | |
245 {0x0CDE, POS_BELOW_C}, | |
246 {0x0D2F, POS_POST_C}, | |
247 {0x0D30, POS_POST_C}, | |
248 {0x0D32, POS_BELOW_C}, | |
249 {0x0D35, POS_POST_C}, | |
250 }; | |
251 | 228 |
252 /* XXX | 229 /* XXX |
253 * This is a hack for now. We should move this data into the main Indic table. | 230 * This is a hack for now. We should move this data into the main Indic table. |
254 * Or completely remove it and just check in the tables. | 231 * Or completely remove it and just check in the tables. |
255 */ | 232 */ |
256 static const hb_codepoint_t ra_chars[] = { | 233 static const hb_codepoint_t ra_chars[] = { |
257 0x0930, /* Devanagari */ | 234 0x0930, /* Devanagari */ |
258 0x09B0, /* Bengali */ | 235 0x09B0, /* Bengali */ |
259 0x09F0, /* Bengali */ | 236 0x09F0, /* Bengali */ |
260 0x0A30, /* Gurmukhi */ /* No Reph */ | 237 0x0A30, /* Gurmukhi */ /* No Reph */ |
261 0x0AB0, /* Gujarati */ | 238 0x0AB0, /* Gujarati */ |
262 0x0B30, /* Oriya */ | 239 0x0B30, /* Oriya */ |
263 0x0BB0, /* Tamil */ /* No Reph */ | 240 0x0BB0, /* Tamil */ /* No Reph */ |
264 0x0C30, /* Telugu */» » /* No Reph */ | 241 0x0C30, /* Telugu */» » /* Reph formed only with ZWJ */ |
265 0x0CB0, /* Kannada */ | 242 0x0CB0, /* Kannada */ |
266 0x0D30, /* Malayalam */» /* No Reph */ | 243 0x0D30, /* Malayalam */» /* No Reph, Logical Repha */ |
| 244 |
| 245 0x0DBB, /* Sinhala */»» /* Reph formed only with ZWJ */ |
| 246 |
| 247 0x179A, /* Khmer */» » /* No Reph, Visual Repha */ |
267 }; | 248 }; |
268 | 249 |
| 250 static inline indic_position_t |
| 251 consonant_position (hb_codepoint_t u) |
| 252 { |
| 253 if ((u & ~0x007F) == 0x1780) |
| 254 return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not
be reordered. */ |
| 255 return POS_BASE_C; /* Will recategorize later based on font lookups. */ |
| 256 } |
| 257 |
| 258 static inline bool |
| 259 is_ra (hb_codepoint_t u) |
| 260 { |
| 261 for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++) |
| 262 if (u == ra_chars[i]) |
| 263 return true; |
| 264 return false; |
| 265 } |
| 266 |
| 267 |
| 268 static inline bool |
| 269 is_one_of (const hb_glyph_info_t &info, unsigned int flags) |
| 270 { |
| 271 /* If it ligated, all bets are off. */ |
| 272 if (is_a_ligature (info)) return false; |
| 273 return !!(FLAG (info.indic_category()) & flags); |
| 274 } |
| 275 |
| 276 #define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ)) |
| 277 static inline bool |
| 278 is_joiner (const hb_glyph_info_t &info) |
| 279 { |
| 280 return is_one_of (info, JOINER_FLAGS); |
| 281 } |
| 282 |
| 283 /* Note: |
| 284 * |
| 285 * We treat Vowels and placeholders as if they were consonants. This is safe be
cause Vowels |
| 286 * cannot happen in a consonant syllable. The plus side however is, we can call
the |
| 287 * consonant syllable logic from the vowel syllable function and get it all righ
t! */ |
| 288 #define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBS
P) | FLAG (OT_DOTTEDCIRCLE)) |
| 289 static inline bool |
| 290 is_consonant (const hb_glyph_info_t &info) |
| 291 { |
| 292 return is_one_of (info, CONSONANT_FLAGS); |
| 293 } |
| 294 |
| 295 #define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng)) |
| 296 static inline bool |
| 297 is_halant_or_coeng (const hb_glyph_info_t &info) |
| 298 { |
| 299 return is_one_of (info, HALANT_OR_COENG_FLAGS); |
| 300 } |
| 301 |
| 302 static inline void |
| 303 set_indic_properties (hb_glyph_info_t &info) |
| 304 { |
| 305 hb_codepoint_t u = info.codepoint; |
| 306 unsigned int type = get_indic_categories (u); |
| 307 indic_category_t cat = (indic_category_t) (type & 0x0F); |
| 308 indic_position_t pos = (indic_position_t) (type >> 4); |
| 309 |
| 310 |
| 311 /* |
| 312 * Re-assign category |
| 313 */ |
| 314 |
| 315 |
| 316 /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe |
| 317 * treats U+0951..U+0952 all as OT_VD. |
| 318 * TESTS: |
| 319 * U+092E,U+0947,U+0952 |
| 320 * U+092E,U+0952,U+0947 |
| 321 * U+092E,U+0947,U+0951 |
| 322 * U+092E,U+0951,U+0947 |
| 323 * */ |
| 324 if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0951, 0x0954))) |
| 325 cat = OT_VD; |
| 326 |
| 327 if (unlikely (u == 0x17D1)) |
| 328 cat = OT_X; |
| 329 if (cat == OT_X && |
| 330 unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CB, 0x17D3))) /* Khmer Vario
us signs */ |
| 331 { |
| 332 /* These are like Top Matras. */ |
| 333 cat = OT_M; |
| 334 pos = POS_ABOVE_C; |
| 335 } |
| 336 if (u == 0x17C6) /* Khmer Bindu doesn't like to be repositioned. */ |
| 337 cat = OT_N; |
| 338 |
| 339 if (unlikely (u == 0x17D2)) cat = OT_Coeng; /* Khmer coeng */ |
| 340 else if (unlikely (u == 0x200C)) cat = OT_ZWNJ; |
| 341 else if (unlikely (u == 0x200D)) cat = OT_ZWJ; |
| 342 else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE; |
| 343 else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. More like co
nsonant medial. like 0A75. */ |
| 344 |
| 345 if (cat == OT_Repha) { |
| 346 /* There are two kinds of characters marked as Repha: |
| 347 * - The ones that are GenCat=Mn are already positioned visually, ie. after
base. (eg. Khmer) |
| 348 * - The ones that are GenCat=Lo is encoded logically, ie. beginning of syll
able. (eg. Malayalam) |
| 349 * |
| 350 * We recategorize the first kind to look like a Nukta and attached to the b
ase directly. |
| 351 */ |
| 352 if (_hb_glyph_info_get_general_category (&info) == HB_UNICODE_GENERAL_CATEGO
RY_NON_SPACING_MARK) |
| 353 cat = OT_N; |
| 354 } |
| 355 |
| 356 |
| 357 |
| 358 /* |
| 359 * Re-assign position. |
| 360 */ |
| 361 |
| 362 if ((FLAG (cat) & CONSONANT_FLAGS)) |
| 363 { |
| 364 pos = consonant_position (u); |
| 365 if (is_ra (u)) |
| 366 cat = OT_Ra; |
| 367 } |
| 368 else if (cat == OT_M) |
| 369 { |
| 370 pos = matra_position (u, pos); |
| 371 } |
| 372 else if (cat == OT_SM || cat == OT_VD) |
| 373 { |
| 374 pos = POS_SMVD; |
| 375 } |
| 376 |
| 377 if (unlikely (u == 0x0B01)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub
in the spec. */ |
| 378 |
| 379 |
| 380 |
| 381 info.indic_category() = cat; |
| 382 info.indic_position() = pos; |
| 383 } |
| 384 |
| 385 |
269 | 386 |
270 #endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */ | 387 #endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */ |
OLD | NEW |