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
23static 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
30static void
31_output_with_dotted_circle (hb_buffer_t *buffer)
32{
33 _output_dotted_circle (buffer);
34 (void) buffer->next_glyph ();
35}
36
37void
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