367 * ccc=0 chars with their previous Starter. */ |
371 * ccc=0 chars with their previous Starter. */ |
368 |
372 |
369 buffer->clear_output (); |
373 buffer->clear_output (); |
370 count = buffer->len; |
374 count = buffer->len; |
371 unsigned int starter = 0; |
375 unsigned int starter = 0; |
|
376 bool combine = true; |
372 buffer->next_glyph (); |
377 buffer->next_glyph (); |
373 while (buffer->idx < count && !buffer->in_error) |
378 while (buffer->idx < count && !buffer->in_error) |
374 { |
379 { |
375 hb_codepoint_t composed, glyph; |
380 hb_codepoint_t composed, glyph; |
376 if (/* We don't try to compose a non-mark character with it's preceding starter. |
381 if (combine && |
|
382 /* We don't try to compose a non-mark character with it's preceding starter. |
377 * This is both an optimization to avoid trying to compose every two neighboring |
383 * This is both an optimization to avoid trying to compose every two neighboring |
378 * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul |
384 * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul |
379 * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */ |
385 * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */ |
380 HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())) && |
386 HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) |
381 /* If there's anything between the starter and this char, they should have CCC |
|
382 * smaller than this character's. */ |
|
383 (starter == buffer->out_len - 1 || |
|
384 _hb_glyph_info_get_modified_combining_class (&buffer->prev()) < _hb_glyph_info_get_modified_combining_class (&buffer->cur())) && |
|
385 /* And compose. */ |
|
386 c.compose (&c, |
|
387 buffer->out_info[starter].codepoint, |
|
388 buffer->cur().codepoint, |
|
389 &composed) && |
|
390 /* And the font has glyph for the composite. */ |
|
391 font->get_nominal_glyph (composed, &glyph)) |
|
392 { |
387 { |
393 /* Composes. */ |
388 if (/* If there's anything between the starter and this char, they should have CCC |
394 buffer->next_glyph (); /* Copy to out-buffer. */ |
389 * smaller than this character's. */ |
395 if (unlikely (buffer->in_error)) |
390 (starter == buffer->out_len - 1 || |
396 return; |
391 info_cc (buffer->prev()) < info_cc (buffer->cur())) && |
397 buffer->merge_out_clusters (starter, buffer->out_len); |
392 /* And compose. */ |
398 buffer->out_len--; /* Remove the second composable. */ |
393 c.compose (&c, |
399 /* Modify starter and carry on. */ |
394 buffer->out_info[starter].codepoint, |
400 buffer->out_info[starter].codepoint = composed; |
395 buffer->cur().codepoint, |
401 buffer->out_info[starter].glyph_index() = glyph; |
396 &composed) && |
402 _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); |
397 /* And the font has glyph for the composite. */ |
403 |
398 font->get_nominal_glyph (composed, &glyph)) |
404 continue; |
399 { |
|
400 /* Composes. */ |
|
401 buffer->next_glyph (); /* Copy to out-buffer. */ |
|
402 if (unlikely (buffer->in_error)) |
|
403 return; |
|
404 buffer->merge_out_clusters (starter, buffer->out_len); |
|
405 buffer->out_len--; /* Remove the second composable. */ |
|
406 /* Modify starter and carry on. */ |
|
407 buffer->out_info[starter].codepoint = composed; |
|
408 buffer->out_info[starter].glyph_index() = glyph; |
|
409 _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); |
|
410 |
|
411 continue; |
|
412 } |
|
413 else if (/* We sometimes custom-tailor the sorted order of marks. In that case, stop |
|
414 * trying to combine as soon as combining-class drops. */ |
|
415 starter < buffer->out_len - 1 && |
|
416 info_cc (buffer->prev()) > info_cc (buffer->cur())) |
|
417 combine = false; |
405 } |
418 } |
406 |
419 |
407 /* Blocked, or doesn't compose. */ |
420 /* Blocked, or doesn't compose. */ |
408 buffer->next_glyph (); |
421 buffer->next_glyph (); |
409 |
422 |
410 if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0) |
423 if (info_cc (buffer->prev()) == 0) |
|
424 { |
411 starter = buffer->out_len - 1; |
425 starter = buffer->out_len - 1; |
|
426 combine = true; |
|
427 } |
412 } |
428 } |
413 buffer->swap_buffers (); |
429 buffer->swap_buffers (); |
414 |
430 |
415 } |
431 } |