2 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 * This is part of HarfBuzz, an OpenType Layout engine library.
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 #include "harfbuzz-shaper.h"
26 #include "harfbuzz-shaper-private.h"
31 #define FLAG(x) (1 << (x))
33 static HB_Bool isLetter(HB_UChar16 ucs)
35 const int test = FLAG(HB_Letter_Uppercase) |
36 FLAG(HB_Letter_Lowercase) |
37 FLAG(HB_Letter_Titlecase) |
38 FLAG(HB_Letter_Modifier) |
39 FLAG(HB_Letter_Other);
40 return FLAG(HB_GetUnicodeCharCategory(ucs)) & test;
43 static HB_Bool isMark(HB_UChar16 ucs)
45 const int test = FLAG(HB_Mark_NonSpacing) |
46 FLAG(HB_Mark_SpacingCombining) |
47 FLAG(HB_Mark_Enclosing);
48 return FLAG(HB_GetUnicodeCharCategory(ucs)) & test;
53 UnknownForm = Invalid,
66 static const unsigned char indicForms[0xe00-0x900] = {
68 Invalid, VowelMark, VowelMark, VowelMark,
69 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
70 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
71 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
73 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
74 IndependentVowel, Consonant, Consonant, Consonant,
75 Consonant, Consonant, Consonant, Consonant,
76 Consonant, Consonant, Consonant, Consonant,
78 Consonant, Consonant, Consonant, Consonant,
79 Consonant, Consonant, Consonant, Consonant,
80 Consonant, Consonant, Consonant, Consonant,
81 Consonant, Consonant, Consonant, Consonant,
83 Consonant, Consonant, Consonant, Consonant,
84 Consonant, Consonant, Consonant, Consonant,
85 Consonant, Consonant, UnknownForm, UnknownForm,
86 Nukta, Other, Matra, Matra,
88 Matra, Matra, Matra, Matra,
89 Matra, Matra, Matra, Matra,
90 Matra, Matra, Matra, Matra,
91 Matra, Halant, UnknownForm, UnknownForm,
93 Other, StressMark, StressMark, StressMark,
94 StressMark, UnknownForm, UnknownForm, UnknownForm,
95 Consonant, Consonant, Consonant, Consonant,
96 Consonant, Consonant, Consonant, Consonant,
98 IndependentVowel, IndependentVowel, VowelMark, VowelMark,
99 Other, Other, Other, Other,
100 Other, Other, Other, Other,
101 Other, Other, Other, Other,
103 Other, Other, Other, Other,
104 Other, Other, Other, Other,
105 Other, Other, Other, Consonant,
106 Consonant, Consonant /* ??? */, Consonant, Consonant,
109 Invalid, VowelMark, VowelMark, VowelMark,
110 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
111 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
112 IndependentVowel, Invalid, Invalid, IndependentVowel,
114 IndependentVowel, Invalid, Invalid, IndependentVowel,
115 IndependentVowel, Consonant, Consonant, Consonant,
116 Consonant, Consonant, Consonant, Consonant,
117 Consonant, Consonant, Consonant, Consonant,
119 Consonant, Consonant, Consonant, Consonant,
120 Consonant, Consonant, Consonant, Consonant,
121 Consonant, Invalid, Consonant, Consonant,
122 Consonant, Consonant, Consonant, Consonant,
124 Consonant, Invalid, Consonant, Invalid,
125 Invalid, Invalid, Consonant, Consonant,
126 Consonant, Consonant, UnknownForm, UnknownForm,
127 Nukta, Other, Matra, Matra,
129 Matra, Matra, Matra, Matra,
130 Matra, Invalid, Invalid, Matra,
131 Matra, Invalid, Invalid, Matra,
132 Matra, Halant, Consonant, UnknownForm,
134 Invalid, Invalid, Invalid, Invalid,
135 Invalid, Invalid, Invalid, VowelMark,
136 Invalid, Invalid, Invalid, Invalid,
137 Consonant, Consonant, Invalid, Consonant,
139 IndependentVowel, IndependentVowel, VowelMark, VowelMark,
140 Other, Other, Other, Other,
141 Other, Other, Other, Other,
142 Other, Other, Other, Other,
144 Consonant, Consonant, Other, Other,
145 Other, Other, Other, Other,
146 Other, Other, Other, Other,
147 Other, Other, Other, Other,
150 Invalid, VowelMark, VowelMark, VowelMark,
151 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
152 IndependentVowel, IndependentVowel, IndependentVowel, Invalid,
153 Invalid, Invalid, Invalid, IndependentVowel,
155 IndependentVowel, Invalid, Invalid, IndependentVowel,
156 IndependentVowel, Consonant, Consonant, Consonant,
157 Consonant, Consonant, Consonant, Consonant,
158 Consonant, Consonant, Consonant, Consonant,
160 Consonant, Consonant, Consonant, Consonant,
161 Consonant, Consonant, Consonant, Consonant,
162 Consonant, Invalid, Consonant, Consonant,
163 Consonant, Consonant, Consonant, Consonant,
165 Consonant, Invalid, Consonant, Consonant,
166 Invalid, Consonant, Consonant, Invalid,
167 Consonant, Consonant, UnknownForm, UnknownForm,
168 Nukta, Other, Matra, Matra,
170 Matra, Matra, Matra, Invalid,
171 Invalid, Invalid, Invalid, Matra,
172 Matra, Invalid, Invalid, Matra,
173 Matra, Halant, UnknownForm, UnknownForm,
175 Invalid, Invalid, Invalid, Invalid,
176 Invalid, UnknownForm, UnknownForm, UnknownForm,
177 Invalid, Consonant, Consonant, Consonant,
178 Consonant, Invalid, Consonant, Invalid,
180 Other, Other, Invalid, Invalid,
181 Other, Other, Other, Other,
182 Other, Other, Other, Other,
183 Other, Other, Other, Other,
185 StressMark, StressMark, Consonant, Consonant,
186 Other, Other, Other, Other,
187 Other, Other, Other, Other,
188 Other, Other, Other, Other,
191 Invalid, VowelMark, VowelMark, VowelMark,
192 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
193 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
194 IndependentVowel, IndependentVowel, Invalid, IndependentVowel,
196 IndependentVowel, IndependentVowel, Invalid, IndependentVowel,
197 IndependentVowel, Consonant, Consonant, Consonant,
198 Consonant, Consonant, Consonant, Consonant,
199 Consonant, Consonant, Consonant, Consonant,
201 Consonant, Consonant, Consonant, Consonant,
202 Consonant, Consonant, Consonant, Consonant,
203 Consonant, Invalid, Consonant, Consonant,
204 Consonant, Consonant, Consonant, Consonant,
206 Consonant, Invalid, Consonant, Consonant,
207 Invalid, Consonant, Consonant, Consonant,
208 Consonant, Consonant, UnknownForm, UnknownForm,
209 Nukta, Other, Matra, Matra,
211 Matra, Matra, Matra, Matra,
212 Matra, Matra, Invalid, Matra,
213 Matra, Matra, Invalid, Matra,
214 Matra, Halant, UnknownForm, UnknownForm,
216 Other, UnknownForm, UnknownForm, UnknownForm,
217 UnknownForm, UnknownForm, UnknownForm, UnknownForm,
218 UnknownForm, UnknownForm, UnknownForm, UnknownForm,
219 UnknownForm, UnknownForm, UnknownForm, UnknownForm,
221 IndependentVowel, IndependentVowel, VowelMark, VowelMark,
222 Other, Other, Other, Other,
223 Other, Other, Other, Other,
224 Other, Other, Other, Other,
226 Other, Other, Other, Other,
227 Other, Other, Other, Other,
228 Other, Other, Other, Other,
229 Other, Other, Other, Other,
232 Invalid, VowelMark, VowelMark, VowelMark,
233 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
234 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
235 IndependentVowel, Invalid, Invalid, IndependentVowel,
237 IndependentVowel, Invalid, Invalid, IndependentVowel,
238 IndependentVowel, Consonant, Consonant, Consonant,
239 Consonant, Consonant, Consonant, Consonant,
240 Consonant, Consonant, Consonant, Consonant,
242 Consonant, Consonant, Consonant, Consonant,
243 Consonant, Consonant, Consonant, Consonant,
244 Consonant, Invalid, Consonant, Consonant,
245 Consonant, Consonant, Consonant, Consonant,
247 Consonant, Invalid, Consonant, Consonant,
248 Invalid, Consonant, Consonant, Consonant,
249 Consonant, Consonant, UnknownForm, UnknownForm,
250 Nukta, Other, Matra, Matra,
252 Matra, Matra, Matra, Matra,
253 Invalid, Invalid, Invalid, Matra,
254 Matra, Invalid, Invalid, Matra,
255 Matra, Halant, UnknownForm, UnknownForm,
257 Other, Invalid, Invalid, Invalid,
258 Invalid, UnknownForm, LengthMark, LengthMark,
259 Invalid, Invalid, Invalid, Invalid,
260 Consonant, Consonant, Invalid, Consonant,
262 IndependentVowel, IndependentVowel, Invalid, Invalid,
263 Invalid, Invalid, Other, Other,
264 Other, Other, Other, Other,
265 Other, Other, Other, Other,
267 Other, Consonant, Other, Other,
268 Other, Other, Other, Other,
269 Other, Other, Other, Other,
270 Other, Other, Other, Other,
273 Invalid, Invalid, VowelMark, Other,
274 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
275 IndependentVowel, IndependentVowel, IndependentVowel, Invalid,
276 Invalid, Invalid, IndependentVowel, IndependentVowel,
278 IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
279 IndependentVowel, Consonant, Invalid, Invalid,
280 Invalid, Consonant, Consonant, Invalid,
281 Consonant, Invalid, Consonant, Consonant,
283 Invalid, Invalid, Invalid, Consonant,
284 Consonant, Invalid, Invalid, Invalid,
285 Consonant, Consonant, Consonant, Invalid,
286 Invalid, Invalid, Consonant, Consonant,
288 Consonant, Consonant, Consonant, Consonant,
289 Consonant, Consonant, Consonant, Consonant,
290 Consonant, Consonant, UnknownForm, UnknownForm,
291 Invalid, Invalid, Matra, Matra,
293 Matra, Matra, Matra, Invalid,
294 Invalid, Invalid, Matra, Matra,
295 Matra, Invalid, Matra, Matra,
296 Matra, Halant, Invalid, Invalid,
298 Invalid, Invalid, Invalid, Invalid,
299 Invalid, Invalid, Invalid, LengthMark,
300 Invalid, Invalid, Invalid, Invalid,
301 Invalid, Invalid, Invalid, Invalid,
303 Invalid, Invalid, Invalid, Invalid,
304 Invalid, Invalid, Other, Other,
305 Other, Other, Other, Other,
306 Other, Other, Other, Other,
308 Other, Other, Other, Other,
309 Other, Other, Other, Other,
310 Other, Other, Other, Other,
311 Other, Other, Other, Other,
314 Invalid, VowelMark, VowelMark, VowelMark,
315 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
316 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
317 IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
319 IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
320 IndependentVowel, Consonant, Consonant, Consonant,
321 Consonant, Consonant, Consonant, Consonant,
322 Consonant, Consonant, Consonant, Consonant,
324 Consonant, Consonant, Consonant, Consonant,
325 Consonant, Consonant, Consonant, Consonant,
326 Consonant, Invalid, Consonant, Consonant,
327 Consonant, Consonant, Consonant, Consonant,
329 Consonant, Consonant, Consonant, Consonant,
330 Invalid, Consonant, Consonant, Consonant,
331 Consonant, Consonant, UnknownForm, UnknownForm,
332 Invalid, Invalid, Matra, Matra,
334 Matra, Matra, Matra, Matra,
335 Matra, Invalid, Matra, Matra,
336 Matra, Invalid, Matra, Matra,
337 Matra, Halant, Invalid, Invalid,
339 Invalid, Invalid, Invalid, Invalid,
340 Invalid, LengthMark, Matra, Invalid,
341 Invalid, Invalid, Invalid, Invalid,
342 Invalid, Invalid, Invalid, Invalid,
344 IndependentVowel, IndependentVowel, Invalid, Invalid,
345 Invalid, Invalid, Other, Other,
346 Other, Other, Other, Other,
347 Other, Other, Other, Other,
349 Other, Other, Other, Other,
350 Other, Other, Other, Other,
351 Other, Other, Other, Other,
352 Other, Other, Other, Other,
355 Invalid, Invalid, VowelMark, VowelMark,
356 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
357 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
358 IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
360 IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
361 IndependentVowel, Consonant, Consonant, Consonant,
362 Consonant, Consonant, Consonant, Consonant,
363 Consonant, Consonant, Consonant, Consonant,
365 Consonant, Consonant, Consonant, Consonant,
366 Consonant, Consonant, Consonant, Consonant,
367 Consonant, Invalid, Consonant, Consonant,
368 Consonant, Consonant, Consonant, Consonant,
370 Consonant, Consonant, Consonant, Consonant,
371 Invalid, Consonant, Consonant, Consonant,
372 Consonant, Consonant, UnknownForm, UnknownForm,
373 Nukta, Other, Matra, Matra,
375 Matra, Matra, Matra, Matra,
376 Matra, Invalid, Matra, Matra,
377 Matra, Invalid, Matra, Matra,
378 Matra, Halant, Invalid, Invalid,
380 Invalid, Invalid, Invalid, Invalid,
381 Invalid, LengthMark, LengthMark, Invalid,
382 Invalid, Invalid, Invalid, Invalid,
383 Invalid, Invalid, Consonant, Invalid,
385 IndependentVowel, IndependentVowel, VowelMark, VowelMark,
386 Invalid, Invalid, Other, Other,
387 Other, Other, Other, Other,
388 Other, Other, Other, Other,
390 Other, Other, Other, Other,
391 Other, Other, Other, Other,
392 Other, Other, Other, Other,
393 Other, Other, Other, Other,
396 Invalid, Invalid, VowelMark, VowelMark,
397 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
398 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
399 IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
401 IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
402 IndependentVowel, Consonant, Consonant, Consonant,
403 Consonant, Consonant, Consonant, Consonant,
404 Consonant, Consonant, Consonant, Consonant,
406 Consonant, Consonant, Consonant, Consonant,
407 Consonant, Consonant, Consonant, Consonant,
408 Consonant, Invalid, Consonant, Consonant,
409 Consonant, Consonant, Consonant, Consonant,
411 Consonant, Consonant, Consonant, Consonant,
412 Consonant, Consonant, Consonant, Consonant,
413 Consonant, Consonant, UnknownForm, UnknownForm,
414 Invalid, Invalid, Matra, Matra,
416 Matra, Matra, Matra, Matra,
417 Invalid, Invalid, Matra, Matra,
418 Matra, Invalid, Matra, Matra,
419 Matra, Halant, Invalid, Invalid,
421 Invalid, Invalid, Invalid, Invalid,
422 Invalid, Invalid, Invalid, Matra,
423 Invalid, Invalid, Invalid, Invalid,
424 Invalid, Invalid, Invalid, Invalid,
426 IndependentVowel, IndependentVowel, Invalid, Invalid,
427 Invalid, Invalid, Other, Other,
428 Other, Other, Other, Other,
429 Other, Other, Other, Other,
431 Other, Other, Other, Other,
432 Other, Other, Other, Other,
433 Other, Other, Other, Other,
434 Other, Other, Other, Other,
437 Invalid, Invalid, VowelMark, VowelMark,
438 Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
439 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
440 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
442 IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
443 IndependentVowel, IndependentVowel, IndependentVowel, Invalid,
444 Invalid, Invalid, Consonant, Consonant,
445 Consonant, Consonant, Consonant, Consonant,
447 Consonant, Consonant, Consonant, Consonant,
448 Consonant, Consonant, Consonant, Consonant,
449 Consonant, Consonant, Consonant, Consonant,
450 Consonant, Consonant, Consonant, Consonant,
452 Consonant, Consonant, Invalid, Consonant,
453 Consonant, Consonant, Consonant, Consonant,
454 Consonant, Consonant, Consonant, Consonant,
455 Invalid, Consonant, Invalid, Invalid,
457 Consonant, Consonant, Consonant, Consonant,
458 Consonant, Consonant, Consonant, Invalid,
459 Invalid, Invalid, Halant, Invalid,
460 Invalid, Invalid, Invalid, Matra,
462 Matra, Matra, Matra, Matra,
463 Matra, Invalid, Matra, Invalid,
464 Matra, Matra, Matra, Matra,
465 Matra, Matra, Matra, Matra,
467 Invalid, Invalid, Invalid, Invalid,
468 Invalid, Invalid, Invalid, Invalid,
469 Invalid, Invalid, Invalid, Invalid,
470 Invalid, Invalid, Invalid, Invalid,
472 Invalid, Invalid, Matra, Matra,
473 Other, Other, Other, Other,
474 Other, Other, Other, Other,
475 Other, Other, Other, Other,
478 typedef enum _Position {
491 static const unsigned char indicPosition[0xe00-0x900] = {
493 None, Above, Above, Post,
494 None, None, None, None,
495 None, None, None, None,
496 None, None, None, None,
498 None, None, None, None,
499 None, None, None, None,
500 None, None, None, None,
501 None, None, None, None,
503 None, None, None, None,
504 None, None, None, None,
505 None, None, None, None,
506 None, None, None, None,
508 Below, None, None, None,
509 None, None, None, None,
510 None, None, None, None,
511 None, None, Post, Pre,
513 Post, Below, Below, Below,
514 Below, Above, Above, Above,
515 Above, Post, Post, Post,
516 Post, None, None, None,
518 None, Above, Below, Above,
519 Above, None, None, None,
520 None, None, None, None,
521 None, None, None, None,
523 None, None, Below, Below,
524 None, None, None, None,
525 None, None, None, None,
526 None, None, None, None,
528 None, None, None, None,
529 None, None, None, None,
530 None, None, None, None,
531 None, None, None, None,
534 None, Above, Post, Post,
535 None, None, None, None,
536 None, None, None, None,
537 None, None, None, None,
539 None, None, None, None,
540 None, None, None, None,
541 None, None, None, None,
542 None, None, None, None,
544 None, None, None, None,
545 None, None, None, None,
546 None, None, None, None,
547 Below, None, None, Post,
549 Below, None, None, None,
550 None, None, None, None,
551 None, None, None, None,
552 Below, None, Post, Pre,
554 Post, Below, Below, Below,
555 Below, None, None, Pre,
556 Pre, None, None, Split,
557 Split, Below, None, None,
559 None, None, None, None,
560 None, None, None, Post,
561 None, None, None, None,
562 None, None, None, None,
564 None, None, Below, Below,
565 None, None, None, None,
566 None, None, None, None,
567 None, None, None, None,
569 Below, None, None, None,
570 None, None, None, None,
571 None, None, None, None,
572 None, None, None, None,
575 None, Above, Above, Post,
576 None, None, None, None,
577 None, None, None, None,
578 None, None, None, None,
580 None, None, None, None,
581 None, None, None, None,
582 None, None, None, None,
583 None, None, None, None,
585 None, None, None, None,
586 None, None, None, None,
587 None, None, None, None,
588 None, None, None, Post,
590 Below, None, None, None,
591 None, Below, None, None,
592 None, Below, None, None,
593 Below, None, Post, Pre,
595 Post, Below, Below, None,
596 None, None, None, Above,
597 Above, None, None, Above,
598 Above, None, None, None,
600 None, None, None, None,
601 None, None, None, None,
602 None, None, None, None,
603 None, None, None, None,
605 None, None, None, None,
606 None, None, None, None,
607 None, None, None, None,
608 None, None, None, None,
610 Above, Above, None, None,
611 None, None, None, None,
612 None, None, None, None,
613 None, None, None, None,
616 None, Above, Above, Post,
617 None, None, None, None,
618 None, None, None, None,
619 None, None, None, None,
621 None, None, None, None,
622 None, None, None, None,
623 None, None, None, None,
624 None, None, None, None,
626 None, None, None, None,
627 None, None, None, None,
628 None, None, None, None,
629 None, None, None, None,
631 Below, None, None, None,
632 None, None, None, None,
633 None, None, None, None,
634 None, None, Post, Pre,
636 Post, Below, Below, Below,
637 Below, Above, None, Above,
638 Above, Post, None, Post,
639 Post, None, None, None,
641 None, None, None, None,
642 None, None, None, None,
643 None, None, None, None,
644 None, None, None, None,
646 None, None, Below, Below,
647 None, None, None, None,
648 None, None, None, None,
649 None, None, None, None,
651 None, None, None, None,
652 None, None, None, None,
653 None, None, None, None,
654 None, None, None, None,
657 None, Above, Post, Post,
658 None, None, None, None,
659 None, None, None, None,
660 None, None, None, None,
662 None, None, None, None,
663 None, None, None, None,
664 None, None, None, None,
665 None, None, None, None,
667 None, None, None, None,
668 Below, None, None, None,
669 Below, None, None, None,
670 Below, Below, Below, Post,
672 Below, None, Below, Below,
673 None, None, None, None,
674 None, None, None, None,
675 None, None, Post, Above,
677 Post, Below, Below, Below,
678 None, None, None, Pre,
679 Split, None, None, Split,
680 Split, None, None, None,
682 None, None, None, None,
683 None, None, Above, Post,
684 None, None, None, None,
685 None, None, None, Post,
687 None, None, None, None,
688 None, None, None, None,
689 None, None, None, None,
690 None, None, None, None,
692 None, Below, None, None,
693 None, None, None, None,
694 None, None, None, None,
695 None, None, None, None,
698 None, None, Above, None,
699 None, None, None, None,
700 None, None, None, None,
701 None, None, None, None,
703 None, None, None, None,
704 None, None, None, None,
705 None, None, None, None,
706 None, None, None, None,
708 None, None, None, None,
709 None, None, None, None,
710 None, None, None, None,
711 None, None, None, None,
713 None, None, None, None,
714 None, None, None, None,
715 None, None, None, None,
716 None, None, Post, Post,
718 Above, Below, Below, None,
719 None, None, Pre, Pre,
720 Pre, None, Split, Split,
721 Split, Halant, None, None,
723 None, None, None, None,
724 None, None, None, Post,
725 None, None, None, None,
726 None, None, None, None,
728 None, None, None, None,
729 None, None, None, None,
730 None, None, None, None,
731 None, None, None, None,
733 None, None, None, None,
734 None, None, None, None,
735 None, None, None, None,
736 None, None, None, None,
739 None, Post, Post, Post,
740 None, None, None, None,
741 None, None, None, None,
742 None, None, None, None,
744 None, None, None, None,
745 None, Below, Below, Below,
746 Below, Below, Below, Below,
747 Below, Below, Below, Below,
749 Below, Below, Below, Below,
750 Below, Below, Below, Below,
751 Below, None, Below, Below,
752 Below, Below, Below, Below,
754 Below, None, Below, Below,
755 None, Below, Below, Below,
756 Below, Below, None, None,
757 None, None, Post, Above,
759 Above, Post, Post, Post,
760 Post, None, Above, Above,
761 Split, None, Post, Above,
762 Above, Halant, None, None,
764 None, None, None, None,
765 None, Above, Below, None,
766 None, None, None, None,
767 None, None, None, None,
769 None, None, None, None,
770 None, None, None, None,
771 None, None, None, None,
772 None, None, None, None,
774 None, None, None, None,
775 None, None, None, None,
776 None, None, None, None,
777 None, None, None, None,
780 None, None, Post, Post,
781 None, None, None, None,
782 None, None, None, None,
783 None, None, None, None,
785 None, None, None, None,
786 None, Below, Below, Below,
787 Below, Below, Below, Below,
788 Below, Below, Below, Below,
790 Below, Below, Below, Below,
791 Below, Below, Below, Below,
792 Below, Below, Below, Below,
793 Below, Below, Below, Below,
795 Below, None, Below, Below,
796 None, Below, Below, Below,
797 Below, Below, None, None,
798 None, None, Post, Above,
800 Split, Post, Post, Post,
801 Post, None, Above, Split,
802 Split, None, Split, Split,
803 Above, Halant, None, None,
805 None, None, None, None,
806 None, Post, Post, None,
807 None, None, None, None,
808 None, None, Below, None,
810 None, None, Below, Below,
811 None, None, None, None,
812 None, None, None, None,
813 None, None, None, None,
815 None, None, None, None,
816 None, None, None, None,
817 None, None, None, None,
818 None, None, None, None,
821 None, None, Post, Post,
822 None, None, None, None,
823 None, None, None, None,
824 None, None, None, None,
826 None, None, None, None,
827 None, None, None, None,
828 None, None, None, None,
829 None, None, None, None,
831 None, None, None, None,
832 None, None, None, None,
833 None, None, None, None,
834 None, None, None, Post,
836 Post, None, Below, None,
837 None, Post, None, None,
838 None, None, None, None,
839 None, None, Post, Post,
841 Post, Post, Post, Post,
842 None, None, Pre, Pre,
843 Pre, None, Split, Split,
844 Split, Halant, None, None,
846 None, None, None, None,
847 None, None, None, Post,
848 None, None, None, None,
849 None, None, None, None,
851 None, None, None, None,
852 None, None, None, None,
853 None, None, None, None,
854 None, None, None, None,
856 None, None, None, None,
857 None, None, None, None,
858 None, None, None, None,
859 None, None, None, None,
862 None, None, Post, Post,
863 None, None, None, None,
864 None, None, None, None,
865 None, None, None, None,
867 None, None, None, None,
868 None, None, None, None,
869 None, None, None, None,
870 None, None, None, None,
872 None, None, None, None,
873 None, None, None, None,
874 None, None, None, None,
875 None, None, None, None,
877 None, None, None, None,
878 None, None, None, None,
879 None, None, None, None,
880 None, None, None, None,
882 None, None, None, None,
883 None, None, None, None,
884 None, None, None, None,
885 None, None, None, Post,
887 Post, Post, Above, Above,
888 Below, None, Below, None,
889 Post, Pre, Split, Pre,
890 Split, Split, Split, Post,
892 None, None, None, None,
893 None, None, None, None,
894 None, None, None, None,
895 None, None, None, None,
897 None, None, Post, Post,
898 None, None, None, None,
899 None, None, None, None,
900 None, None, None, None
903 static Form form(unsigned short uc) {
904 if (uc < 0x900 || uc > 0xdff) {
907 if (uc == 0x200c || uc == 0x200d)
911 return (Form)indicForms[uc-0x900];
914 static Position indic_position(unsigned short uc) {
915 if (uc < 0x900 || uc > 0xdff)
917 return (Position) indicPosition[uc-0x900];
921 enum IndicScriptProperties {
926 const hb_uint8 scriptProperties[10] = {
949 typedef struct _IndicOrdering {
954 static const IndicOrdering devanagari_order [] = {
955 { Consonant, Below },
957 { VowelMark, Below },
958 { StressMark, Below },
962 { VowelMark, Above },
963 { StressMark, Above },
968 static const IndicOrdering bengali_order [] = {
969 { Consonant, Below },
973 { VowelMark, Above },
980 static const IndicOrdering gurmukhi_order [] = {
981 { Consonant, Below },
986 { VowelMark, Above },
990 static const IndicOrdering tamil_order [] = {
997 static const IndicOrdering telugu_order [] = {
1001 { Consonant, Below },
1002 { Consonant, Post },
1003 { VowelMark, Post },
1007 static const IndicOrdering kannada_order [] = {
1010 { Consonant, Below },
1011 { Consonant, Post },
1012 { LengthMark, Post },
1013 { Consonant, Reph },
1014 { VowelMark, Post },
1018 static const IndicOrdering malayalam_order [] = {
1019 { Consonant, Below },
1021 { Consonant, Reph },
1022 { Consonant, Post },
1024 { VowelMark, Post },
1028 static const IndicOrdering sinhala_order [] = {
1032 { VowelMark, Post },
1036 static const IndicOrdering * const indic_order[] = {
1037 devanagari_order, // Devanagari
1038 bengali_order, // Bengali
1039 gurmukhi_order, // Gurmukhi
1040 devanagari_order, // Gujarati
1041 bengali_order, // Oriya
1042 tamil_order, // Tamil
1043 telugu_order, // Telugu
1044 kannada_order, // Kannada
1045 malayalam_order, // Malayalam
1046 sinhala_order // Sinhala
1051 // vowel matras that have to be split into two parts.
1052 static const unsigned short split_matras[] = {
1053 // matra, split1, split2, split3
1056 0x9cb, 0x9c7, 0x9be, 0x0,
1057 0x9cc, 0x9c7, 0x9d7, 0x0,
1059 0xb48, 0xb47, 0xb56, 0x0,
1060 0xb4b, 0xb47, 0xb3e, 0x0,
1061 0xb4c, 0xb47, 0xb57, 0x0,
1063 0xbca, 0xbc6, 0xbbe, 0x0,
1064 0xbcb, 0xbc7, 0xbbe, 0x0,
1065 0xbcc, 0xbc6, 0xbd7, 0x0,
1067 0xc48, 0xc46, 0xc56, 0x0,
1069 0xcc0, 0xcbf, 0xcd5, 0x0,
1070 0xcc7, 0xcc6, 0xcd5, 0x0,
1071 0xcc8, 0xcc6, 0xcd6, 0x0,
1072 0xcca, 0xcc6, 0xcc2, 0x0,
1073 0xccb, 0xcc6, 0xcc2, 0xcd5,
1075 0xd4a, 0xd46, 0xd3e, 0x0,
1076 0xd4b, 0xd47, 0xd3e, 0x0,
1077 0xd4c, 0xd46, 0xd57, 0x0,
1079 0xdda, 0xdd9, 0xdca, 0x0,
1080 0xddc, 0xdd9, 0xdcf, 0x0,
1081 0xddd, 0xdd9, 0xdcf, 0xdca,
1082 0xdde, 0xdd9, 0xddf, 0x0,
1086 static void splitMatra(unsigned short *reordered, int matra, int *len)
1088 unsigned short matra_uc = reordered[matra];
1089 //qDebug("matra=%d, reordered[matra]=%x", matra, reordered[matra]);
1091 const unsigned short *split = split_matras;
1092 while (split[0] < matra_uc)
1095 assert(*split == matra_uc);
1098 int added_chars = split[2] == 0x0 ? 1 : 2;
1100 memmove(reordered + matra + added_chars, reordered + matra, (*len-matra)*sizeof(unsigned short));
1101 reordered[matra] = split[0];
1102 reordered[matra+1] = split[1];
1103 if(added_chars == 2)
1104 reordered[matra+2] = split[2];
1105 *len += added_chars;
1109 static const HB_OpenTypeFeature indic_features[] = {
1110 { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
1111 { HB_MAKE_TAG('i', 'n', 'i', 't'), InitProperty },
1112 { HB_MAKE_TAG('n', 'u', 'k', 't'), NuktaProperty },
1113 { HB_MAKE_TAG('a', 'k', 'h', 'n'), AkhantProperty },
1114 { HB_MAKE_TAG('r', 'p', 'h', 'f'), RephProperty },
1115 { HB_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty },
1116 { HB_MAKE_TAG('h', 'a', 'l', 'f'), HalfFormProperty },
1117 { HB_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty },
1118 { HB_MAKE_TAG('v', 'a', 't', 'u'), VattuProperty },
1119 { HB_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty },
1120 { HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty },
1121 { HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty },
1122 { HB_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty },
1123 { HB_MAKE_TAG('h', 'a', 'l', 'n'), HalantProperty },
1128 // #define INDIC_DEBUG
1130 #define IDEBUG hb_debug
1133 static void hb_debug(const char *msg, ...)
1136 va_start(ap, msg); // use variable arg list
1137 vfprintf(stderr, msg, ap);
1139 fprintf(stderr, "\n");
1143 #define IDEBUG if(0) printf
1146 #if 0 //def INDIC_DEBUG
1147 static QString propertiesToString(int properties)
1150 properties = ~properties;
1151 if (properties & CcmpProperty)
1153 if (properties & InitProperty)
1155 if (properties & NuktaProperty)
1157 if (properties & AkhantProperty)
1159 if (properties & RephProperty)
1161 if (properties & PreFormProperty)
1163 if (properties & BelowFormProperty)
1164 res += "BelowForm ";
1165 if (properties & AboveFormProperty)
1166 res += "AboveForm ";
1167 if (properties & HalfFormProperty)
1169 if (properties & PostFormProperty)
1171 if (properties & VattuProperty)
1173 if (properties & PreSubstProperty)
1175 if (properties & BelowSubstProperty)
1176 res += "BelowSubst ";
1177 if (properties & AboveSubstProperty)
1178 res += "AboveSubst ";
1179 if (properties & PostSubstProperty)
1180 res += "PostSubst ";
1181 if (properties & HalantProperty)
1183 if (properties & CligProperty)
1189 static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool invalid)
1191 HB_Script script = item->item.script;
1192 assert(script >= HB_Script_Devanagari && script <= HB_Script_Sinhala);
1193 const unsigned short script_base = 0x0900 + 0x80*(script-HB_Script_Devanagari);
1194 const unsigned short ra = script_base + 0x30;
1195 const unsigned short halant = script_base + 0x4d;
1196 const unsigned short nukta = script_base + 0x3c;
1197 bool control = false;
1199 int len = (int)item->item.length;
1200 IDEBUG(">>>>> indic shape: from=%d, len=%d invalid=%d", item->item.pos, item->item.length, invalid);
1202 if ((int)item->num_glyphs < len+4) {
1203 item->num_glyphs = len+4;
1207 HB_STACKARRAY(HB_UChar16, reordered, len + 4);
1208 HB_STACKARRAY(hb_uint8, position, len + 4);
1210 unsigned char properties = scriptProperties[script-HB_Script_Devanagari];
1213 *reordered = 0x25cc;
1214 memcpy(reordered+1, item->string + item->item.pos, len*sizeof(HB_UChar16));
1217 memcpy(reordered, item->string + item->item.pos, len*sizeof(HB_UChar16));
1219 if (reordered[len-1] == 0x200c) // zero width non joiner
1227 IDEBUG("original:");
1228 for (i = 0; i < len; i++) {
1229 IDEBUG(" %d: %4x", i, reordered[i]);
1234 HB_UChar16 *uc = reordered;
1235 bool beginsWithRa = false;
1237 // Rule 1: find base consonant
1239 // The shaping engine finds the base consonant of the
1240 // syllable, using the following algorithm: starting from the
1241 // end of the syllable, move backwards until a consonant is
1242 // found that does not have a below-base or post-base form
1243 // (post-base forms have to follow below-base forms), or
1244 // arrive at the first consonant. The consonant stopped at
1245 // will be the base.
1247 // * If the syllable starts with Ra + H (in a script that has
1248 // 'Reph'), Ra is excluded from candidates for base
1251 // * In Kannada and Telugu, the base consonant cannot be
1252 // farther than 3 consonants from the end of the syllable.
1253 // #### replace the HasReph property by testing if the feature exists in the font!
1254 if (form(*uc) == Consonant || (script == HB_Script_Bengali && form(*uc) == IndependentVowel)) {
1255 if ((properties & HasReph) && (len > 2) &&
1256 (*uc == ra || *uc == 0x9f0) && *(uc+1) == halant)
1257 beginsWithRa = true;
1259 if (beginsWithRa && form(*(uc+2)) == Control)
1260 beginsWithRa = false;
1262 base = (beginsWithRa ? 2 : 0);
1263 IDEBUG(" length = %d, beginsWithRa = %d, base=%d", len, beginsWithRa, base);
1265 int lastConsonant = 0;
1268 // * the last consonant since we need it for rule 2
1269 // * the matras position for rule 3 and 4
1271 // figure out possible base glyphs
1272 memset(position, 0, len);
1273 if (script == HB_Script_Devanagari || script == HB_Script_Gujarati) {
1275 for (i = base; i < len; ++i) {
1276 position[i] = form(uc[i]);
1277 if (position[i] == Consonant) {
1279 vattu = (!vattu && uc[i] == ra);
1281 IDEBUG("excluding vattu glyph at %d from base candidates", i);
1282 position[i] = Vattu;
1284 } else if (position[i] == Matra) {
1289 for (i = base; i < len; ++i) {
1290 position[i] = form(uc[i]);
1291 if (position[i] == Consonant)
1293 else if (matra < 0 && position[i] == Matra)
1298 Position pos = Post;
1299 for (i = len-1; i > base; i--) {
1300 if (position[i] != Consonant && (position[i] != Control || script == HB_Script_Kannada))
1303 Position charPosition = indic_position(uc[i]);
1304 if (pos == Post && charPosition == Post) {
1306 } else if ((pos == Post || pos == Below) && charPosition == Below) {
1307 if (script == HB_Script_Devanagari || script == HB_Script_Gujarati)
1314 if (skipped == 2 && (script == HB_Script_Kannada || script == HB_Script_Telugu)) {
1321 IDEBUG(" base consonant at %d skipped=%d, lastConsonant=%d", base, skipped, lastConsonant);
1325 // If the base consonant is not the last one, Uniscribe
1326 // moves the halant from the base consonant to the last
1328 if (lastConsonant > base) {
1330 if (uc[base+1] == halant)
1331 halantPos = base + 1;
1332 else if (uc[base+1] == nukta && uc[base+2] == halant)
1333 halantPos = base + 2;
1334 if (halantPos > 0) {
1335 IDEBUG(" moving halant from %d to %d!", base+1, lastConsonant);
1336 for (i = halantPos; i < lastConsonant; i++)
1338 uc[lastConsonant] = halant;
1344 // If the syllable starts with Ra + H, Uniscribe moves
1345 // this combination so that it follows either:
1347 // * the post-base 'matra' (if any) or the base consonant
1348 // (in scripts that show similarity to Devanagari, i.e.,
1349 // Devanagari, Gujarati, Bengali)
1350 // * the base consonant (other scripts)
1351 // * the end of the syllable (Kannada)
1353 Position matra_position = None;
1355 matra_position = indic_position(uc[matra]);
1356 IDEBUG(" matra at %d with form %d, base=%d", matra, matra_position, base);
1358 if (beginsWithRa && base != 0) {
1360 if (toPos < len && uc[toPos] == nukta)
1362 if (toPos < len && uc[toPos] == halant)
1364 if (toPos < len && uc[toPos] == 0x200d)
1366 if (toPos < len-1 && uc[toPos] == ra && uc[toPos+1] == halant)
1368 if (script == HB_Script_Devanagari || script == HB_Script_Gujarati || script == HB_Script_Bengali) {
1369 if (matra_position == Post || matra_position == Split) {
1373 } else if (script == HB_Script_Kannada) {
1378 IDEBUG("moving leading ra+halant to position %d", toPos);
1379 for (i = 2; i < toPos; i++)
1382 uc[toPos-1] = halant;
1384 if (properties & HasReph)
1390 // Uniscribe splits two- or three-part matras into their
1391 // parts. This splitting is a character-to-character
1394 // Uniscribe describes some moving operations for these
1395 // matras here. For shaping however all pre matras need
1396 // to be at the beginning of the syllable, so we just move
1398 if (matra_position == Split) {
1399 splitMatra(uc, matra, &len);
1400 // Handle three-part matras (0xccb in Kannada)
1401 matra_position = indic_position(uc[matra]);
1404 if (matra_position == Pre) {
1405 unsigned short m = uc[matra];
1407 uc[matra+1] = uc[matra];
1415 // Uniscribe classifies consonants and 'matra' parts as
1416 // pre-base, above-base (Reph), below-base or post-base. This
1417 // classification exists on the character code level and is
1418 // language-dependent, not font-dependent.
1419 for (i = 0; i < base; ++i)
1421 position[base] = Base;
1422 for (i = base+1; i < len; ++i) {
1423 position[i] = indic_position(uc[i]);
1424 // #### replace by adjusting table
1425 if (uc[i] == nukta || uc[i] == halant)
1426 position[i] = Inherit;
1429 // recalculate reph, it might have changed.
1430 for (i = base+1; i < len; ++i)
1433 position[reph] = Reph;
1434 position[reph+1] = Inherit;
1437 // all reordering happens now to the chars after the base
1439 if (fixed < len && uc[fixed] == nukta)
1441 if (fixed < len && uc[fixed] == halant)
1443 if (fixed < len && uc[fixed] == 0x200d)
1447 for (i = fixed; i < len; ++i)
1448 IDEBUG("position[%d] = %d, form=%d uc=%x", i, position[i], form(uc[i]), uc[i]);
1450 // we continuosly position the matras and vowel marks and increase the fixed
1451 // until we reached the end.
1452 const IndicOrdering *finalOrder = indic_order[script-HB_Script_Devanagari];
1454 IDEBUG(" reordering pass:");
1455 IDEBUG(" base=%d fixed=%d", base, fixed);
1457 while (finalOrder[toMove].form && fixed < len-1) {
1458 IDEBUG(" fixed = %d, toMove=%d, moving form %d with pos %d", fixed, toMove, finalOrder[toMove].form, finalOrder[toMove].position);
1459 for (i = fixed; i < len; i++) {
1460 // IDEBUG() << " i=" << i << "uc=" << hex << uc[i] << "form=" << form(uc[i])
1461 // << "position=" << position[i];
1462 if (form(uc[i]) == finalOrder[toMove].form &&
1463 position[i] == finalOrder[toMove].position) {
1465 // need to move this glyph
1467 if (i < len-1 && position[i+1] == Inherit) {
1468 IDEBUG(" moving two chars from %d to %d", i, to);
1469 unsigned short ch = uc[i];
1470 unsigned short ch2 = uc[i+1];
1471 unsigned char pos = position[i];
1472 for (j = i+1; j > to+1; j--) {
1474 position[j] = position[j-2];
1479 position[to+1] = pos;
1482 IDEBUG(" moving one char from %d to %d", i, to);
1483 unsigned short ch = uc[i];
1484 unsigned char pos = position[i];
1485 for (j = i; j > to; j--) {
1487 position[j] = position[j-1];
1501 // recalculate reph, it might have changed.
1502 for (i = base+1; i < len; ++i)
1503 if (reordered[i] == ra)
1508 const int availableGlyphs = item->num_glyphs;
1510 if (!item->font->klass->convertStringToGlyphIndices(item->font,
1512 item->glyphs, &item->num_glyphs,
1513 item->item.bidiLevel % 2))
1517 IDEBUG(" base=%d, reph=%d", base, reph);
1518 IDEBUG("reordered:");
1519 for (i = 0; i < len; i++) {
1520 item->attributes[i].mark = false;
1521 item->attributes[i].clusterStart = false;
1522 item->attributes[i].justification = 0;
1523 item->attributes[i].zeroWidth = false;
1524 IDEBUG(" %d: %4x", i, reordered[i]);
1527 // now we have the syllable in the right order, and can start running it through open type.
1529 for (i = 0; i < len; ++i)
1530 control |= (form(reordered[i]) == Control);
1535 // we need to keep track of where the base glyph is for some
1536 // scripts and use the cluster feature for this. This
1537 // also means we have to correct the logCluster output from
1538 // the open type engine manually afterwards. for indic this
1539 // is rather simple, as all chars just point to the first
1540 // glyph in the syllable.
1541 HB_STACKARRAY(unsigned short, clusters, len);
1542 HB_STACKARRAY(unsigned int, properties, len);
1544 for (i = 0; i < len; ++i)
1547 // features we should always apply
1548 for (i = 0; i < len; ++i)
1549 properties[i] = ~(CcmpProperty
1553 | BelowSubstProperty
1554 | AboveSubstProperty
1556 | PositioningProperties);
1558 // Ccmp always applies
1560 if (item->item.pos == 0
1561 || !(isLetter(item->string[item->item.pos-1]) || isMark(item->string[item->item.pos-1])))
1562 properties[0] &= ~InitProperty;
1564 // Nukta always applies
1566 for (i = 0; i <= base; ++i)
1567 properties[i] &= ~AkhantProperty;
1570 properties[reph] &= ~RephProperty;
1571 properties[reph+1] &= ~RephProperty;
1574 for (i = base+1; i < len; ++i)
1575 properties[i] &= ~BelowFormProperty;
1577 if (script == HB_Script_Devanagari || script == HB_Script_Gujarati) {
1578 // vattu glyphs need this aswell
1580 for (i = base-2; i > 1; --i) {
1581 if (form(reordered[i]) == Consonant) {
1582 vattu = (!vattu && reordered[i] == ra);
1584 IDEBUG("forming vattu ligature at %d", i);
1585 properties[i] &= ~BelowFormProperty;
1586 properties[i+1] &= ~BelowFormProperty;
1592 for (i = 0; i < base; ++i)
1593 properties[i] &= ~HalfFormProperty;
1595 for (i = 2; i < len; ++i) {
1596 if (reordered[i] == 0x200d /* ZWJ */) {
1597 properties[i-1] &= ~HalfFormProperty;
1598 properties[i-2] &= ~HalfFormProperty;
1599 } else if (reordered[i] == 0x200c /* ZWNJ */) {
1600 properties[i-1] &= ~HalfFormProperty;
1601 properties[i-2] &= ~HalfFormProperty;
1606 for (i = base+1; i < len; ++i)
1607 properties[i] &= ~PostFormProperty;
1608 // vattu always applies
1609 // pres always applies
1610 // blws always applies
1611 // abvs always applies
1614 // ### this looks slightly different from before, but I believe it's correct
1615 if (reordered[len-1] != halant || base != len-2)
1616 properties[base] &= ~PostSubstProperty;
1617 for (i = base+1; i < len; ++i)
1618 properties[i] &= ~PostSubstProperty;
1620 // halant always applies
1624 // IDEBUG("OT properties:");
1625 // for (int i = 0; i < len; ++i)
1626 // qDebug(" i: %s", ::propertiesToString(properties[i]).toLatin1().data());
1631 item->log_clusters = clusters;
1632 HB_OpenTypeShape(item, properties);
1634 int newLen = item->face->buffer->in_length;
1635 HB_GlyphItem otl_glyphs = item->face->buffer->in_string;
1637 // move the left matra back to its correct position in malayalam and tamil
1638 if ((script == HB_Script_Malayalam || script == HB_Script_Tamil) && (form(reordered[0]) == Matra)) {
1639 // qDebug("reordering matra, len=%d", newLen);
1640 // need to find the base in the shaped string and move the matra there
1642 while (basePos < newLen && (int)otl_glyphs[basePos].cluster <= base)
1645 if (basePos < newLen && basePos > 1) {
1646 // qDebug("moving prebase matra to position %d in syllable newlen=%d", basePos, newLen);
1647 HB_GlyphItemRec m = otl_glyphs[0];
1649 for (i = 0; i < basePos; ++i)
1650 otl_glyphs[i] = otl_glyphs[i+1];
1651 otl_glyphs[basePos] = m;
1655 HB_Bool positioned = HB_OpenTypePosition(item, availableGlyphs, false);
1657 HB_FREE_STACKARRAY(clusters);
1658 HB_FREE_STACKARRAY(properties);
1664 IDEBUG("found a control char in the syllable");
1665 hb_uint32 i = 0, j = 0;
1666 while (i < item->num_glyphs) {
1667 if (form(reordered[otl_glyphs[i].cluster]) == Control) {
1669 if (i >= item->num_glyphs)
1672 item->glyphs[j] = item->glyphs[i];
1673 item->attributes[j] = item->attributes[i];
1677 item->num_glyphs = j;
1681 HB_HeuristicPosition(item);
1683 #endif // NO_OPENTYPE
1684 item->attributes[0].clusterStart = true;
1686 HB_FREE_STACKARRAY(reordered);
1687 HB_FREE_STACKARRAY(position);
1693 HB_FREE_STACKARRAY(reordered);
1694 HB_FREE_STACKARRAY(position);
1698 /* syllables are of the form:
1700 (Consonant Nukta? Halant)* Consonant Matra? VowelMark? StressMark?
1701 (Consonant Nukta? Halant)* Consonant Halant
1702 IndependentVowel VowelMark? StressMark?
1704 We return syllable boundaries on invalid combinations aswell
1706 /* SAMSUNG - Kaja Changes -Start */
1707 int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int start, int end, HB_Bool *invalid)
1708 //static int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int start, int end, HB_Bool *invalid)
1709 /* SAMSUNG - Kaja Changes -End */
1712 IDEBUG("indic_nextSyllableBoundary: start=%d, end=%d", start, end);
1713 const HB_UChar16 *uc = s+start ;
1716 Form state = form(uc[pos]);
1717 IDEBUG("state[%d]=%d (uc=%4x)", pos, state, uc[pos]);
1720 if (state != Consonant && state != IndependentVowel) {
1726 while (pos < end - start) {
1727 Form newState = form(uc[pos]);
1728 IDEBUG("state[%d]=%d (uc=%4x)", pos, newState, uc[pos]);
1732 if (state == Halant && uc[pos] == 0x200d /* ZWJ */)
1734 // the control character should be the last char in the item
1738 if (state == Halant && (script != HB_Script_Sinhala || uc[pos-1] == 0x200d /* ZWJ */))
1742 if (state == Nukta || state == Consonant)
1744 // Bengali has a special exception allowing the combination Vowel_A/E + Halant + Ya
1745 if (script == HB_Script_Bengali && pos == 1 &&
1746 (uc[0] == 0x0985 || uc[0] == 0x098f))
1748 // Sinhala uses the Halant as a component of certain matras. Allow these, but keep the state on Matra.
1749 if (script == HB_Script_Sinhala && state == Matra) {
1753 if (script == HB_Script_Malayalam && state == Matra && uc[pos-1] == 0x0d41) {
1759 if (state == Consonant)
1763 if (state == VowelMark)
1767 if (state == Matra || state == LengthMark || state == IndependentVowel)
1771 if (state == Consonant || state == Nukta)
1773 if (state == Matra) {
1774 // ### needs proper testing for correct two/three part matras
1777 // ### not sure if this is correct. If it is, does it apply only to Bengali or should
1778 // it work for all Indic languages?
1779 // the combination Independent_A + Vowel Sign AA is allowed.
1780 if (script == HB_Script_Bengali && uc[pos] == 0x9be && uc[pos-1] == 0x985)
1782 if (script == HB_Script_Tamil && state == Matra) {
1783 if (uc[pos-1] == 0x0bc6 &&
1784 (uc[pos] == 0xbbe || uc[pos] == 0xbd7))
1786 if (uc[pos-1] == 0x0bc7 && uc[pos] == 0xbbe)
1792 if (state == Matra) {
1793 // ### needs proper testing for correct two/three part matras
1796 case IndependentVowel:
1808 HB_Bool HB_IndicShape(HB_ShaperItem *item)
1810 assert(item->item.script >= HB_Script_Devanagari && item->item.script <= HB_Script_Sinhala);
1812 HB_Bool openType = false;
1814 openType = HB_SelectScript(item, indic_features);
1816 unsigned short *logClusters = item->log_clusters;
1818 HB_ShaperItem syllable = *item;
1819 int first_glyph = 0;
1821 int sstart = item->item.pos;
1822 int end = sstart + item->item.length;
1823 IDEBUG("indic_shape: from %d length %d", item->item.pos, item->item.length);
1824 while (sstart < end) {
1826 int send = indic_nextSyllableBoundary(item->item.script, item->string, sstart, end, &invalid);
1827 IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,
1828 invalid ? "true" : "false");
1829 syllable.item.pos = sstart;
1830 syllable.item.length = send-sstart;
1831 syllable.glyphs = item->glyphs + first_glyph;
1832 syllable.attributes = item->attributes + first_glyph;
1833 syllable.offsets = item->offsets + first_glyph;
1834 syllable.advances = item->advances + first_glyph;
1835 syllable.num_glyphs = item->num_glyphs - first_glyph;
1836 if (!indic_shape_syllable(openType, &syllable, invalid)) {
1837 IDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs);
1838 item->num_glyphs += syllable.num_glyphs;
1841 // fix logcluster array
1842 IDEBUG("syllable:");
1844 for (g = first_glyph; g < first_glyph + syllable.num_glyphs; ++g)
1845 IDEBUG(" %d -> glyph %x", g, item->glyphs[g]);
1846 IDEBUG(" logclusters:");
1848 for (i = sstart; i < send; ++i) {
1849 IDEBUG(" %d -> glyph %d", i, first_glyph);
1850 logClusters[i-item->item.pos] = first_glyph;
1853 first_glyph += syllable.num_glyphs;
1855 item->num_glyphs = first_glyph;
1859 void HB_IndicAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes)
1861 int end = from + len;
1862 const HB_UChar16 *uc = text + from;
1867 hb_uint32 boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from;
1868 attributes[i].charStop = true;
1870 if (boundary > len-1) boundary = len;
1872 while (i < boundary) {
1873 attributes[i].charStop = false;
1877 assert(i == boundary);