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 enum MymrCharClassValues
34 Mymr_CC_CONSONANT
= 1, /* Consonant of type 1, that has subscript form */
35 Mymr_CC_CONSONANT2
= 2, /* Consonant of type 2, that has no subscript form */
36 Mymr_CC_NGA
= 3, /* Consonant NGA */
37 Mymr_CC_YA
= 4, /* Consonant YA */
38 Mymr_CC_RA
= 5, /* Consonant RA */
39 Mymr_CC_WA
= 6, /* Consonant WA */
40 Mymr_CC_HA
= 7, /* Consonant HA */
41 Mymr_CC_IND_VOWEL
= 8, /* Independent vowel */
42 Mymr_CC_ZERO_WIDTH_NJ_MARK
= 9, /* Zero Width non joiner character (0x200C) */
43 Mymr_CC_VIRAMA
= 10, /* Subscript consonant combining character */
44 Mymr_CC_PRE_VOWEL
= 11, /* Dependent vowel, prebase (Vowel e) */
45 Mymr_CC_BELOW_VOWEL
= 12, /* Dependent vowel, prebase (Vowel u, uu) */
46 Mymr_CC_ABOVE_VOWEL
= 13, /* Dependent vowel, prebase (Vowel i, ii, ai) */
47 Mymr_CC_POST_VOWEL
= 14, /* Dependent vowel, prebase (Vowel aa) */
48 Mymr_CC_SIGN_ABOVE
= 15,
49 Mymr_CC_SIGN_BELOW
= 16,
50 Mymr_CC_SIGN_AFTER
= 17,
51 Mymr_CC_ZERO_WIDTH_J_MARK
= 18, /* Zero width joiner character */
52 Mymr_CC_COUNT
= 19 /* This is the number of character classes */
55 enum MymrCharClassFlags
57 Mymr_CF_CLASS_MASK
= 0x0000FFFF,
59 Mymr_CF_CONSONANT
= 0x01000000, /* flag to speed up comparing */
60 Mymr_CF_MEDIAL
= 0x02000000, /* flag to speed up comparing */
61 Mymr_CF_IND_VOWEL
= 0x04000000, /* flag to speed up comparing */
62 Mymr_CF_DEP_VOWEL
= 0x08000000, /* flag to speed up comparing */
63 Mymr_CF_DOTTED_CIRCLE
= 0x10000000, /* add a dotted circle if a character with this flag is the first in a syllable */
64 Mymr_CF_VIRAMA
= 0x20000000, /* flag to speed up comparing */
67 Mymr_CF_POS_BEFORE
= 0x00080000,
68 Mymr_CF_POS_BELOW
= 0x00040000,
69 Mymr_CF_POS_ABOVE
= 0x00020000,
70 Mymr_CF_POS_AFTER
= 0x00010000,
71 Mymr_CF_POS_MASK
= 0x000f0000,
73 Mymr_CF_AFTER_KINZI
= 0x00100000
76 /* Characters that get refrered to by name */
79 Mymr_C_SIGN_ZWNJ
= 0x200C,
80 Mymr_C_SIGN_ZWJ
= 0x200D,
81 Mymr_C_DOTTED_CIRCLE
= 0x25CC,
85 Mymr_C_VOWEL_E
= 0x1031,
86 Mymr_C_VIRAMA
= 0x1039
91 Mymr_xx
= Mymr_CC_RESERVED
,
92 Mymr_c1
= Mymr_CC_CONSONANT
| Mymr_CF_CONSONANT
| Mymr_CF_POS_BELOW
,
93 Mymr_c2
= Mymr_CC_CONSONANT2
| Mymr_CF_CONSONANT
,
94 Mymr_ng
= Mymr_CC_NGA
| Mymr_CF_CONSONANT
| Mymr_CF_POS_ABOVE
,
95 Mymr_ya
= Mymr_CC_YA
| Mymr_CF_CONSONANT
| Mymr_CF_MEDIAL
| Mymr_CF_POS_AFTER
| Mymr_CF_AFTER_KINZI
,
96 Mymr_ra
= Mymr_CC_RA
| Mymr_CF_CONSONANT
| Mymr_CF_MEDIAL
| Mymr_CF_POS_BEFORE
,
97 Mymr_wa
= Mymr_CC_WA
| Mymr_CF_CONSONANT
| Mymr_CF_MEDIAL
| Mymr_CF_POS_BELOW
,
98 Mymr_ha
= Mymr_CC_HA
| Mymr_CF_CONSONANT
| Mymr_CF_MEDIAL
| Mymr_CF_POS_BELOW
,
99 Mymr_id
= Mymr_CC_IND_VOWEL
| Mymr_CF_IND_VOWEL
,
100 Mymr_vi
= Mymr_CC_VIRAMA
| Mymr_CF_VIRAMA
| Mymr_CF_POS_ABOVE
| Mymr_CF_DOTTED_CIRCLE
,
101 Mymr_dl
= Mymr_CC_PRE_VOWEL
| Mymr_CF_DEP_VOWEL
| Mymr_CF_POS_BEFORE
| Mymr_CF_DOTTED_CIRCLE
| Mymr_CF_AFTER_KINZI
,
102 Mymr_db
= Mymr_CC_BELOW_VOWEL
| Mymr_CF_DEP_VOWEL
| Mymr_CF_POS_BELOW
| Mymr_CF_DOTTED_CIRCLE
| Mymr_CF_AFTER_KINZI
,
103 Mymr_da
= Mymr_CC_ABOVE_VOWEL
| Mymr_CF_DEP_VOWEL
| Mymr_CF_POS_ABOVE
| Mymr_CF_DOTTED_CIRCLE
| Mymr_CF_AFTER_KINZI
,
104 Mymr_dr
= Mymr_CC_POST_VOWEL
| Mymr_CF_DEP_VOWEL
| Mymr_CF_POS_AFTER
| Mymr_CF_DOTTED_CIRCLE
| Mymr_CF_AFTER_KINZI
,
105 Mymr_sa
= Mymr_CC_SIGN_ABOVE
| Mymr_CF_DOTTED_CIRCLE
| Mymr_CF_POS_ABOVE
| Mymr_CF_AFTER_KINZI
,
106 Mymr_sb
= Mymr_CC_SIGN_BELOW
| Mymr_CF_DOTTED_CIRCLE
| Mymr_CF_POS_BELOW
| Mymr_CF_AFTER_KINZI
,
107 Mymr_sp
= Mymr_CC_SIGN_AFTER
| Mymr_CF_DOTTED_CIRCLE
| Mymr_CF_AFTER_KINZI
111 typedef int MymrCharClass
;
114 static const MymrCharClass mymrCharClasses
[] =
116 Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_ng
, Mymr_c1
, Mymr_c1
, Mymr_c1
,
117 Mymr_c1
, Mymr_c1
, Mymr_c2
, Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_c1
, /* 1000 - 100F */
118 Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_c1
, Mymr_c1
,
119 Mymr_c1
, Mymr_c1
, Mymr_ya
, Mymr_ra
, Mymr_c1
, Mymr_wa
, Mymr_c1
, Mymr_ha
, /* 1010 - 101F */
120 Mymr_c2
, Mymr_c2
, Mymr_xx
, Mymr_id
, Mymr_id
, Mymr_id
, Mymr_id
, Mymr_id
,
121 Mymr_xx
, Mymr_id
, Mymr_id
, Mymr_xx
, Mymr_dr
, Mymr_da
, Mymr_da
, Mymr_db
, /* 1020 - 102F */
122 Mymr_db
, Mymr_dl
, Mymr_da
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_sa
, Mymr_sb
,
123 Mymr_sp
, Mymr_vi
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, /* 1030 - 103F */
124 Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
,
125 Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, /* 1040 - 104F */
126 Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
,
127 Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, Mymr_xx
, /* 1050 - 105F */
131 getMyanmarCharClass (HB_UChar16 ch
)
133 if (ch
== Mymr_C_SIGN_ZWJ
)
134 return Mymr_CC_ZERO_WIDTH_J_MARK
;
136 if (ch
== Mymr_C_SIGN_ZWNJ
)
137 return Mymr_CC_ZERO_WIDTH_NJ_MARK
;
139 if (ch
< 0x1000 || ch
> 0x105f)
140 return Mymr_CC_RESERVED
;
142 return mymrCharClasses
[ch
- 0x1000];
145 static const signed char mymrStateTable
[][Mymr_CC_COUNT
] =
147 /* xx c1, c2 ng ya ra wa ha id zwnj vi dl db da dr sa sb sp zwj */
148 { 1, 4, 4, 2, 4, 4, 4, 4, 24, 1, 27, 17, 18, 19, 20, 21, 1, 1, 4}, /* 0 - ground state */
149 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 1 - exit state (or sp to the right of the syllable) */
150 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 17, 18, 19, 20, 21, -1, -1, 4}, /* 2 - NGA */
151 {-1, 4, 4, 4, 4, 4, 4, 4, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 3 - Virama after NGA */
152 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 17, 18, 19, 20, 21, 1, 1, -1}, /* 4 - Base consonant */
153 {-2, 6, -2, -2, 7, 8, 9, 10, -2, 23, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 5 - First virama */
154 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 17, 18, 19, 20, 21, -1, -1, -1}, /* 6 - c1 after virama */
155 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 7 - ya after virama */
156 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 8 - ra after virama */
157 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, /* 9 - wa after virama */
158 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 10 - ha after virama */
159 {-1, -1, -1, -1, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 11 - Virama after NGA+zwj */
160 {-2, -2, -2, -2, -2, -2, 13, 14, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 12 - Second virama */
161 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 17, 18, 19, 20, 21, -1, -1, -1}, /* 13 - wa after virama */
162 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 14 - ha after virama */
163 {-2, -2, -2, -2, -2, -2, -2, 16, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 15 - Third virama */
164 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, /* 16 - ha after virama */
165 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, 1, 1, -1}, /* 17 - dl, Dependent vowel e */
166 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, 21, 1, 1, -1}, /* 18 - db, Dependent vowel u,uu */
167 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1}, /* 19 - da, Dependent vowel i,ii,ai */
168 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, 1, 1, -1}, /* 20 - dr, Dependent vowel aa */
169 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, /* 21 - sa, Sign anusvara */
170 {-1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 22 - atha */
171 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, /* 23 - zwnj for atha */
172 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, /* 24 - Independent vowel */
173 {-2, -2, -2, -2, 26, 26, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, /* 25 - Virama after subscript consonant */
174 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, 1, -1}, /* 26 - ra/ya after subscript consonant + virama */
175 {-1, 6, -1, -1, 7, 8, 9, 10, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 - Virama after ground state */
176 /* exit state -2 is for invalid order of medials and combination of invalids
177 with virama where virama should treat as start of next syllable
183 /*#define MYANMAR_DEBUG */
185 #define MMDEBUG qDebug
187 #define MMDEBUG if(0) printf
191 // Given an input string of characters and a location in which to start looking
192 // calculate, using the state table, which one is the last character of the syllable
193 // that starts in the starting position.
195 static int myanmar_nextSyllableBoundary(const HB_UChar16
*s
, int start
, int end
, HB_Bool
*invalid
)
197 const HB_UChar16
*uc
= s
+ start
;
203 MymrCharClass charClass
= getMyanmarCharClass(*uc
);
204 state
= mymrStateTable
[state
][charClass
& Mymr_CF_CLASS_MASK
];
206 *invalid
= (HB_Bool
)(charClass
& Mymr_CF_DOTTED_CIRCLE
);
208 MMDEBUG("state[%d]=%d class=%8x (uc=%4x)", pos
- start
, state
, charClass
, *uc
);
222 /* ###### might have to change order of above and below forms and substitutions,
223 but according to Unicode below comes before above */
224 static const HB_OpenTypeFeature myanmar_features
[] = {
225 { HB_MAKE_TAG('p', 'r', 'e', 'f'), PreFormProperty
},
226 { HB_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty
},
227 { HB_MAKE_TAG('a', 'b', 'v', 'f'), AboveFormProperty
},
228 { HB_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty
},
229 { HB_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty
},
230 { HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty
},
231 { HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty
},
232 { HB_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty
},
233 { HB_MAKE_TAG('r', 'l', 'i', 'g'), CligProperty
}, /* Myanmar1 uses this instead of the other features */
240 // Visual order before shaping should be:
243 // [Virama + Medial Ra]
245 // [Virama + Consonant]
246 // [Nga + Virama] (Kinzi) ### should probably come before post forms (medial ya)
250 // This means that we can keep the logical order apart from having to
251 // move the pre vowel, medial ra and kinzi
254 static HB_Bool
myanmar_shape_syllable(HB_Bool openType
, HB_ShaperItem
*item
, HB_Bool invalid
)
257 // MMDEBUG("\nsyllable from %d len %d, str='%s'", item->item.pos, item->item.length,
258 // item->string->mid(item->from, item->length).toUtf8().data());
262 const int availableGlyphs
= item
->num_glyphs
;
264 const HB_UChar16
*uc
= item
->string
+ item
->item
.pos
;
271 unsigned short reordered
[32];
272 unsigned char properties
[32];
279 HB_Bool lastWasVirama
= FALSE
;
282 memset(properties
, 0, 32*sizeof(unsigned char));
284 /* according to the table the max length of a syllable should be around 14 chars */
285 assert(item
->item
.length
< 32);
289 for (i
= 0; i
< (int)item
->item
.length
; i
++) {
290 printf(" %d: %4x", i
, uc
[i
]);
293 for (i
= 0; i
< (int)item
->item
.length
; ++i
) {
294 HB_UChar16 chr
= uc
[i
];
296 if (chr
== Mymr_C_VOWEL_E
) {
302 && i
+ 2 < (int)item
->item
.length
303 && uc
[i
+1] == Mymr_C_VIRAMA
) {
304 int mc
= getMyanmarCharClass(uc
[i
+2]);
305 /*MMDEBUG("maybe kinzi: mc=%x", mc);*/
306 if ((mc
& Mymr_CF_CONSONANT
) == Mymr_CF_CONSONANT
) {
312 && chr
== Mymr_C_VIRAMA
313 && i
+ 1 < (int)item
->item
.length
314 && uc
[i
+1] == Mymr_C_RA
) {
322 MMDEBUG("\n base=%d, vowel_e=%d, kinzi=%d, medial_ra=%d", base
, vowel_e
, kinzi
, medial_ra
);
323 /* write vowel_e if found */
325 reordered
[0] = Mymr_C_VOWEL_E
;
328 /* write medial_ra */
329 if (medial_ra
>= 0) {
330 reordered
[len
] = Mymr_C_VIRAMA
;
331 reordered
[len
+1] = Mymr_C_RA
;
332 properties
[len
] = PreForm
;
333 properties
[len
+1] = PreForm
;
337 /* shall we add a dotted circle?
338 If in the position in which the base should be (first char in the string) there is
339 a character that has the Dotted circle flag (a character that cannot be a base)
340 then write a dotted circle */
342 reordered
[len
] = C_DOTTED_CIRCLE
;
346 /* copy the rest of the syllable to the output, inserting the kinzi
347 at the correct place */
348 for (i
= 0; i
< (int)item
->item
.length
; ++i
) {
349 hb_uint16 chr
= uc
[i
];
353 if (i
== medial_ra
|| i
== kinzi
) {
358 cc
= getMyanmarCharClass(uc
[i
]);
359 if (kinzi
>= 0 && i
> base
&& (cc
& Mymr_CF_AFTER_KINZI
)) {
360 reordered
[len
] = Mymr_C_NGA
;
361 reordered
[len
+1] = Mymr_C_VIRAMA
;
363 properties
[len
-1] = AboveForm
;
364 properties
[len
] = AboveForm
;
371 switch(cc
& Mymr_CF_POS_MASK
) {
372 case Mymr_CF_POS_BEFORE
:
375 case Mymr_CF_POS_BELOW
:
378 case Mymr_CF_POS_ABOVE
:
381 case Mymr_CF_POS_AFTER
:
387 properties
[len
-1] = prop
;
388 properties
[len
] = prop
;
389 if(basePos
>= 0 && basePos
== len
-2)
390 properties
[len
-2] = prop
;
392 lastWasVirama
= (chr
== Mymr_C_VIRAMA
);
396 if ((chr
!= Mymr_C_SIGN_ZWNJ
&& chr
!= Mymr_C_SIGN_ZWJ
) || !len
) {
397 reordered
[len
] = chr
;
402 reordered
[len
] = Mymr_C_NGA
;
403 reordered
[len
+1] = Mymr_C_VIRAMA
;
404 properties
[len
] = AboveForm
;
405 properties
[len
+1] = AboveForm
;
409 if (!item
->font
->klass
->convertStringToGlyphIndices(item
->font
,
411 item
->glyphs
, &item
->num_glyphs
,
412 item
->item
.bidiLevel
% 2))
415 MMDEBUG("after shaping: len=%d", len
);
416 for (i
= 0; i
< len
; i
++) {
417 item
->attributes
[i
].mark
= FALSE
;
418 item
->attributes
[i
].clusterStart
= FALSE
;
419 item
->attributes
[i
].justification
= 0;
420 item
->attributes
[i
].zeroWidth
= FALSE
;
421 MMDEBUG(" %d: %4x property=%x", i
, reordered
[i
], properties
[i
]);
424 /* now we have the syllable in the right order, and can start running it through open type. */
430 for (i
= 0; i
< len
; ++i
) {
431 where
[i
] = ~(PreSubstProperty
436 | PositioningProperties
);
437 if (properties
[i
] & PreForm
)
438 where
[i
] &= ~PreFormProperty
;
439 if (properties
[i
] & BelowForm
)
440 where
[i
] &= ~BelowFormProperty
;
441 if (properties
[i
] & AboveForm
)
442 where
[i
] &= ~AboveFormProperty
;
443 if (properties
[i
] & PostForm
)
444 where
[i
] &= ~PostFormProperty
;
447 HB_OpenTypeShape(item
, where
);
448 if (!HB_OpenTypePosition(item
, availableGlyphs
, /*doLogClusters*/FALSE
))
453 MMDEBUG("Not using openType");
454 HB_HeuristicPosition(item
);
457 item
->attributes
[0].clusterStart
= TRUE
;
461 HB_Bool
HB_MyanmarShape(HB_ShaperItem
*item
)
463 HB_Bool openType
= FALSE
;
464 unsigned short *logClusters
= item
->log_clusters
;
466 HB_ShaperItem syllable
= *item
;
469 int sstart
= item
->item
.pos
;
470 int end
= sstart
+ item
->item
.length
;
473 assert(item
->item
.script
== HB_Script_Myanmar
);
475 openType
= HB_SelectScript(item
, myanmar_features
);
478 MMDEBUG("myanmar_shape: from %d length %d", item
->item
.pos
, item
->item
.length
);
479 while (sstart
< end
) {
481 int send
= myanmar_nextSyllableBoundary(item
->string
, sstart
, end
, &invalid
);
482 MMDEBUG("syllable from %d, length %d, invalid=%s", sstart
, send
-sstart
,
483 invalid
? "TRUE" : "FALSE");
484 syllable
.item
.pos
= sstart
;
485 syllable
.item
.length
= send
-sstart
;
486 syllable
.glyphs
= item
->glyphs
+ first_glyph
;
487 syllable
.attributes
= item
->attributes
+ first_glyph
;
488 syllable
.advances
= item
->advances
+ first_glyph
;
489 syllable
.offsets
= item
->offsets
+ first_glyph
;
490 syllable
.num_glyphs
= item
->num_glyphs
- first_glyph
;
491 if (!myanmar_shape_syllable(openType
, &syllable
, invalid
)) {
492 MMDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable
.num_glyphs
);
493 item
->num_glyphs
+= syllable
.num_glyphs
;
497 /* fix logcluster array */
498 MMDEBUG("syllable:");
499 for (i
= first_glyph
; i
< first_glyph
+ (int)syllable
.num_glyphs
; ++i
)
500 MMDEBUG(" %d -> glyph %x", i
, item
->glyphs
[i
]);
501 MMDEBUG(" logclusters:");
502 for (i
= sstart
; i
< send
; ++i
) {
503 MMDEBUG(" %d -> glyph %d", i
, first_glyph
);
504 logClusters
[i
-item
->item
.pos
] = first_glyph
;
507 first_glyph
+= syllable
.num_glyphs
;
509 item
->num_glyphs
= first_glyph
;
513 void HB_MyanmarAttributes(HB_Script script
, const HB_UChar16
*text
, hb_uint32 from
, hb_uint32 len
, HB_CharAttributes
*attributes
)
515 int end
= from
+ len
;
516 const HB_UChar16
*uc
= text
+ from
;
522 hb_uint32 boundary
= myanmar_nextSyllableBoundary(text
, from
+i
, end
, &invalid
) - from
;
524 attributes
[i
].charStop
= TRUE
;
526 attributes
[i
-1].lineBreakType
= HB_Break
;
528 if (boundary
> len
-1)
531 while (i
< boundary
) {
532 attributes
[i
].charStop
= FALSE
;
536 assert(i
== boundary
);