diff options
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc')
-rw-r--r-- | Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc | 307 |
1 files changed, 137 insertions, 170 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc index 8c5e38e06dd..ccee8d34300 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape.cc @@ -26,8 +26,6 @@ * Google Author(s): Behdad Esfahbod */ -#define HB_SHAPER ot -#define hb_ot_shape_plan_data_t hb_ot_shape_plan_t #include "hb-shaper-impl.hh" #include "hb-ot-shape.hh" @@ -52,6 +50,11 @@ **/ +static void +hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, + const hb_feature_t *user_features, + unsigned int num_user_features); + static bool _hb_apply_morx (hb_face_t *face) { @@ -59,37 +62,41 @@ _hb_apply_morx (hb_face_t *face) hb_aat_layout_has_substitution (face)) return true; - return !hb_ot_layout_has_substitution (face) && + /* Ignore empty GSUB tables. */ + return (!hb_ot_layout_has_substitution (face) || + !hb_ot_layout_table_get_script_tags (face, + HB_OT_TAG_GSUB, + 0, nullptr, nullptr)) && hb_aat_layout_has_substitution (face); } -hb_ot_shape_planner_t::hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : - face (master_plan->face_unsafe), - props (master_plan->props), - map (face, &props), - aat_map (face, &props), +hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face, + const hb_segment_properties_t *props) : + face (face), + props (*props), + map (face, props), + aat_map (face, props), apply_morx (_hb_apply_morx (face)), shaper (apply_morx ? &_hb_ot_complex_shaper_default : hb_ot_shape_complex_categorize (this)) {} void -hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, - const int *coords, - unsigned int num_coords) +hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, + const hb_ot_shape_plan_key_t &key) { plan.props = props; plan.shaper = shaper; - map.compile (plan.map, coords, num_coords); + map.compile (plan.map, key); if (apply_morx) - aat_map.compile (plan.aat_map, coords, num_coords); + aat_map.compile (plan.aat_map); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m')); plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask); plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); - hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ? + hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ? HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'); plan.kern_mask = plan.map.get_mask (kern_tag); plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k')); @@ -119,30 +126,91 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, if (hb_options ().aat && hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; - else if (!disable_gpos && hb_ot_layout_has_positioning (face)) + else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face)) plan.apply_gpos = true; else if (hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; - if (plan.requested_kerning && !plan.apply_kerx && !has_gpos_kern) + if (!plan.apply_kerx && !has_gpos_kern) { /* Apparently Apple applies kerx if GPOS kern was not applied. */ if (hb_aat_layout_has_positioning (face)) plan.apply_kerx = true; - if (hb_ot_layout_has_kerning (face)) + else if (hb_ot_layout_has_kerning (face)) plan.apply_kern = true; - else - plan.fallback_kerning = true; } + bool has_kern_mark = plan.apply_kern && hb_ot_layout_has_cross_kerning (face); + plan.zero_marks = !plan.apply_morx && !plan.apply_kerx && !has_kern_mark; plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k')); - if (!plan.apply_gpos && !plan.apply_kerx) - plan.fallback_mark_positioning = true; + plan.fallback_mark_positioning = !plan.apply_gpos && plan.zero_marks; /* Currently we always apply trak. */ plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face); } +bool +hb_ot_shape_plan_t::init0 (hb_face_t *face, + const hb_shape_plan_key_t *key) +{ + map.init (); + aat_map.init (); + + hb_ot_shape_planner_t planner (face, + &key->props); + hb_ot_shape_collect_features (&planner, + key->user_features, + key->num_user_features); + + planner.compile (*this, key->ot); + + if (shaper->data_create) + { + data = shaper->data_create (this); + if (unlikely (!data)) + return false; + } + + return true; +} + +void +hb_ot_shape_plan_t::fini (void) +{ + if (shaper->data_destroy) + shaper->data_destroy (const_cast<void *> (data)); + + map.fini (); + aat_map.fini (); +} + +void +hb_ot_shape_plan_t::substitute (hb_font_t *font, + hb_buffer_t *buffer) const +{ + if (unlikely (apply_morx)) + hb_aat_layout_substitute (this, font, buffer); + else + map.substitute (this, font, buffer); +} + +void +hb_ot_shape_plan_t::position (hb_font_t *font, + hb_buffer_t *buffer) const +{ + if (this->apply_gpos) + map.position (this, font, buffer); + else if (this->apply_kerx) + hb_aat_layout_position (this, font, buffer); + else if (this->apply_kern) + hb_ot_layout_kern (this, font, buffer); + else + _hb_ot_shape_fallback_kern (this, font, buffer); + + if (this->apply_trak) + hb_aat_layout_track (this, font, buffer); +} + static const hb_ot_map_feature_t common_features[] = @@ -168,7 +236,6 @@ horizontal_features[] = static void hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, - const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features) { @@ -177,7 +244,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, map->enable_feature (HB_TAG('r','v','r','n')); map->add_gsub_pause (nullptr); - switch (props->direction) { + switch (planner->props.direction) { case HB_DIRECTION_LTR: map->enable_feature (HB_TAG ('l','t','r','a')); map->enable_feature (HB_TAG ('l','t','r','m')); @@ -216,7 +283,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) map->add_feature (common_features[i]); - if (HB_DIRECTION_IS_HORIZONTAL (props->direction)) + if (HB_DIRECTION_IS_HORIZONTAL (planner->props.direction)) for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++) map->add_feature (horizontal_features[i]); else @@ -256,18 +323,17 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, * shaper face data */ -HB_SHAPER_DATA_ENSURE_DEFINE(ot, face) +struct hb_ot_face_data_t {}; hb_ot_face_data_t * _hb_ot_shaper_face_data_create (hb_face_t *face) { - return _hb_ot_face_data_create (face); + return (hb_ot_face_data_t *) HB_SHAPER_DATA_SUCCEEDED; } void _hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data) { - _hb_ot_face_data_destroy (data); } @@ -275,8 +341,6 @@ _hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data) * shaper font data */ -HB_SHAPER_DATA_ENSURE_DEFINE(ot, font) - struct hb_ot_font_data_t {}; hb_ot_font_data_t * @@ -292,54 +356,6 @@ _hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED) /* - * shaper shape_plan data - */ - -hb_ot_shape_plan_data_t * -_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, - const hb_feature_t *user_features, - unsigned int num_user_features, - const int *coords, - unsigned int num_coords) -{ - hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t)); - if (unlikely (!plan)) - return nullptr; - - plan->init (); - - hb_ot_shape_planner_t planner (shape_plan); - - hb_ot_shape_collect_features (&planner, &shape_plan->props, - user_features, num_user_features); - - planner.compile (*plan, coords, num_coords); - - if (plan->shaper->data_create) { - plan->data = plan->shaper->data_create (plan); - if (unlikely (!plan->data)) - { - free (plan); - return nullptr; - } - } - - return plan; -} - -void -_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shape_plan_data_t *plan) -{ - if (plan->shaper->data_destroy) - plan->shaper->data_destroy (const_cast<void *> (plan->data)); - - plan->fini (); - - free (plan); -} - - -/* * shaper */ @@ -476,7 +492,9 @@ hb_ensure_native_direction (hb_buffer_t *buffer) } -/* Substitute */ +/* + * Substitute + */ static inline void hb_ot_mirror_chars (const hb_ot_shape_context_t *c) @@ -582,10 +600,8 @@ hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c) } static void -hb_ot_zero_width_default_ignorables (const hb_ot_shape_context_t *c) +hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer) { - hb_buffer_t *buffer = c->buffer; - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) || (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) || (buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES)) @@ -601,21 +617,19 @@ hb_ot_zero_width_default_ignorables (const hb_ot_shape_context_t *c) } static void -hb_ot_hide_default_ignorables (const hb_ot_shape_context_t *c) +hb_ot_hide_default_ignorables (hb_buffer_t *buffer, + hb_font_t *font) { - hb_buffer_t *buffer = c->buffer; - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) || (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)) return; unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; - hb_glyph_position_t *pos = buffer->pos; - hb_codepoint_t invisible = c->buffer->invisible; + hb_codepoint_t invisible = buffer->invisible; if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) && - (invisible || c->font->get_nominal_glyph (' ', &invisible))) + (invisible || font->get_nominal_glyph (' ', &invisible))) { /* Replace default-ignorables with a zero-advance invisible glyph. */ for (unsigned int i = 0; i < count; i++) @@ -625,49 +639,7 @@ hb_ot_hide_default_ignorables (const hb_ot_shape_context_t *c) } } else - { - /* Merge clusters and delete default-ignorables. - * NOTE! We can't use out-buffer as we have positioning data. */ - unsigned int j = 0; - for (unsigned int i = 0; i < count; i++) - { - if (_hb_glyph_info_is_default_ignorable (&info[i])) - { - /* Merge clusters. - * Same logic as buffer->delete_glyph(), but for in-place removal. */ - - unsigned int cluster = info[i].cluster; - if (i + 1 < count && cluster == info[i + 1].cluster) - continue; /* Cluster survives; do nothing. */ - - if (j) - { - /* Merge cluster backward. */ - if (cluster < info[j - 1].cluster) - { - unsigned int mask = info[i].mask; - unsigned int old_cluster = info[j - 1].cluster; - for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) - buffer->set_cluster (info[k - 1], cluster, mask); - } - continue; - } - - if (i + 1 < count) - buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */ - - continue; - } - - if (j != i) - { - info[j] = info[i]; - pos[j] = pos[i]; - } - j++; - } - buffer->len = j; - } + hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable); } @@ -684,10 +656,10 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer) } static inline void -hb_synthesize_glyph_classes (const hb_ot_shape_context_t *c) +hb_synthesize_glyph_classes (hb_buffer_t *buffer) { - unsigned int count = c->buffer->len; - hb_glyph_info_t *info = c->buffer->info; + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) { hb_ot_layout_glyph_props_flags_t klass; @@ -739,16 +711,13 @@ hb_ot_substitute_complex (const hb_ot_shape_context_t *c) hb_ot_layout_substitute_start (c->font, buffer); if (c->plan->fallback_glyph_classes) - hb_synthesize_glyph_classes (c); + hb_synthesize_glyph_classes (c->buffer); - if (unlikely (c->plan->apply_morx)) - hb_aat_layout_substitute (c->plan, c->font, c->buffer); - else - c->plan->substitute (c->font, buffer); + c->plan->substitute (c->font, buffer); } static inline void -hb_ot_substitute (const hb_ot_shape_context_t *c) +hb_ot_substitute_pre (const hb_ot_shape_context_t *c) { hb_ot_substitute_default (c); @@ -757,7 +726,21 @@ hb_ot_substitute (const hb_ot_shape_context_t *c) hb_ot_substitute_complex (c); } -/* Position */ +static inline void +hb_ot_substitute_post (const hb_ot_shape_context_t *c) +{ + hb_ot_hide_default_ignorables (c->buffer, c->font); + if (c->plan->apply_morx) + hb_aat_layout_remove_deleted_glyphs (c->buffer); + + if (c->plan->shaper->postprocess_glyphs) + c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); +} + + +/* + * Position + */ static inline void adjust_mark_offsets (hb_glyph_position_t *pos) @@ -852,7 +835,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) hb_ot_layout_position_start (c->font, c->buffer); - if (!c->plan->apply_kerx) + if (c->plan->zero_marks) switch (c->plan->shaper->zero_width_marks) { case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: @@ -865,15 +848,9 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) break; } - if (c->plan->apply_gpos) - c->plan->position (c->font, c->buffer); - else if (c->plan->apply_kerx) - hb_aat_layout_position (c->plan, c->font, c->buffer); - - if (c->plan->apply_trak) - hb_aat_layout_track (c->plan, c->font, c->buffer); + c->plan->position (c->font, c->buffer); - if (!c->plan->apply_kerx) + if (c->plan->zero_marks) switch (c->plan->shaper->zero_width_marks) { case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: @@ -886,9 +863,11 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) break; } - /* Finishing off GPOS has to follow a certain order. */ + /* Finish off. Has to follow a certain order. */ hb_ot_layout_position_finish_advances (c->font, c->buffer); - hb_ot_zero_width_default_ignorables (c); + hb_ot_zero_width_default_ignorables (c->buffer); + if (c->plan->apply_morx) + hb_aat_layout_zero_width_deleted_glyphs (c->buffer); hb_ot_layout_position_finish_offsets (c->font, c->buffer); /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ @@ -897,6 +876,9 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) c->font->subtract_glyph_h_origin (info[i].codepoint, &pos[i].x_offset, &pos[i].y_offset); + + if (c->plan->fallback_mark_positioning && c->plan->shaper->fallback_position) + _hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer); } static inline void @@ -908,19 +890,9 @@ hb_ot_position (const hb_ot_shape_context_t *c) hb_ot_position_complex (c); - if (c->plan->fallback_mark_positioning && c->plan->shaper->fallback_position) - _hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer); - if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) hb_buffer_reverse (c->buffer); - /* Visual fallback goes here. */ - - if (c->plan->apply_kern) - hb_ot_layout_kern (c->plan, c->font, c->buffer); - else if (c->plan->fallback_kerning) - _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); - _hb_buffer_deallocate_gsubgpos_vars (c->buffer); } @@ -986,13 +958,9 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) if (c->plan->shaper->preprocess_text) c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font); - hb_ot_substitute (c); + hb_ot_substitute_pre (c); hb_ot_position (c); - - hb_ot_hide_default_ignorables (c); - - if (c->plan->shaper->postprocess_glyphs) - c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); + hb_ot_substitute_post (c); hb_propagate_flags (c->buffer); @@ -1013,7 +981,7 @@ _hb_ot_shape (hb_shape_plan_t *shape_plan, const hb_feature_t *features, unsigned int num_features) { - hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features}; + hb_ot_shape_context_t c = {&shape_plan->ot, font, font->face, buffer, features, num_features}; hb_ot_shape_internal (&c); return true; @@ -1030,8 +998,7 @@ hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, hb_tag_t table_tag, hb_set_t *lookup_indexes /* OUT */) { - /* XXX Does the first part always succeed? */ - HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes); + shape_plan->ot.collect_lookups (table_tag, lookup_indexes); } |