@@ -157,22 +157,34 @@ bool MCTextLayout(const unichar_t *p_chars, uint32_t p_char_count, MCFontStruct
157157 CTRunRef t_run;
158158 t_run = (CTRunRef)t_run_id;
159159
160- uint32_t t_glyph_count;
160+ CFIndex t_glyph_count;
161161 t_glyph_count = CTRunGetGlyphCount (t_run);
162162
163- CFRange t_char_range;
164- t_char_range = CTRunGetStringRange (t_run);
165-
166163 CGGlyph *t_glyphs;
167164 CGPoint *t_positions;
168165 CFIndex *t_indices;
169166 t_glyphs = new CGGlyph[t_glyph_count];
170167 t_positions = new CGPoint[t_glyph_count];
171168 t_indices = new CFIndex[t_glyph_count];
172- CTRunGetGlyphs (t_run, CFRangeMake (0 , 0 ), t_glyphs);
173- CTRunGetPositions (t_run, CFRangeMake (0 , 0 ), t_positions);
174- CTRunGetStringIndices (t_run, CFRangeMake (0 , 0 ), t_indices);
169+ CTRunGetGlyphs (t_run, CFRangeMake (0 , t_glyph_count ), t_glyphs);
170+ CTRunGetPositions (t_run, CFRangeMake (0 , t_glyph_count ), t_positions);
171+ CTRunGetStringIndices (t_run, CFRangeMake (0 , t_glyph_count ), t_indices);
175172
173+ // Work out the string range of the run - the value returned by
174+ // CTRunGetCharRange() can't be trusted as it considers a line
175+ // 'as a whole' rather than individual runs. (This can happen with
176+ // abugida scripts where you get several runs for one cluster due
177+ // to font fallback).
178+ CFIndex t_min_char_range = p_char_count;
179+ CFIndex t_max_char_range = 0 ;
180+ for (CFIndex i = 0 ; i < t_glyph_count; i++)
181+ {
182+ t_min_char_range = MCMin (t_min_char_range, t_indices[i]);
183+ t_max_char_range = MCMax (t_max_char_range, t_indices[i] + 1 );
184+ }
185+ CFRange t_char_range = CFRangeMake (t_min_char_range,
186+ t_max_char_range - t_min_char_range);
187+
176188 MCTextLayoutGlyph *t_layout_glyphs;
177189 uint16_t *t_clusters;
178190 t_layout_glyphs = new MCTextLayoutGlyph[t_glyph_count];
@@ -185,25 +197,26 @@ bool MCTextLayout(const unichar_t *p_chars, uint32_t p_char_count, MCFontStruct
185197 }
186198
187199 // Compute the clusters.
188- for (uint32_t i = 0 ; i < t_char_range . length; i++)
200+ for (CFIndex i = 0 ; i < t_char_range . length; i++)
189201 t_clusters[i] = 65535 ;
190- for (uint32_t i = 0 ; i < t_glyph_count; i++)
191- t_clusters[t_indices[i] - t_char_range . location] = MCMin (( uint32_t )t_clusters[t_indices[i]], i );
202+ for (CFIndex i = 0 ; i < t_glyph_count; i++)
203+ t_clusters[t_indices[i] - t_char_range . location] = ( uint16_t ) MCMin (i, UINT16_MAX );
192204
193205 for (uint32_t i = 1 ; i < t_char_range . length; i++)
194206 {
195207 // If a cluster has 0xffff as its value it means it was never set and must be
196- // part of a surrogate, so we set it to the previous char.
208+ // part of a surrogate (or an out of order cluster), so we just set it to the
209+ // previous char.
197210 if (t_clusters[i] == 0xffff )
198211 t_clusters[i] = t_clusters[i - 1 ];
199212 }
200213
201214 MCTextLayoutSpan t_span;
202215 t_span . chars = p_chars + t_char_range . location;
203216 t_span . clusters = t_clusters;
204- t_span . char_count = t_char_range . length;
217+ t_span . char_count = ( uint32_t ) t_char_range . length;
205218 t_span . glyphs = t_layout_glyphs;
206- t_span . glyph_count = t_glyph_count;
219+ t_span . glyph_count = ( uint32_t ) t_glyph_count;
207220 t_span . font = (void *)ctfont_from_ctfont ((CTFontRef)CFDictionaryGetValue (CTRunGetAttributes (t_run), kCTFontAttributeName ));
208221 p_callback (p_context, &t_span);
209222
0 commit comments