74 decompose_unicode (const hb_ot_shape_normalize_context_t *c,
75 hb_codepoint_t ab,
76 hb_codepoint_t *a,
77 hb_codepoint_t *b)
78 {
79 return (bool) c->unicode->decompose (ab, a, b);
80 }
81
82 static bool
83 compose_unicode (const hb_ot_shape_normalize_context_t *c,
84 hb_codepoint_t a,
85 hb_codepoint_t b,
86 hb_codepoint_t *ab)
87 {
88 return (bool) c->unicode->compose (a, b, ab);
89 }
90
91 static inline void
92 set_glyph (hb_glyph_info_t &info, hb_font_t *font)
93 {
94 font->get_nominal_glyph (info.codepoint, &info.glyph_index());
95 }
96
97 static inline void
98 output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
99 {
100 buffer->cur().glyph_index() = glyph;
101 buffer->output_glyph (unichar); /* This is very confusing indeed. */
102 _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
103 }
104
105 static inline void
106 next_char (hb_buffer_t *buffer, hb_codepoint_t glyph)
107 {
108 buffer->cur().glyph_index() = glyph;
109 buffer->next_glyph ();
110 }
111
112 static inline void
113 skip_char (hb_buffer_t *buffer)
114 {
328 break;
329
330 decompose_cluster (&c, end, might_short_circuit, always_short_circuit);
331 }
332 buffer->swap_buffers ();
333
334
335 /* Second round, reorder (inplace) */
336
337 count = buffer->len;
338 for (unsigned int i = 0; i < count; i++)
339 {
340 if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
341 continue;
342
343 unsigned int end;
344 for (end = i + 1; end < count; end++)
345 if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
346 break;
347
348 /* We are going to do a O(n^2). Only do this if the sequence is short. */
349 if (end - i > 10) {
350 i = end;
351 continue;
352 }
353
354 buffer->sort (i, end, compare_combining_class);
355
356 i = end;
357 }
358
359
360 if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
361 mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
362 return;
363
364 /* Third round, recompose */
365
366 /* As noted in the comment earlier, we don't try to combine
367 * ccc=0 chars with their previous Starter. */
368
369 buffer->clear_output ();
370 count = buffer->len;
371 unsigned int starter = 0;
372 buffer->next_glyph ();
373 while (buffer->idx < count && !buffer->in_error)
374 {
375 hb_codepoint_t composed, glyph;
376 if (/* 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
378 * 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. */
380 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 {
393 /* Composes. */
394 buffer->next_glyph (); /* Copy to out-buffer. */
395 if (unlikely (buffer->in_error))
396 return;
397 buffer->merge_out_clusters (starter, buffer->out_len);
398 buffer->out_len--; /* Remove the second composable. */
399 /* Modify starter and carry on. */
400 buffer->out_info[starter].codepoint = composed;
401 buffer->out_info[starter].glyph_index() = glyph;
402 _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
403
404 continue;
405 }
406
407 /* Blocked, or doesn't compose. */
408 buffer->next_glyph ();
409
410 if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0)
411 starter = buffer->out_len - 1;
412 }
413 buffer->swap_buffers ();
414
415 }
|
74 decompose_unicode (const hb_ot_shape_normalize_context_t *c,
75 hb_codepoint_t ab,
76 hb_codepoint_t *a,
77 hb_codepoint_t *b)
78 {
79 return (bool) c->unicode->decompose (ab, a, b);
80 }
81
82 static bool
83 compose_unicode (const hb_ot_shape_normalize_context_t *c,
84 hb_codepoint_t a,
85 hb_codepoint_t b,
86 hb_codepoint_t *ab)
87 {
88 return (bool) c->unicode->compose (a, b, ab);
89 }
90
91 static inline void
92 set_glyph (hb_glyph_info_t &info, hb_font_t *font)
93 {
94 (void) font->get_nominal_glyph (info.codepoint, &info.glyph_index());
95 }
96
97 static inline void
98 output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph)
99 {
100 buffer->cur().glyph_index() = glyph;
101 buffer->output_glyph (unichar); /* This is very confusing indeed. */
102 _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer);
103 }
104
105 static inline void
106 next_char (hb_buffer_t *buffer, hb_codepoint_t glyph)
107 {
108 buffer->cur().glyph_index() = glyph;
109 buffer->next_glyph ();
110 }
111
112 static inline void
113 skip_char (hb_buffer_t *buffer)
114 {
328 break;
329
330 decompose_cluster (&c, end, might_short_circuit, always_short_circuit);
331 }
332 buffer->swap_buffers ();
333
334
335 /* Second round, reorder (inplace) */
336
337 count = buffer->len;
338 for (unsigned int i = 0; i < count; i++)
339 {
340 if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
341 continue;
342
343 unsigned int end;
344 for (end = i + 1; end < count; end++)
345 if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
346 break;
347
348 /* We are going to do a O(n^2). Only do this if the sequence is short,
349 * but not too short ;). */
350 if (end - i < 2 || end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
351 i = end;
352 continue;
353 }
354
355 buffer->sort (i, end, compare_combining_class);
356
357 if (plan->shaper->reorder_marks)
358 plan->shaper->reorder_marks (plan, buffer, i, end);
359
360 i = end;
361 }
362
363
364 if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
365 mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
366 return;
367
368 /* Third round, recompose */
369
370 /* As noted in the comment earlier, we don't try to combine
371 * ccc=0 chars with their previous Starter. */
372
373 buffer->clear_output ();
374 count = buffer->len;
375 unsigned int starter = 0;
376 bool combine = true;
377 buffer->next_glyph ();
378 while (buffer->idx < count && !buffer->in_error)
379 {
380 hb_codepoint_t composed, glyph;
381 if (combine &&
382 /* We don't try to compose a non-mark character with it's preceding starter.
383 * This is both an optimization to avoid trying to compose every two neighboring
384 * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul
385 * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
386 HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
387 {
388 if (/* If there's anything between the starter and this char, they should have CCC
389 * smaller than this character's. */
390 (starter == buffer->out_len - 1 ||
391 info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
392 /* And compose. */
393 c.compose (&c,
394 buffer->out_info[starter].codepoint,
395 buffer->cur().codepoint,
396 &composed) &&
397 /* And the font has glyph for the composite. */
398 font->get_nominal_glyph (composed, &glyph))
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;
418 }
419
420 /* Blocked, or doesn't compose. */
421 buffer->next_glyph ();
422
423 if (info_cc (buffer->prev()) == 0)
424 {
425 starter = buffer->out_len - 1;
426 combine = true;
427 }
428 }
429 buffer->swap_buffers ();
430
431 }
|