1 | /* == Start of generated functions == */ |
---|---|
2 | /* |
3 | * The following functions are generated by running: |
4 | * |
5 | * ./gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt |
6 | * |
7 | * on files with these headers: |
8 | * |
9 | * # IndicShapingInvalidCluster.txt |
10 | * # Date: 2015-03-12, 21:17:00 GMT [AG] |
11 | * # Date: 2019-11-08, 23:22:00 GMT [AG] |
12 | * |
13 | * # Scripts-15.0.0.txt |
14 | * # Date: 2022-04-26, 23:15:02 GMT |
15 | */ |
16 | |
17 | #include "hb.hh" |
18 | |
19 | #ifndef HB_NO_OT_SHAPE |
20 | |
21 | #include "hb-ot-shaper-vowel-constraints.hh" |
22 | |
23 | static void |
24 | _output_dotted_circle (hb_buffer_t *buffer) |
25 | { |
26 | (void) buffer->output_glyph (0x25CCu); |
27 | _hb_glyph_info_reset_continuation (&buffer->prev()); |
28 | } |
29 | |
30 | static void |
31 | _output_with_dotted_circle (hb_buffer_t *buffer) |
32 | { |
33 | _output_dotted_circle (buffer); |
34 | (void) buffer->next_glyph (); |
35 | } |
36 | |
37 | void |
38 | _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, |
39 | hb_buffer_t *buffer, |
40 | hb_font_t *font HB_UNUSED) |
41 | { |
42 | #ifdef HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS |
43 | return; |
44 | #endif |
45 | if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) |
46 | return; |
47 | |
48 | /* UGLY UGLY UGLY business of adding dotted-circle in the middle of |
49 | * vowel-sequences that look like another vowel. Data for each script |
50 | * collected from the USE script development spec. |
51 | * |
52 | * https://github.com/harfbuzz/harfbuzz/issues/1019 |
53 | */ |
54 | buffer->clear_output (); |
55 | unsigned int count = buffer->len; |
56 | switch ((unsigned) buffer->props.script) |
57 | { |
58 | case HB_SCRIPT_DEVANAGARI: |
59 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
60 | { |
61 | bool matched = false; |
62 | switch (buffer->cur ().codepoint) |
63 | { |
64 | case 0x0905u: |
65 | switch (buffer->cur (1).codepoint) |
66 | { |
67 | case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u: |
68 | case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu: |
69 | case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u: |
70 | matched = true; |
71 | break; |
72 | } |
73 | break; |
74 | case 0x0906u: |
75 | switch (buffer->cur (1).codepoint) |
76 | { |
77 | case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u: |
78 | case 0x0948u: |
79 | matched = true; |
80 | break; |
81 | } |
82 | break; |
83 | case 0x0909u: |
84 | matched = 0x0941u == buffer->cur (1).codepoint; |
85 | break; |
86 | case 0x090Fu: |
87 | switch (buffer->cur (1).codepoint) |
88 | { |
89 | case 0x0945u: case 0x0946u: case 0x0947u: |
90 | matched = true; |
91 | break; |
92 | } |
93 | break; |
94 | case 0x0930u: |
95 | if (0x094Du == buffer->cur (1).codepoint && |
96 | buffer->idx + 2 < count && |
97 | 0x0907u == buffer->cur (2).codepoint) |
98 | { |
99 | (void) buffer->next_glyph (); |
100 | matched = true; |
101 | } |
102 | break; |
103 | } |
104 | (void) buffer->next_glyph (); |
105 | if (matched) _output_with_dotted_circle (buffer); |
106 | } |
107 | break; |
108 | |
109 | case HB_SCRIPT_BENGALI: |
110 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
111 | { |
112 | bool matched = false; |
113 | switch (buffer->cur ().codepoint) |
114 | { |
115 | case 0x0985u: |
116 | matched = 0x09BEu == buffer->cur (1).codepoint; |
117 | break; |
118 | case 0x098Bu: |
119 | matched = 0x09C3u == buffer->cur (1).codepoint; |
120 | break; |
121 | case 0x098Cu: |
122 | matched = 0x09E2u == buffer->cur (1).codepoint; |
123 | break; |
124 | } |
125 | (void) buffer->next_glyph (); |
126 | if (matched) _output_with_dotted_circle (buffer); |
127 | } |
128 | break; |
129 | |
130 | case HB_SCRIPT_GURMUKHI: |
131 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
132 | { |
133 | bool matched = false; |
134 | switch (buffer->cur ().codepoint) |
135 | { |
136 | case 0x0A05u: |
137 | switch (buffer->cur (1).codepoint) |
138 | { |
139 | case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu: |
140 | matched = true; |
141 | break; |
142 | } |
143 | break; |
144 | case 0x0A72u: |
145 | switch (buffer->cur (1).codepoint) |
146 | { |
147 | case 0x0A3Fu: case 0x0A40u: case 0x0A47u: |
148 | matched = true; |
149 | break; |
150 | } |
151 | break; |
152 | case 0x0A73u: |
153 | switch (buffer->cur (1).codepoint) |
154 | { |
155 | case 0x0A41u: case 0x0A42u: case 0x0A4Bu: |
156 | matched = true; |
157 | break; |
158 | } |
159 | break; |
160 | } |
161 | (void) buffer->next_glyph (); |
162 | if (matched) _output_with_dotted_circle (buffer); |
163 | } |
164 | break; |
165 | |
166 | case HB_SCRIPT_GUJARATI: |
167 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
168 | { |
169 | bool matched = false; |
170 | switch (buffer->cur ().codepoint) |
171 | { |
172 | case 0x0A85u: |
173 | switch (buffer->cur (1).codepoint) |
174 | { |
175 | case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u: |
176 | case 0x0AC9u: case 0x0ACBu: case 0x0ACCu: |
177 | matched = true; |
178 | break; |
179 | } |
180 | break; |
181 | case 0x0AC5u: |
182 | matched = 0x0ABEu == buffer->cur (1).codepoint; |
183 | break; |
184 | } |
185 | (void) buffer->next_glyph (); |
186 | if (matched) _output_with_dotted_circle (buffer); |
187 | } |
188 | break; |
189 | |
190 | case HB_SCRIPT_ORIYA: |
191 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
192 | { |
193 | bool matched = false; |
194 | switch (buffer->cur ().codepoint) |
195 | { |
196 | case 0x0B05u: |
197 | matched = 0x0B3Eu == buffer->cur (1).codepoint; |
198 | break; |
199 | case 0x0B0Fu: case 0x0B13u: |
200 | matched = 0x0B57u == buffer->cur (1).codepoint; |
201 | break; |
202 | } |
203 | (void) buffer->next_glyph (); |
204 | if (matched) _output_with_dotted_circle (buffer); |
205 | } |
206 | break; |
207 | |
208 | case HB_SCRIPT_TAMIL: |
209 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
210 | { |
211 | bool matched = false; |
212 | if (0x0B85u == buffer->cur ().codepoint && |
213 | 0x0BC2u == buffer->cur (1).codepoint) |
214 | { |
215 | matched = true; |
216 | } |
217 | (void) buffer->next_glyph (); |
218 | if (matched) _output_with_dotted_circle (buffer); |
219 | } |
220 | break; |
221 | |
222 | case HB_SCRIPT_TELUGU: |
223 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
224 | { |
225 | bool matched = false; |
226 | switch (buffer->cur ().codepoint) |
227 | { |
228 | case 0x0C12u: |
229 | switch (buffer->cur (1).codepoint) |
230 | { |
231 | case 0x0C4Cu: case 0x0C55u: |
232 | matched = true; |
233 | break; |
234 | } |
235 | break; |
236 | case 0x0C3Fu: case 0x0C46u: case 0x0C4Au: |
237 | matched = 0x0C55u == buffer->cur (1).codepoint; |
238 | break; |
239 | } |
240 | (void) buffer->next_glyph (); |
241 | if (matched) _output_with_dotted_circle (buffer); |
242 | } |
243 | break; |
244 | |
245 | case HB_SCRIPT_KANNADA: |
246 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
247 | { |
248 | bool matched = false; |
249 | switch (buffer->cur ().codepoint) |
250 | { |
251 | case 0x0C89u: case 0x0C8Bu: |
252 | matched = 0x0CBEu == buffer->cur (1).codepoint; |
253 | break; |
254 | case 0x0C92u: |
255 | matched = 0x0CCCu == buffer->cur (1).codepoint; |
256 | break; |
257 | } |
258 | (void) buffer->next_glyph (); |
259 | if (matched) _output_with_dotted_circle (buffer); |
260 | } |
261 | break; |
262 | |
263 | case HB_SCRIPT_MALAYALAM: |
264 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
265 | { |
266 | bool matched = false; |
267 | switch (buffer->cur ().codepoint) |
268 | { |
269 | case 0x0D07u: case 0x0D09u: |
270 | matched = 0x0D57u == buffer->cur (1).codepoint; |
271 | break; |
272 | case 0x0D0Eu: |
273 | matched = 0x0D46u == buffer->cur (1).codepoint; |
274 | break; |
275 | case 0x0D12u: |
276 | switch (buffer->cur (1).codepoint) |
277 | { |
278 | case 0x0D3Eu: case 0x0D57u: |
279 | matched = true; |
280 | break; |
281 | } |
282 | break; |
283 | } |
284 | (void) buffer->next_glyph (); |
285 | if (matched) _output_with_dotted_circle (buffer); |
286 | } |
287 | break; |
288 | |
289 | case HB_SCRIPT_SINHALA: |
290 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
291 | { |
292 | bool matched = false; |
293 | switch (buffer->cur ().codepoint) |
294 | { |
295 | case 0x0D85u: |
296 | switch (buffer->cur (1).codepoint) |
297 | { |
298 | case 0x0DCFu: case 0x0DD0u: case 0x0DD1u: |
299 | matched = true; |
300 | break; |
301 | } |
302 | break; |
303 | case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u: |
304 | matched = 0x0DDFu == buffer->cur (1).codepoint; |
305 | break; |
306 | case 0x0D8Du: |
307 | matched = 0x0DD8u == buffer->cur (1).codepoint; |
308 | break; |
309 | case 0x0D91u: |
310 | switch (buffer->cur (1).codepoint) |
311 | { |
312 | case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu: |
313 | case 0x0DDDu: case 0x0DDEu: |
314 | matched = true; |
315 | break; |
316 | } |
317 | break; |
318 | } |
319 | (void) buffer->next_glyph (); |
320 | if (matched) _output_with_dotted_circle (buffer); |
321 | } |
322 | break; |
323 | |
324 | case HB_SCRIPT_BRAHMI: |
325 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
326 | { |
327 | bool matched = false; |
328 | switch (buffer->cur ().codepoint) |
329 | { |
330 | case 0x11005u: |
331 | matched = 0x11038u == buffer->cur (1).codepoint; |
332 | break; |
333 | case 0x1100Bu: |
334 | matched = 0x1103Eu == buffer->cur (1).codepoint; |
335 | break; |
336 | case 0x1100Fu: |
337 | matched = 0x11042u == buffer->cur (1).codepoint; |
338 | break; |
339 | } |
340 | (void) buffer->next_glyph (); |
341 | if (matched) _output_with_dotted_circle (buffer); |
342 | } |
343 | break; |
344 | |
345 | case HB_SCRIPT_KHOJKI: |
346 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
347 | { |
348 | bool matched = false; |
349 | switch (buffer->cur ().codepoint) |
350 | { |
351 | case 0x11200u: |
352 | switch (buffer->cur (1).codepoint) |
353 | { |
354 | case 0x1122Cu: case 0x11231u: case 0x11233u: |
355 | matched = true; |
356 | break; |
357 | } |
358 | break; |
359 | case 0x11206u: |
360 | matched = 0x1122Cu == buffer->cur (1).codepoint; |
361 | break; |
362 | case 0x1122Cu: |
363 | switch (buffer->cur (1).codepoint) |
364 | { |
365 | case 0x11230u: case 0x11231u: |
366 | matched = true; |
367 | break; |
368 | } |
369 | break; |
370 | case 0x11240u: |
371 | matched = 0x1122Eu == buffer->cur (1).codepoint; |
372 | break; |
373 | } |
374 | (void) buffer->next_glyph (); |
375 | if (matched) _output_with_dotted_circle (buffer); |
376 | } |
377 | break; |
378 | |
379 | case HB_SCRIPT_KHUDAWADI: |
380 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
381 | { |
382 | bool matched = false; |
383 | switch (buffer->cur ().codepoint) |
384 | { |
385 | case 0x112B0u: |
386 | switch (buffer->cur (1).codepoint) |
387 | { |
388 | case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u: |
389 | case 0x112E8u: |
390 | matched = true; |
391 | break; |
392 | } |
393 | break; |
394 | } |
395 | (void) buffer->next_glyph (); |
396 | if (matched) _output_with_dotted_circle (buffer); |
397 | } |
398 | break; |
399 | |
400 | case HB_SCRIPT_TIRHUTA: |
401 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
402 | { |
403 | bool matched = false; |
404 | switch (buffer->cur ().codepoint) |
405 | { |
406 | case 0x11481u: |
407 | matched = 0x114B0u == buffer->cur (1).codepoint; |
408 | break; |
409 | case 0x1148Bu: case 0x1148Du: |
410 | matched = 0x114BAu == buffer->cur (1).codepoint; |
411 | break; |
412 | case 0x114AAu: |
413 | switch (buffer->cur (1).codepoint) |
414 | { |
415 | case 0x114B5u: case 0x114B6u: |
416 | matched = true; |
417 | break; |
418 | } |
419 | break; |
420 | } |
421 | (void) buffer->next_glyph (); |
422 | if (matched) _output_with_dotted_circle (buffer); |
423 | } |
424 | break; |
425 | |
426 | case HB_SCRIPT_MODI: |
427 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
428 | { |
429 | bool matched = false; |
430 | switch (buffer->cur ().codepoint) |
431 | { |
432 | case 0x11600u: case 0x11601u: |
433 | switch (buffer->cur (1).codepoint) |
434 | { |
435 | case 0x11639u: case 0x1163Au: |
436 | matched = true; |
437 | break; |
438 | } |
439 | break; |
440 | } |
441 | (void) buffer->next_glyph (); |
442 | if (matched) _output_with_dotted_circle (buffer); |
443 | } |
444 | break; |
445 | |
446 | case HB_SCRIPT_TAKRI: |
447 | for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) |
448 | { |
449 | bool matched = false; |
450 | switch (buffer->cur ().codepoint) |
451 | { |
452 | case 0x11680u: |
453 | switch (buffer->cur (1).codepoint) |
454 | { |
455 | case 0x116ADu: case 0x116B4u: case 0x116B5u: |
456 | matched = true; |
457 | break; |
458 | } |
459 | break; |
460 | case 0x11686u: |
461 | matched = 0x116B2u == buffer->cur (1).codepoint; |
462 | break; |
463 | } |
464 | (void) buffer->next_glyph (); |
465 | if (matched) _output_with_dotted_circle (buffer); |
466 | } |
467 | break; |
468 | |
469 | default: |
470 | break; |
471 | } |
472 | buffer->sync (); |
473 | } |
474 | |
475 | |
476 | #endif |
477 | /* == End of generated functions == */ |
478 |