OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2011,2012 Google, Inc. | 2 * Copyright © 2011,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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 else if (unlikely (u == 0x1CEDu)) | 193 else if (unlikely (u == 0x1CEDu)) |
194 cat = OT_A; | 194 cat = OT_A; |
195 /* The following take marks in standalone clusters, similar to Avagraha. */ | 195 /* The following take marks in standalone clusters, similar to Avagraha. */ |
196 else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u, | 196 else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u, |
197 0x1CE9u, 0x1CECu, | 197 0x1CE9u, 0x1CECu, |
198 0x1CEEu, 0x1CF1u))) | 198 0x1CEEu, 0x1CF1u))) |
199 { | 199 { |
200 cat = OT_Symbol; | 200 cat = OT_Symbol; |
201 ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol); | 201 ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol); |
202 } | 202 } |
203 else if (unlikely (u == 0x17DDu)) /* https://github.com/roozbehp/unicode-data/
issues/2 */ | |
204 { | |
205 cat = OT_M; | |
206 pos = POS_ABOVE_C; | |
207 } | |
208 else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to b
e repositioned. */ | 203 else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to b
e repositioned. */ |
209 else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) | 204 else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) |
210 cat = OT_PLACEHOLDER; | 205 cat = OT_PLACEHOLDER; |
211 else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE; | 206 else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE; |
212 else if (unlikely (u == 0xA982u)) cat = OT_SM; /* Javanese repha. */ | |
213 else if (unlikely (u == 0xA9BEu)) cat = OT_CM2; /* Javanese medial ya. */ | |
214 else if (unlikely (u == 0xA9BDu)) { cat = OT_M; pos = POS_POST_C; } /* Javanes
e vocalic r. */ | |
215 | 207 |
216 | 208 |
217 /* | 209 /* |
218 * Re-assign position. | 210 * Re-assign position. |
219 */ | 211 */ |
220 | 212 |
221 if ((FLAG_SAFE (cat) & CONSONANT_FLAGS)) | 213 if ((FLAG_SAFE (cat) & CONSONANT_FLAGS)) |
222 { | 214 { |
223 pos = POS_BASE_C; | 215 pos = POS_BASE_C; |
224 if (is_ra (u)) | 216 if (is_ra (u)) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 enum reph_mode_t { | 262 enum reph_mode_t { |
271 REPH_MODE_IMPLICIT, /* Reph formed out of initial Ra,H sequence. */ | 263 REPH_MODE_IMPLICIT, /* Reph formed out of initial Ra,H sequence. */ |
272 REPH_MODE_EXPLICIT, /* Reph formed out of initial Ra,H,ZWJ sequence. */ | 264 REPH_MODE_EXPLICIT, /* Reph formed out of initial Ra,H,ZWJ sequence. */ |
273 REPH_MODE_VIS_REPHA, /* Encoded Repha character, no reordering needed. */ | 265 REPH_MODE_VIS_REPHA, /* Encoded Repha character, no reordering needed. */ |
274 REPH_MODE_LOG_REPHA /* Encoded Repha character, needs reordering. */ | 266 REPH_MODE_LOG_REPHA /* Encoded Repha character, needs reordering. */ |
275 }; | 267 }; |
276 enum blwf_mode_t { | 268 enum blwf_mode_t { |
277 BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-ba
se. */ | 269 BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-ba
se. */ |
278 BLWF_MODE_POST_ONLY /* Below-forms feature applied to post-base only. */ | 270 BLWF_MODE_POST_ONLY /* Below-forms feature applied to post-base only. */ |
279 }; | 271 }; |
280 enum pref_len_t { | |
281 PREF_LEN_1 = 1, | |
282 PREF_LEN_2 = 2, | |
283 PREF_LEN_DONT_CARE = PREF_LEN_2 | |
284 }; | |
285 struct indic_config_t | 272 struct indic_config_t |
286 { | 273 { |
287 hb_script_t script; | 274 hb_script_t script; |
288 bool has_old_spec; | 275 bool has_old_spec; |
289 hb_codepoint_t virama; | 276 hb_codepoint_t virama; |
290 base_position_t base_pos; | 277 base_position_t base_pos; |
291 reph_position_t reph_pos; | 278 reph_position_t reph_pos; |
292 reph_mode_t reph_mode; | 279 reph_mode_t reph_mode; |
293 blwf_mode_t blwf_mode; | 280 blwf_mode_t blwf_mode; |
294 pref_len_t pref_len; | |
295 }; | 281 }; |
296 | 282 |
297 static const indic_config_t indic_configs[] = | 283 static const indic_config_t indic_configs[] = |
298 { | 284 { |
299 /* Default. Should be first. */ | 285 /* Default. Should be first. */ |
300 {HB_SCRIPT_INVALID,» false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, | 286 {HB_SCRIPT_INVALID,» false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, |
301 {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, | 287 {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, |
302 {HB_SCRIPT_BENGALI,» true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, | 288 {HB_SCRIPT_BENGALI,» true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, |
303 {HB_SCRIPT_GURMUKHI,» true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, | 289 {HB_SCRIPT_GURMUKHI,» true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, |
304 {HB_SCRIPT_GUJARATI,» true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, | 290 {HB_SCRIPT_GUJARATI,» true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, |
305 {HB_SCRIPT_ORIYA,» true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, | 291 {HB_SCRIPT_ORIYA,» true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, |
306 {HB_SCRIPT_TAMIL,» true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, | 292 {HB_SCRIPT_TAMIL,» true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_M
ODE_IMPLICIT, BLWF_MODE_PRE_AND_POST}, |
307 {HB_SCRIPT_TELUGU,» true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_M
ODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, | 293 {HB_SCRIPT_TELUGU,» true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_M
ODE_EXPLICIT, BLWF_MODE_POST_ONLY}, |
308 {HB_SCRIPT_KANNADA,» true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_M
ODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, | 294 {HB_SCRIPT_KANNADA,» true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_M
ODE_IMPLICIT, BLWF_MODE_POST_ONLY}, |
309 {HB_SCRIPT_MALAYALAM,»true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_M
ODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, | 295 {HB_SCRIPT_MALAYALAM,»true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_M
ODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST}, |
310 {HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA, | 296 {HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA, |
311 » » » » » » REPH_POS_AFTER_MAIN, REPH_M
ODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, | 297 » » » » » » REPH_POS_AFTER_MAIN, REPH_M
ODE_EXPLICIT, BLWF_MODE_PRE_AND_POST}, |
312 {HB_SCRIPT_KHMER,» false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_M
ODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, | 298 {HB_SCRIPT_KHMER,» false,0x17D2u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_M
ODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST}, |
313 {HB_SCRIPT_JAVANESE,» false,0xA9C0u,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_M
ODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, | |
314 }; | 299 }; |
315 | 300 |
316 | 301 |
317 | 302 |
318 /* | 303 /* |
319 * Indic shaper. | 304 * Indic shaper. |
320 */ | 305 */ |
321 | 306 |
322 struct feature_list_t { | 307 struct feature_list_t { |
323 hb_tag_t tag; | 308 hb_tag_t tag; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 * 930,94D in 'blwf', not the expected 94D,930 (with new-spec | 566 * 930,94D in 'blwf', not the expected 94D,930 (with new-spec |
582 * table). As such, we simply match both sequences. Seems | 567 * table). As such, we simply match both sequences. Seems |
583 * to work. */ | 568 * to work. */ |
584 hb_codepoint_t glyphs[3] = {virama, consonant, virama}; | 569 hb_codepoint_t glyphs[3] = {virama, consonant, virama}; |
585 if (indic_plan->blwf.would_substitute (glyphs , 2, face) || | 570 if (indic_plan->blwf.would_substitute (glyphs , 2, face) || |
586 indic_plan->blwf.would_substitute (glyphs+1, 2, face)) | 571 indic_plan->blwf.would_substitute (glyphs+1, 2, face)) |
587 return POS_BELOW_C; | 572 return POS_BELOW_C; |
588 if (indic_plan->pstf.would_substitute (glyphs , 2, face) || | 573 if (indic_plan->pstf.would_substitute (glyphs , 2, face) || |
589 indic_plan->pstf.would_substitute (glyphs+1, 2, face)) | 574 indic_plan->pstf.would_substitute (glyphs+1, 2, face)) |
590 return POS_POST_C; | 575 return POS_POST_C; |
591 unsigned int pref_len = indic_plan->config->pref_len; | 576 if (indic_plan->pref.would_substitute (glyphs , 2, face) || |
592 if ((pref_len == PREF_LEN_2 && | 577 indic_plan->pref.would_substitute (glyphs+1, 2, face)) |
593 (indic_plan->pref.would_substitute (glyphs , 2, face) || | |
594 indic_plan->pref.would_substitute (glyphs+1, 2, face))) | |
595 || (pref_len == PREF_LEN_1 && | |
596 indic_plan->pref.would_substitute (glyphs+1, 1, face))) | |
597 return POS_POST_C; | 578 return POS_POST_C; |
598 return POS_BASE_C; | 579 return POS_BASE_C; |
599 } | 580 } |
600 | 581 |
601 | 582 |
602 enum syllable_type_t { | 583 enum syllable_type_t { |
603 consonant_syllable, | 584 consonant_syllable, |
604 vowel_syllable, | 585 vowel_syllable, |
605 standalone_cluster, | 586 standalone_cluster, |
606 symbol_cluster, | 587 symbol_cluster, |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 if (info[i ].indic_category() == OT_Ra && | 1073 if (info[i ].indic_category() == OT_Ra && |
1093 info[i+1].indic_category() == OT_H && | 1074 info[i+1].indic_category() == OT_H && |
1094 (i + 2 == base || | 1075 (i + 2 == base || |
1095 info[i+2].indic_category() != OT_ZWJ)) | 1076 info[i+2].indic_category() != OT_ZWJ)) |
1096 { | 1077 { |
1097 info[i ].mask |= indic_plan->mask_array[BLWF]; | 1078 info[i ].mask |= indic_plan->mask_array[BLWF]; |
1098 info[i+1].mask |= indic_plan->mask_array[BLWF]; | 1079 info[i+1].mask |= indic_plan->mask_array[BLWF]; |
1099 } | 1080 } |
1100 } | 1081 } |
1101 | 1082 |
1102 unsigned int pref_len = indic_plan->config->pref_len; | 1083 unsigned int pref_len = 2; |
1103 if (indic_plan->mask_array[PREF] && base + pref_len < end) | 1084 if (indic_plan->mask_array[PREF] && base + pref_len < end) |
1104 { | 1085 { |
1105 assert (1 <= pref_len && pref_len <= 2); | |
1106 /* Find a Halant,Ra sequence and mark it for pre-base reordering processing.
*/ | 1086 /* Find a Halant,Ra sequence and mark it for pre-base reordering processing.
*/ |
1107 for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) { | 1087 for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) { |
1108 hb_codepoint_t glyphs[2]; | 1088 hb_codepoint_t glyphs[2]; |
1109 for (unsigned int j = 0; j < pref_len; j++) | 1089 for (unsigned int j = 0; j < pref_len; j++) |
1110 glyphs[j] = info[i + j].codepoint; | 1090 glyphs[j] = info[i + j].codepoint; |
1111 if (indic_plan->pref.would_substitute (glyphs, pref_len, face)) | 1091 if (indic_plan->pref.would_substitute (glyphs, pref_len, face)) |
1112 { | 1092 { |
1113 for (unsigned int j = 0; j < pref_len; j++) | 1093 for (unsigned int j = 0; j < pref_len; j++) |
1114 info[i++].mask |= indic_plan->mask_array[PREF]; | 1094 info[i++].mask |= indic_plan->mask_array[PREF]; |
1115 | 1095 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1305 * cluster. | 1285 * cluster. |
1306 */ | 1286 */ |
1307 | 1287 |
1308 bool try_pref = !!indic_plan->mask_array[PREF]; | 1288 bool try_pref = !!indic_plan->mask_array[PREF]; |
1309 | 1289 |
1310 /* Find base again */ | 1290 /* Find base again */ |
1311 unsigned int base; | 1291 unsigned int base; |
1312 for (base = start; base < end; base++) | 1292 for (base = start; base < end; base++) |
1313 if (info[base].indic_position() >= POS_BASE_C) | 1293 if (info[base].indic_position() >= POS_BASE_C) |
1314 { | 1294 { |
1315 if (try_pref && base + 1 < end && indic_plan->config->pref_len == 2) | 1295 if (try_pref && base + 1 < end) |
1316 { | 1296 { |
1317 for (unsigned int i = base + 1; i < end; i++) | 1297 for (unsigned int i = base + 1; i < end; i++) |
1318 if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) | 1298 if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) |
1319 { | 1299 { |
1320 if (!(_hb_glyph_info_substituted (&info[i]) && | 1300 if (!(_hb_glyph_info_substituted (&info[i]) && |
1321 _hb_glyph_info_ligated_and_didnt_multiply (&info[i]))) | 1301 _hb_glyph_info_ligated_and_didnt_multiply (&info[i]))) |
1322 { | 1302 { |
1323 /* Ok, this was a 'pref' candidate but didn't form any. | 1303 /* Ok, this was a 'pref' candidate but didn't form any. |
1324 * Base is around here... */ | 1304 * Base is around here... */ |
1325 base = i; | 1305 base = i; |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1587 | 1567 |
1588 | 1568 |
1589 /* o Reorder pre-base reordering consonants: | 1569 /* o Reorder pre-base reordering consonants: |
1590 * | 1570 * |
1591 * If a pre-base reordering consonant is found, reorder it according to | 1571 * If a pre-base reordering consonant is found, reorder it according to |
1592 * the following rules: | 1572 * the following rules: |
1593 */ | 1573 */ |
1594 | 1574 |
1595 if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base reord
ering Ra. */ | 1575 if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base reord
ering Ra. */ |
1596 { | 1576 { |
1597 unsigned int pref_len = indic_plan->config->pref_len; | |
1598 for (unsigned int i = base + 1; i < end; i++) | 1577 for (unsigned int i = base + 1; i < end; i++) |
1599 if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) | 1578 if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) |
1600 { | 1579 { |
1601 /* 1. Only reorder a glyph produced by substitution during applica
tion | 1580 /* 1. Only reorder a glyph produced by substitution during applica
tion |
1602 * of the <pref> feature. (Note that a font may shape a Ra cons
onant with | 1581 * of the <pref> feature. (Note that a font may shape a Ra cons
onant with |
1603 * the feature generally but block it in certain contexts.) | 1582 * the feature generally but block it in certain contexts.) |
1604 */ | 1583 */ |
1605 /* Note: We just check that something got substituted. We don't check t
hat | 1584 /* Note: We just check that something got substituted. We don't check t
hat |
1606 * the <pref> feature actually did it... | 1585 * the <pref> feature actually did it... |
1607 * | 1586 * |
1608 » * If pref len is longer than one, then only reorder if it ligated. If | 1587 » * Reorder pref only if it ligated. */ |
1609 » * pref len is one, only reorder if it didn't ligate with other things.
*/ | 1588 » if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i])) |
1610 » if (_hb_glyph_info_substituted (&info[i]) && | |
1611 » ((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[
i]))) | |
1612 { | 1589 { |
1613 /* | 1590 /* |
1614 * 2. Try to find a target position the same way as for pre-base
matra. | 1591 * 2. Try to find a target position the same way as for pre-base
matra. |
1615 * If it is found, reorder pre-base consonant glyph. | 1592 * If it is found, reorder pre-base consonant glyph. |
1616 * | 1593 * |
1617 * 3. If position is not found, reorder immediately before main | 1594 * 3. If position is not found, reorder immediately before main |
1618 * consonant. | 1595 * consonant. |
1619 */ | 1596 */ |
1620 | 1597 |
1621 unsigned int new_pos = base; | 1598 unsigned int new_pos = base; |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1838 data_destroy_indic, | 1815 data_destroy_indic, |
1839 NULL, /* preprocess_text */ | 1816 NULL, /* preprocess_text */ |
1840 NULL, /* postprocess_glyphs */ | 1817 NULL, /* postprocess_glyphs */ |
1841 HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, | 1818 HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, |
1842 decompose_indic, | 1819 decompose_indic, |
1843 compose_indic, | 1820 compose_indic, |
1844 setup_masks_indic, | 1821 setup_masks_indic, |
1845 HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, | 1822 HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, |
1846 false, /* fallback_position */ | 1823 false, /* fallback_position */ |
1847 }; | 1824 }; |
OLD | NEW |