2 * Copyright © 2009,2010 Red Hat, Inc.
3 * Copyright © 2010,2011,2012 Google, Inc.
5 * This is part of HarfBuzz, a text shaping library.
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 * Red Hat Author(s): Behdad Esfahbod
26 * Google Author(s): Behdad Esfahbod
30 #define hb_ot_shaper_face_data_t hb_ot_layout_t
31 #define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
32 #include "hb-shaper-impl-private.hh"
34 #include "hb-ot-shape-private.hh"
35 #include "hb-ot-shape-complex-private.hh"
36 #include "hb-ot-shape-fallback-private.hh"
37 #include "hb-ot-shape-normalize-private.hh"
39 #include "hb-ot-layout-private.hh"
40 #include "hb-unicode-private.hh"
41 #include "hb-set-private.hh"
44 static hb_tag_t common_features
[] = {
45 HB_TAG('c','c','m','p'),
46 HB_TAG('l','o','c','l'),
47 HB_TAG('m','a','r','k'),
48 HB_TAG('m','k','m','k'),
49 HB_TAG('r','l','i','g'),
53 static hb_tag_t horizontal_features
[] = {
54 HB_TAG('c','a','l','t'),
55 HB_TAG('c','l','i','g'),
56 HB_TAG('c','u','r','s'),
57 HB_TAG('k','e','r','n'),
58 HB_TAG('l','i','g','a'),
59 HB_TAG('r','c','l','t'),
65 hb_ot_shape_collect_features (hb_ot_shape_planner_t
*planner
,
66 const hb_segment_properties_t
*props
,
67 const hb_feature_t
*user_features
,
68 unsigned int num_user_features
)
70 hb_ot_map_builder_t
*map
= &planner
->map
;
72 switch (props
->direction
) {
73 case HB_DIRECTION_LTR
:
74 map
->add_global_bool_feature (HB_TAG ('l','t','r','a'));
75 map
->add_global_bool_feature (HB_TAG ('l','t','r','m'));
77 case HB_DIRECTION_RTL
:
78 map
->add_global_bool_feature (HB_TAG ('r','t','l','a'));
79 map
->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE
);
81 case HB_DIRECTION_TTB
:
82 case HB_DIRECTION_BTT
:
83 case HB_DIRECTION_INVALID
:
88 map
->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE
);
89 map
->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE
);
90 map
->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE
);
92 if (planner
->shaper
->collect_features
)
93 planner
->shaper
->collect_features (planner
);
95 for (unsigned int i
= 0; i
< ARRAY_LENGTH (common_features
); i
++)
96 map
->add_global_bool_feature (common_features
[i
]);
98 if (HB_DIRECTION_IS_HORIZONTAL (props
->direction
))
99 for (unsigned int i
= 0; i
< ARRAY_LENGTH (horizontal_features
); i
++)
100 map
->add_feature (horizontal_features
[i
], 1, F_GLOBAL
|
101 (horizontal_features
[i
] == HB_TAG('k','e','r','n') ?
102 F_HAS_FALLBACK
: F_NONE
));
105 /* We really want to find a 'vert' feature if there's any in the font, no
106 * matter which script/langsys it is listed (or not) under.
107 * See various bugs referenced from:
108 * https://github.com/behdad/harfbuzz/issues/63 */
109 map
->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL
| F_GLOBAL_SEARCH
);
112 if (planner
->shaper
->override_features
)
113 planner
->shaper
->override_features (planner
);
115 for (unsigned int i
= 0; i
< num_user_features
; i
++) {
116 const hb_feature_t
*feature
= &user_features
[i
];
117 map
->add_feature (feature
->tag
, feature
->value
,
118 (feature
->start
== 0 && feature
->end
== (unsigned int) -1) ?
128 hb_ot_shaper_face_data_t
*
129 _hb_ot_shaper_face_data_create (hb_face_t
*face
)
131 return _hb_ot_layout_create (face
);
135 _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t
*data
)
137 _hb_ot_layout_destroy (data
);
145 struct hb_ot_shaper_font_data_t
{};
147 hb_ot_shaper_font_data_t
*
148 _hb_ot_shaper_font_data_create (hb_font_t
*font
)
150 return (hb_ot_shaper_font_data_t
*) HB_SHAPER_DATA_SUCCEEDED
;
154 _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t
*data
)
160 * shaper shape_plan data
163 hb_ot_shaper_shape_plan_data_t
*
164 _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t
*shape_plan
,
165 const hb_feature_t
*user_features
,
166 unsigned int num_user_features
)
168 hb_ot_shape_plan_t
*plan
= (hb_ot_shape_plan_t
*) calloc (1, sizeof (hb_ot_shape_plan_t
));
169 if (unlikely (!plan
))
172 hb_ot_shape_planner_t
planner (shape_plan
);
174 planner
.shaper
= hb_ot_shape_complex_categorize (&planner
);
176 hb_ot_shape_collect_features (&planner
, &shape_plan
->props
, user_features
, num_user_features
);
178 planner
.compile (*plan
);
180 if (plan
->shaper
->data_create
) {
181 plan
->data
= plan
->shaper
->data_create (plan
);
182 if (unlikely (!plan
->data
))
190 _hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t
*plan
)
192 if (plan
->shaper
->data_destroy
)
193 plan
->shaper
->data_destroy (const_cast<void *> (plan
->data
));
205 struct hb_ot_shape_context_t
207 hb_ot_shape_plan_t
*plan
;
211 const hb_feature_t
*user_features
;
212 unsigned int num_user_features
;
214 /* Transient stuff */
215 hb_direction_t target_direction
;
226 hb_set_unicode_props (hb_buffer_t
*buffer
)
228 unsigned int count
= buffer
->len
;
229 hb_glyph_info_t
*info
= buffer
->info
;
230 for (unsigned int i
= 0; i
< count
; i
++)
231 _hb_glyph_info_set_unicode_props (&info
[i
], buffer
->unicode
);
235 hb_insert_dotted_circle (hb_buffer_t
*buffer
, hb_font_t
*font
)
237 if (!(buffer
->flags
& HB_BUFFER_FLAG_BOT
) ||
238 buffer
->context_len
[0] ||
239 _hb_glyph_info_get_general_category (&buffer
->info
[0]) !=
240 HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK
)
243 if (!font
->has_glyph (0x25CCu
))
246 hb_glyph_info_t dottedcircle
= {0};
247 dottedcircle
.codepoint
= 0x25CCu
;
248 _hb_glyph_info_set_unicode_props (&dottedcircle
, buffer
->unicode
);
250 buffer
->clear_output ();
253 hb_glyph_info_t info
= dottedcircle
;
254 info
.cluster
= buffer
->cur().cluster
;
255 info
.mask
= buffer
->cur().mask
;
256 buffer
->output_info (info
);
257 while (buffer
->idx
< buffer
->len
)
258 buffer
->next_glyph ();
260 buffer
->swap_buffers ();
264 hb_form_clusters (hb_buffer_t
*buffer
)
266 if (buffer
->cluster_level
!= HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
)
269 /* Loop duplicated in hb_ensure_native_direction(). */
270 unsigned int base
= 0;
271 unsigned int count
= buffer
->len
;
272 hb_glyph_info_t
*info
= buffer
->info
;
273 for (unsigned int i
= 1; i
< count
; i
++)
275 if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info
[i
]))))
277 buffer
->merge_clusters (base
, i
);
281 buffer
->merge_clusters (base
, count
);
285 hb_ensure_native_direction (hb_buffer_t
*buffer
)
287 hb_direction_t direction
= buffer
->props
.direction
;
290 * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
291 * Ogham fonts are supposed to be implemented BTT or not. Need to research that
293 if ((HB_DIRECTION_IS_HORIZONTAL (direction
) && direction
!= hb_script_get_horizontal_direction (buffer
->props
.script
)) ||
294 (HB_DIRECTION_IS_VERTICAL (direction
) && direction
!= HB_DIRECTION_TTB
))
296 /* Same loop as hb_form_clusters().
297 * Since form_clusters() merged clusters already, we don't merge. */
298 unsigned int base
= 0;
299 unsigned int count
= buffer
->len
;
300 hb_glyph_info_t
*info
= buffer
->info
;
301 for (unsigned int i
= 1; i
< count
; i
++)
303 if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info
[i
]))))
305 buffer
->reverse_range (base
, i
);
306 if (buffer
->cluster_level
== HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS
)
307 buffer
->merge_clusters (base
, i
);
311 buffer
->reverse_range (base
, count
);
312 if (buffer
->cluster_level
== HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS
)
313 buffer
->merge_clusters (base
, count
);
317 buffer
->props
.direction
= HB_DIRECTION_REVERSE (buffer
->props
.direction
);
325 hb_ot_mirror_chars (hb_ot_shape_context_t
*c
)
327 if (HB_DIRECTION_IS_FORWARD (c
->target_direction
))
330 hb_buffer_t
*buffer
= c
->buffer
;
331 hb_unicode_funcs_t
*unicode
= buffer
->unicode
;
332 hb_mask_t rtlm_mask
= c
->plan
->rtlm_mask
;
334 unsigned int count
= buffer
->len
;
335 hb_glyph_info_t
*info
= buffer
->info
;
336 for (unsigned int i
= 0; i
< count
; i
++) {
337 hb_codepoint_t codepoint
= unicode
->mirroring (info
[i
].codepoint
);
338 if (likely (codepoint
== info
[i
].codepoint
|| !c
->font
->has_glyph (codepoint
)))
339 info
[i
].mask
|= rtlm_mask
;
341 info
[i
].codepoint
= codepoint
;
346 hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t
*c
)
348 if (!c
->plan
->has_frac
)
351 hb_buffer_t
*buffer
= c
->buffer
;
353 /* TODO look in pre/post context text also. */
354 unsigned int count
= buffer
->len
;
355 hb_glyph_info_t
*info
= buffer
->info
;
356 for (unsigned int i
= 0; i
< count
; i
++)
358 if (info
[i
].codepoint
== 0x2044u
) /* FRACTION SLASH */
360 unsigned int start
= i
, end
= i
+ 1;
362 _hb_glyph_info_get_general_category (&info
[start
- 1]) ==
363 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER
)
365 while (end
< count
&&
366 _hb_glyph_info_get_general_category (&info
[end
]) ==
367 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER
)
370 for (unsigned int j
= start
; j
< i
; j
++)
371 info
[j
].mask
|= c
->plan
->numr_mask
| c
->plan
->frac_mask
;
372 info
[i
].mask
|= c
->plan
->frac_mask
;
373 for (unsigned int j
= i
+ 1; j
< end
; j
++)
374 info
[j
].mask
|= c
->plan
->frac_mask
| c
->plan
->dnom_mask
;
382 hb_ot_shape_initialize_masks (hb_ot_shape_context_t
*c
)
384 hb_ot_map_t
*map
= &c
->plan
->map
;
385 hb_buffer_t
*buffer
= c
->buffer
;
387 hb_mask_t global_mask
= map
->get_global_mask ();
388 buffer
->reset_masks (global_mask
);
392 hb_ot_shape_setup_masks (hb_ot_shape_context_t
*c
)
394 hb_ot_map_t
*map
= &c
->plan
->map
;
395 hb_buffer_t
*buffer
= c
->buffer
;
397 hb_ot_shape_setup_masks_fraction (c
);
399 if (c
->plan
->shaper
->setup_masks
)
400 c
->plan
->shaper
->setup_masks (c
->plan
, buffer
, c
->font
);
402 for (unsigned int i
= 0; i
< c
->num_user_features
; i
++)
404 const hb_feature_t
*feature
= &c
->user_features
[i
];
405 if (!(feature
->start
== 0 && feature
->end
== (unsigned int)-1)) {
407 hb_mask_t mask
= map
->get_mask (feature
->tag
, &shift
);
408 buffer
->set_masks (feature
->value
<< shift
, mask
, feature
->start
, feature
->end
);
414 hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t
*c
)
416 hb_buffer_t
*buffer
= c
->buffer
;
418 if (buffer
->flags
& HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES
)
421 unsigned int count
= buffer
->len
;
422 hb_glyph_info_t
*info
= buffer
->info
;
423 hb_glyph_position_t
*pos
= buffer
->pos
;
425 for (i
= 0; i
< count
; i
++)
426 if (unlikely (_hb_glyph_info_is_default_ignorable (&info
[i
])))
427 pos
[i
].x_advance
= pos
[i
].y_advance
= pos
[i
].x_offset
= pos
[i
].y_offset
= 0;
431 hb_ot_hide_default_ignorables (hb_ot_shape_context_t
*c
)
433 hb_buffer_t
*buffer
= c
->buffer
;
435 if (buffer
->flags
& HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES
)
438 unsigned int count
= buffer
->len
;
439 hb_glyph_info_t
*info
= buffer
->info
;
440 hb_glyph_position_t
*pos
= buffer
->pos
;
442 for (i
= 0; i
< count
; i
++)
444 if (unlikely (_hb_glyph_info_is_default_ignorable (&info
[i
])))
448 /* No default-ignorables found; return. */
452 hb_codepoint_t space
;
453 if (c
->font
->get_glyph (' ', 0, &space
))
455 /* Replace default-ignorables with a zero-advance space glyph. */
456 for (/*continue*/; i
< count
; i
++)
458 if (_hb_glyph_info_is_default_ignorable (&info
[i
]))
459 info
[i
].codepoint
= space
;
464 /* Merge clusters and delete default-ignorables.
465 * NOTE! We can't use out-buffer as we have positioning data. */
467 for (; i
< count
; i
++)
469 if (_hb_glyph_info_is_default_ignorable (&info
[i
]))
472 * Same logic as buffer->delete_glyph(), but for in-place removal. */
474 unsigned int cluster
= info
[i
].cluster
;
475 if (i
+ 1 < count
&& cluster
== info
[i
+ 1].cluster
)
476 continue; /* Cluster survives; do nothing. */
480 /* Merge cluster backward. */
481 if (cluster
< info
[j
- 1].cluster
)
483 unsigned int old_cluster
= info
[j
- 1].cluster
;
484 for (unsigned k
= j
; k
&& info
[k
- 1].cluster
== old_cluster
; k
--)
485 info
[k
- 1].cluster
= cluster
;
491 buffer
->merge_clusters (i
, i
+ 2); /* Merge cluster forward. */
509 hb_ot_map_glyphs_fast (hb_buffer_t
*buffer
)
511 /* Normalization process sets up glyph_index(), we just copy it. */
512 unsigned int count
= buffer
->len
;
513 hb_glyph_info_t
*info
= buffer
->info
;
514 for (unsigned int i
= 0; i
< count
; i
++)
515 info
[i
].codepoint
= info
[i
].glyph_index();
517 buffer
->content_type
= HB_BUFFER_CONTENT_TYPE_GLYPHS
;
521 hb_synthesize_glyph_classes (hb_ot_shape_context_t
*c
)
523 unsigned int count
= c
->buffer
->len
;
524 hb_glyph_info_t
*info
= c
->buffer
->info
;
525 for (unsigned int i
= 0; i
< count
; i
++)
527 hb_ot_layout_glyph_class_mask_t klass
;
529 /* Never mark default-ignorables as marks.
530 * They won't get in the way of lookups anyway,
531 * but having them as mark will cause them to be skipped
532 * over if the lookup-flag says so, but at least for the
533 * Mongolian variation selectors, looks like Uniscribe
534 * marks them as non-mark. Some Mongolian fonts without
535 * GDEF rely on this. Another notable character that
536 * this applies to is COMBINING GRAPHEME JOINER. */
537 klass
= (_hb_glyph_info_get_general_category (&info
[i
]) !=
538 HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK
||
539 _hb_glyph_info_is_default_ignorable (&info
[i
])) ?
540 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH
:
541 HB_OT_LAYOUT_GLYPH_PROPS_MARK
;
542 _hb_glyph_info_set_glyph_props (&info
[i
], klass
);
547 hb_ot_substitute_default (hb_ot_shape_context_t
*c
)
549 hb_buffer_t
*buffer
= c
->buffer
;
551 if (c
->plan
->shaper
->preprocess_text
)
552 c
->plan
->shaper
->preprocess_text (c
->plan
, buffer
, c
->font
);
554 hb_ot_shape_initialize_masks (c
);
556 hb_ot_mirror_chars (c
);
558 HB_BUFFER_ALLOCATE_VAR (buffer
, glyph_index
);
560 _hb_ot_shape_normalize (c
->plan
, buffer
, c
->font
);
562 hb_ot_shape_setup_masks (c
);
564 /* This is unfortunate to go here, but necessary... */
565 if (!hb_ot_layout_has_positioning (c
->face
))
566 _hb_ot_shape_fallback_position_recategorize_marks (c
->plan
, c
->font
, buffer
);
568 hb_ot_map_glyphs_fast (buffer
);
570 HB_BUFFER_DEALLOCATE_VAR (buffer
, glyph_index
);
574 hb_ot_substitute_complex (hb_ot_shape_context_t
*c
)
576 hb_buffer_t
*buffer
= c
->buffer
;
578 _hb_buffer_allocate_gsubgpos_vars (buffer
);
579 hb_ot_layout_substitute_start (c
->font
, buffer
);
581 if (!hb_ot_layout_has_glyph_classes (c
->face
))
582 hb_synthesize_glyph_classes (c
);
584 c
->plan
->substitute (c
->font
, buffer
);
586 hb_ot_layout_substitute_finish (c
->font
, buffer
);
592 hb_ot_substitute (hb_ot_shape_context_t
*c
)
594 hb_ot_substitute_default (c
);
595 hb_ot_substitute_complex (c
);
601 adjust_mark_offsets (hb_glyph_position_t
*pos
)
603 pos
->x_offset
-= pos
->x_advance
;
604 pos
->y_offset
-= pos
->y_advance
;
608 zero_mark_width (hb_glyph_position_t
*pos
)
615 zero_mark_widths_by_unicode (hb_buffer_t
*buffer
, bool adjust_offsets
)
617 unsigned int count
= buffer
->len
;
618 hb_glyph_info_t
*info
= buffer
->info
;
619 for (unsigned int i
= 0; i
< count
; i
++)
620 if (_hb_glyph_info_get_general_category (&info
[i
]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK
)
623 adjust_mark_offsets (&buffer
->pos
[i
]);
624 zero_mark_width (&buffer
->pos
[i
]);
629 zero_mark_widths_by_gdef (hb_buffer_t
*buffer
, bool adjust_offsets
)
631 unsigned int count
= buffer
->len
;
632 hb_glyph_info_t
*info
= buffer
->info
;
633 for (unsigned int i
= 0; i
< count
; i
++)
634 if (_hb_glyph_info_is_mark (&info
[i
]))
637 adjust_mark_offsets (&buffer
->pos
[i
]);
638 zero_mark_width (&buffer
->pos
[i
]);
643 hb_ot_position_default (hb_ot_shape_context_t
*c
)
645 hb_direction_t direction
= c
->buffer
->props
.direction
;
646 unsigned int count
= c
->buffer
->len
;
647 hb_glyph_info_t
*info
= c
->buffer
->info
;
648 hb_glyph_position_t
*pos
= c
->buffer
->pos
;
649 for (unsigned int i
= 0; i
< count
; i
++)
651 c
->font
->get_glyph_advance_for_direction (info
[i
].codepoint
,
655 c
->font
->subtract_glyph_origin_for_direction (info
[i
].codepoint
,
664 hb_ot_position_complex (hb_ot_shape_context_t
*c
)
667 unsigned int count
= c
->buffer
->len
;
668 bool has_positioning
= hb_ot_layout_has_positioning (c
->face
);
669 /* If the font has no GPOS, AND, no fallback positioning will
670 * happen, AND, direction is forward, then when zeroing mark
671 * widths, we shift the mark with it, such that the mark
672 * is positioned hanging over the previous glyph. When
673 * direction is backward we don't shift and it will end up
674 * hanging over the next glyph after the final reordering.
675 * If fallback positinoing happens or GPOS is present, we don't
678 bool adjust_offsets_when_zeroing
= !(has_positioning
|| c
->plan
->shaper
->fallback_position
||
679 HB_DIRECTION_IS_BACKWARD (c
->buffer
->props
.direction
));
681 switch (c
->plan
->shaper
->zero_width_marks
)
683 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY
:
684 zero_mark_widths_by_gdef (c
->buffer
, adjust_offsets_when_zeroing
);
687 /* Not currently used for any shaper:
688 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
689 zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
694 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE
:
695 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE
:
696 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
:
702 hb_glyph_info_t
*info
= c
->buffer
->info
;
703 hb_glyph_position_t
*pos
= c
->buffer
->pos
;
705 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */
707 for (unsigned int i
= 0; i
< count
; i
++) {
708 c
->font
->add_glyph_origin_for_direction (info
[i
].codepoint
,
714 c
->plan
->position (c
->font
, c
->buffer
);
716 for (unsigned int i
= 0; i
< count
; i
++) {
717 c
->font
->subtract_glyph_origin_for_direction (info
[i
].codepoint
,
726 switch (c
->plan
->shaper
->zero_width_marks
)
728 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE
:
729 zero_mark_widths_by_unicode (c
->buffer
, adjust_offsets_when_zeroing
);
732 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
:
733 zero_mark_widths_by_gdef (c
->buffer
, adjust_offsets_when_zeroing
);
737 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE
:
738 //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
739 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY
:
747 hb_ot_position (hb_ot_shape_context_t
*c
)
749 hb_ot_layout_position_start (c
->font
, c
->buffer
);
751 hb_ot_position_default (c
);
753 hb_bool_t fallback
= !hb_ot_position_complex (c
);
755 hb_ot_zero_width_default_ignorables (c
);
757 hb_ot_layout_position_finish (c
->font
, c
->buffer
);
759 if (fallback
&& c
->plan
->shaper
->fallback_position
)
760 _hb_ot_shape_fallback_position (c
->plan
, c
->font
, c
->buffer
);
762 if (HB_DIRECTION_IS_BACKWARD (c
->buffer
->props
.direction
))
763 hb_buffer_reverse (c
->buffer
);
765 /* Visual fallback goes here. */
768 _hb_ot_shape_fallback_kern (c
->plan
, c
->font
, c
->buffer
);
770 _hb_buffer_deallocate_gsubgpos_vars (c
->buffer
);
774 /* Pull it all together! */
777 hb_ot_shape_internal (hb_ot_shape_context_t
*c
)
779 c
->buffer
->deallocate_var_all ();
781 /* Save the original direction, we use it later. */
782 c
->target_direction
= c
->buffer
->props
.direction
;
784 _hb_buffer_allocate_unicode_vars (c
->buffer
);
786 c
->buffer
->clear_output ();
788 hb_set_unicode_props (c
->buffer
);
789 hb_insert_dotted_circle (c
->buffer
, c
->font
);
790 hb_form_clusters (c
->buffer
);
792 hb_ensure_native_direction (c
->buffer
);
794 hb_ot_substitute (c
);
797 hb_ot_hide_default_ignorables (c
);
799 _hb_buffer_deallocate_unicode_vars (c
->buffer
);
801 c
->buffer
->props
.direction
= c
->target_direction
;
803 c
->buffer
->deallocate_var_all ();
808 _hb_ot_shape (hb_shape_plan_t
*shape_plan
,
811 const hb_feature_t
*features
,
812 unsigned int num_features
)
814 hb_ot_shape_context_t c
= {HB_SHAPER_DATA_GET (shape_plan
), font
, font
->face
, buffer
, features
, num_features
};
815 hb_ot_shape_internal (&c
);
825 hb_ot_shape_plan_collect_lookups (hb_shape_plan_t
*shape_plan
,
827 hb_set_t
*lookup_indexes
/* OUT */)
829 /* XXX Does the first part always succeed? */
830 HB_SHAPER_DATA_GET (shape_plan
)->collect_lookups (table_tag
, lookup_indexes
);
834 /* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
836 add_char (hb_font_t
*font
,
837 hb_unicode_funcs_t
*unicode
,
842 hb_codepoint_t glyph
;
843 if (font
->get_glyph (u
, 0, &glyph
))
847 hb_codepoint_t m
= unicode
->mirroring (u
);
848 if (m
!= u
&& font
->get_glyph (m
, 0, &glyph
))
858 hb_ot_shape_glyphs_closure (hb_font_t
*font
,
860 const hb_feature_t
*features
,
861 unsigned int num_features
,
864 hb_ot_shape_plan_t plan
;
866 const char *shapers
[] = {"ot", NULL
};
867 hb_shape_plan_t
*shape_plan
= hb_shape_plan_create_cached (font
->face
, &buffer
->props
,
868 features
, num_features
, shapers
);
870 bool mirror
= hb_script_get_horizontal_direction (buffer
->props
.script
) == HB_DIRECTION_RTL
;
872 unsigned int count
= buffer
->len
;
873 hb_glyph_info_t
*info
= buffer
->info
;
874 for (unsigned int i
= 0; i
< count
; i
++)
875 add_char (font
, buffer
->unicode
, mirror
, info
[i
].codepoint
, glyphs
);
879 hb_ot_shape_plan_collect_lookups (shape_plan
, HB_OT_TAG_GSUB
, &lookups
);
881 /* And find transitive closure. */
886 for (hb_codepoint_t lookup_index
= -1; hb_set_next (&lookups
, &lookup_index
);)
887 hb_ot_layout_lookup_substitute_closure (font
->face
, lookup_index
, glyphs
);
888 } while (!copy
.is_equal (glyphs
));
890 hb_shape_plan_destroy (shape_plan
);