117 |
117 |
118 /* Returns 0 if didn't decompose, number of resulting characters otherwise. */ |
118 /* Returns 0 if didn't decompose, number of resulting characters otherwise. */ |
119 static inline unsigned int |
119 static inline unsigned int |
120 decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint_t ab) |
120 decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint_t ab) |
121 { |
121 { |
122 hb_codepoint_t a, b, a_glyph, b_glyph; |
122 hb_codepoint_t a = 0, b = 0, a_glyph = 0, b_glyph = 0; |
123 hb_buffer_t * const buffer = c->buffer; |
123 hb_buffer_t * const buffer = c->buffer; |
124 hb_font_t * const font = c->font; |
124 hb_font_t * const font = c->font; |
125 |
125 |
126 if (!c->decompose (c, ab, &a, &b) || |
126 if (!c->decompose (c, ab, &a, &b) || |
127 (b && !font->get_nominal_glyph (b, &b_glyph))) |
127 (b && !font->get_nominal_glyph (b, &b_glyph))) |
162 static inline void |
162 static inline void |
163 decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest) |
163 decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest) |
164 { |
164 { |
165 hb_buffer_t * const buffer = c->buffer; |
165 hb_buffer_t * const buffer = c->buffer; |
166 hb_codepoint_t u = buffer->cur().codepoint; |
166 hb_codepoint_t u = buffer->cur().codepoint; |
167 hb_codepoint_t glyph; |
167 hb_codepoint_t glyph = 0; |
168 |
168 |
169 if (shortest && c->font->get_nominal_glyph (u, &glyph)) |
169 if (shortest && c->font->get_nominal_glyph (u, &glyph)) |
170 { |
170 { |
171 next_char (buffer, glyph); |
171 next_char (buffer, glyph); |
172 return; |
172 return; |
216 handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) |
216 handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) |
217 { |
217 { |
218 /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ |
218 /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ |
219 hb_buffer_t * const buffer = c->buffer; |
219 hb_buffer_t * const buffer = c->buffer; |
220 hb_font_t * const font = c->font; |
220 hb_font_t * const font = c->font; |
221 for (; buffer->idx < end - 1 && !buffer->in_error;) { |
221 for (; buffer->idx < end - 1 && buffer->successful;) { |
222 if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { |
222 if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { |
223 /* The next two lines are some ugly lines... But work. */ |
223 /* The next two lines are some ugly lines... But work. */ |
224 if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) |
224 if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) |
225 { |
225 { |
226 buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); |
226 buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); |
252 |
252 |
253 static inline void |
253 static inline void |
254 decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) |
254 decompose_multi_char_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit) |
255 { |
255 { |
256 hb_buffer_t * const buffer = c->buffer; |
256 hb_buffer_t * const buffer = c->buffer; |
257 for (unsigned int i = buffer->idx; i < end && !buffer->in_error; i++) |
257 for (unsigned int i = buffer->idx; i < end && buffer->successful; i++) |
258 if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) { |
258 if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) { |
259 handle_variation_selector_cluster (c, end, short_circuit); |
259 handle_variation_selector_cluster (c, end, short_circuit); |
260 return; |
260 return; |
261 } |
261 } |
262 |
262 |
263 while (buffer->idx < end && !buffer->in_error) |
263 while (buffer->idx < end && buffer->successful) |
264 decompose_current_character (c, short_circuit); |
264 decompose_current_character (c, short_circuit); |
265 } |
265 } |
266 |
266 |
267 static inline void |
267 static inline void |
268 decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit) |
268 decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit) |
318 |
318 |
319 /* First round, decompose */ |
319 /* First round, decompose */ |
320 |
320 |
321 buffer->clear_output (); |
321 buffer->clear_output (); |
322 count = buffer->len; |
322 count = buffer->len; |
323 for (buffer->idx = 0; buffer->idx < count && !buffer->in_error;) |
323 for (buffer->idx = 0; buffer->idx < count && buffer->successful;) |
324 { |
324 { |
325 unsigned int end; |
325 unsigned int end; |
326 for (end = buffer->idx + 1; end < count; end++) |
326 for (end = buffer->idx + 1; end < count; end++) |
327 if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))) |
327 if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))) |
328 break; |
328 break; |
371 |
371 |
372 buffer->clear_output (); |
372 buffer->clear_output (); |
373 count = buffer->len; |
373 count = buffer->len; |
374 unsigned int starter = 0; |
374 unsigned int starter = 0; |
375 buffer->next_glyph (); |
375 buffer->next_glyph (); |
376 while (buffer->idx < count && !buffer->in_error) |
376 while (buffer->idx < count && buffer->successful) |
377 { |
377 { |
378 hb_codepoint_t composed, glyph; |
378 hb_codepoint_t composed, glyph; |
379 if (/* We don't try to compose a non-mark character with it's preceding starter. |
379 if (/* We don't try to compose a non-mark character with it's preceding starter. |
380 * This is both an optimization to avoid trying to compose every two neighboring |
380 * This is both an optimization to avoid trying to compose every two neighboring |
381 * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul |
381 * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul |
394 /* And the font has glyph for the composite. */ |
394 /* And the font has glyph for the composite. */ |
395 font->get_nominal_glyph (composed, &glyph)) |
395 font->get_nominal_glyph (composed, &glyph)) |
396 { |
396 { |
397 /* Composes. */ |
397 /* Composes. */ |
398 buffer->next_glyph (); /* Copy to out-buffer. */ |
398 buffer->next_glyph (); /* Copy to out-buffer. */ |
399 if (unlikely (buffer->in_error)) |
399 if (unlikely (!buffer->successful)) |
400 return; |
400 return; |
401 buffer->merge_out_clusters (starter, buffer->out_len); |
401 buffer->merge_out_clusters (starter, buffer->out_len); |
402 buffer->out_len--; /* Remove the second composable. */ |
402 buffer->out_len--; /* Remove the second composable. */ |
403 /* Modify starter and carry on. */ |
403 /* Modify starter and carry on. */ |
404 buffer->out_info[starter].codepoint = composed; |
404 buffer->out_info[starter].codepoint = composed; |