diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc | 173 |
1 files changed, 161 insertions, 12 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc index a6d2d26210..e354f29176 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc @@ -46,7 +46,7 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, #define HB_SHAPER_PLAN(shaper) \ HB_STMT_START { \ - if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face)) { \ + if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \ HB_SHAPER_DATA (shaper, shape_plan) = \ HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_features, num_user_features); \ shape_plan->shaper_func = _hb_##shaper##_shape; \ @@ -83,6 +83,20 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, * hb_shape_plan_t */ +/** + * hb_shape_plan_create: (Xconstructor) + * @face: + * @props: + * @user_features: (array length=num_user_features): + * @num_user_features: + * @shaper_list: (array zero-terminated=1): + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_shape_plan_t * hb_shape_plan_create (hb_face_t *face, const hb_segment_properties_t *props, @@ -93,24 +107,42 @@ hb_shape_plan_create (hb_face_t *face, assert (props->direction != HB_DIRECTION_INVALID); hb_shape_plan_t *shape_plan; + hb_feature_t *features = NULL; if (unlikely (!face)) face = hb_face_get_empty (); if (unlikely (!props || hb_object_is_inert (face))) return hb_shape_plan_get_empty (); - if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) + if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_features * sizeof (hb_feature_t)))) return hb_shape_plan_get_empty (); + if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) { + free (features); + return hb_shape_plan_get_empty (); + } hb_face_make_immutable (face); shape_plan->default_shaper_list = shaper_list == NULL; - shape_plan->face = hb_face_reference (face); + shape_plan->face_unsafe = face; shape_plan->props = *props; + shape_plan->num_user_features = num_user_features; + shape_plan->user_features = features; + if (num_user_features) + memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); hb_shape_plan_plan (shape_plan, user_features, num_user_features, shaper_list); return shape_plan; } +/** + * hb_shape_plan_get_empty: + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_shape_plan_t * hb_shape_plan_get_empty (void) { @@ -124,6 +156,9 @@ hb_shape_plan_get_empty (void) NULL, /* shaper_func */ NULL, /* shaper_name */ + NULL, /* user_features */ + 0, /* num_user_featurs */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -134,12 +169,30 @@ hb_shape_plan_get_empty (void) return const_cast<hb_shape_plan_t *> (&_hb_shape_plan_nil); } +/** + * hb_shape_plan_reference: (skip) + * @shape_plan: a shape plan. + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_shape_plan_t * hb_shape_plan_reference (hb_shape_plan_t *shape_plan) { return hb_object_reference (shape_plan); } +/** + * hb_shape_plan_destroy: (skip) + * @shape_plan: a shape plan. + * + * + * + * Since: 1.0 + **/ void hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) { @@ -149,11 +202,25 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT - hb_face_destroy (shape_plan->face); + free (shape_plan->user_features); free (shape_plan); } +/** + * hb_shape_plan_set_user_data: (skip) + * @shape_plan: a shape plan. + * @key: + * @data: + * @destroy: + * @replace: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, hb_user_data_key_t *key, @@ -164,6 +231,17 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, return hb_object_set_user_data (shape_plan, key, data, destroy, replace); } +/** + * hb_shape_plan_get_user_data: (skip) + * @shape_plan: a shape plan. + * @key: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ void * hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, hb_user_data_key_t *key) @@ -172,6 +250,20 @@ hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, } +/** + * hb_shape_plan_execute: + * @shape_plan: a shape plan. + * @font: a font. + * @buffer: a buffer. + * @features: (array length=num_features): + * @num_features: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_shape_plan_execute (hb_shape_plan_t *shape_plan, hb_font_t *font, @@ -184,7 +276,7 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, hb_object_is_inert (buffer))) return false; - assert (shape_plan->face == font->face); + assert (shape_plan->face_unsafe == font->face); assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props)); #define HB_SHAPER_EXECUTE(shaper) \ @@ -221,23 +313,69 @@ hb_shape_plan_hash (const hb_shape_plan_t *shape_plan) } #endif -/* TODO no user-feature caching for now. */ +/* User-feature caching is currently somewhat dumb: + * it only finds matches where the feature array is identical, + * not cases where the feature lists would be compatible for plan purposes + * but have different ranges, for example. + */ struct hb_shape_plan_proposal_t { const hb_segment_properties_t props; const char * const *shaper_list; + const hb_feature_t *user_features; + unsigned int num_user_features; hb_shape_func_t *shaper_func; }; +static inline hb_bool_t +hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan, + const hb_shape_plan_proposal_t *proposal) +{ + if (proposal->num_user_features != shape_plan->num_user_features) return false; + for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++) + if (proposal->user_features[i].tag != shape_plan->user_features[i].tag || + proposal->user_features[i].value != shape_plan->user_features[i].value || + proposal->user_features[i].start != shape_plan->user_features[i].start || + proposal->user_features[i].end != shape_plan->user_features[i].end) return false; + return true; +} + static hb_bool_t hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, const hb_shape_plan_proposal_t *proposal) { return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && + hb_shape_plan_user_features_match (shape_plan, proposal) && ((shape_plan->default_shaper_list && proposal->shaper_list == NULL) || (shape_plan->shaper_func == proposal->shaper_func)); } +static inline hb_bool_t +hb_non_global_user_features_present (const hb_feature_t *user_features, + unsigned int num_user_features) +{ + while (num_user_features) + if (user_features->start != 0 || user_features->end != (unsigned int) -1) + return true; + else + num_user_features--, user_features++; + return false; +} + +/** + * hb_shape_plan_create_cached: + * @face: + * @props: + * @user_features: (array length=num_user_features): + * @num_user_features: + * @shaper_list: (array zero-terminated=1): + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_shape_plan_t * hb_shape_plan_create_cached (hb_face_t *face, const hb_segment_properties_t *props, @@ -245,12 +383,11 @@ hb_shape_plan_create_cached (hb_face_t *face, unsigned int num_user_features, const char * const *shaper_list) { - if (num_user_features) - return hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); - hb_shape_plan_proposal_t proposal = { *props, shaper_list, + user_features, + num_user_features, NULL }; @@ -288,6 +425,11 @@ retry: hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); + /* Don't add the plan to the cache if there were user features with non-global ranges */ + + if (hb_non_global_user_features_present (user_features, num_user_features)) + return shape_plan; + hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); if (unlikely (!node)) return shape_plan; @@ -301,12 +443,19 @@ retry: goto retry; } - /* Release our reference on face. */ - hb_face_destroy (face); - return hb_shape_plan_reference (shape_plan); } +/** + * hb_shape_plan_get_shaper: + * @shape_plan: a shape plan. + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ const char * hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) { |