summaryrefslogtreecommitdiff
path: root/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc')
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc392
1 files changed, 150 insertions, 242 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
index f2f21019690..bc3d81636b9 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-shape-plan.cc
@@ -44,88 +44,118 @@
**/
-static void
-hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
- const hb_feature_t *user_features,
- unsigned int num_user_features,
- const int *coords,
- unsigned int num_coords,
- const char * const *shaper_list)
+/*
+ * hb_shape_plan_key_t
+ */
+
+bool
+hb_shape_plan_key_t::init (bool copy,
+ hb_face_t *face,
+ const hb_segment_properties_t *props,
+ const hb_feature_t *user_features,
+ unsigned int num_user_features,
+ const int *coords,
+ unsigned int num_coords,
+ const char * const *shaper_list)
{
- DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
- "num_features=%d num_coords=%d shaper_list=%p",
- num_user_features,
- num_coords,
- shaper_list);
+ hb_feature_t *features = nullptr;
+ if (copy && num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
+ goto bail;
+
+ this->props = *props;
+ this->num_user_features = num_user_features;
+ this->user_features = copy ? features : user_features;
+ if (copy && num_user_features)
+ {
+ memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+ /* Make start/end uniform to easier catch bugs. */
+ for (unsigned int i = 0; i < num_user_features; i++)
+ {
+ if (features[0].start != HB_FEATURE_GLOBAL_START)
+ features[0].start = 1;
+ if (features[0].end != HB_FEATURE_GLOBAL_END)
+ features[0].end = 2;
+ }
+ }
+ this->shaper_func = nullptr;
+ this->shaper_name = nullptr;
+ this->ot.init (face, coords, num_coords);
- const hb_shaper_pair_t *shapers = _hb_shapers_get ();
+ /*
+ * Choose shaper.
+ */
#define HB_SHAPER_PLAN(shaper) \
HB_STMT_START { \
- if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) \
+ if (face->data.shaper) \
{ \
- /* XXX-MT-bug What happened to *ensure*ing this?!!!! */ \
- HB_SHAPER_DATA (shaper, shape_plan).set_relaxed ( \
- HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \
- user_features, num_user_features, \
- coords, num_coords)); \
- shape_plan->shaper_func = _hb_##shaper##_shape; \
- shape_plan->shaper_name = #shaper; \
- return; \
+ this->shaper_func = _hb_##shaper##_shape; \
+ this->shaper_name = #shaper; \
+ return true; \
} \
} HB_STMT_END
- if (likely (!shaper_list)) {
- for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
+ if (unlikely (shaper_list))
+ {
+ for (; *shaper_list; shaper_list++)
if (false)
;
#define HB_SHAPER_IMPLEMENT(shaper) \
- else if (shapers[i].func == _hb_##shaper##_shape) \
+ else if (0 == strcmp (*shaper_list, #shaper)) \
HB_SHAPER_PLAN (shaper);
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
- } else {
- for (; *shaper_list; shaper_list++)
+ }
+ else
+ {
+ const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+ for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
if (false)
;
#define HB_SHAPER_IMPLEMENT(shaper) \
- else if (0 == strcmp (*shaper_list, #shaper)) \
+ else if (shapers[i].func == _hb_##shaper##_shape) \
HB_SHAPER_PLAN (shaper);
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
}
-
#undef HB_SHAPER_PLAN
-}
+bail:
+ ::free (features);
+ return false;
+}
-/*
- * hb_shape_plan_t
- */
-
-DEFINE_NULL_INSTANCE (hb_shape_plan_t) =
+bool
+hb_shape_plan_key_t::user_features_match (const hb_shape_plan_key_t *other)
{
- HB_OBJECT_HEADER_STATIC,
-
- true, /* default_shaper_list */
- nullptr, /* face */
- HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
-
- nullptr, /* shaper_func */
- nullptr, /* shaper_name */
+ if (this->num_user_features != other->num_user_features)
+ return false;
+ for (unsigned int i = 0; i < num_user_features; i++)
+ {
+ if (this->user_features[i].tag != other->user_features[i].tag ||
+ this->user_features[i].value != other->user_features[i].value ||
+ (this->user_features[i].start == HB_FEATURE_GLOBAL_START &&
+ this->user_features[i].end == HB_FEATURE_GLOBAL_END) !=
+ (other->user_features[i].start == HB_FEATURE_GLOBAL_START &&
+ other->user_features[i].end == HB_FEATURE_GLOBAL_END))
+ return false;
+ }
+ return true;
+}
- nullptr, /* user_features */
- 0, /* num_user_featurs */
+bool
+hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other)
+{
+ return hb_segment_properties_equal (&this->props, &other->props) &&
+ this->user_features_match (other) &&
+ this->ot.equal (&other->ot) &&
+ this->shaper_func == other->shaper_func;
+}
- nullptr, /* coords */
- 0, /* num_coords */
- {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_ATOMIC_PTR_INIT (HB_SHAPER_DATA_INVALID),
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
- },
-};
+/*
+ * hb_shape_plan_t
+ */
/**
@@ -160,7 +190,7 @@ hb_shape_plan_create2 (hb_face_t *face,
const hb_segment_properties_t *props,
const hb_feature_t *user_features,
unsigned int num_user_features,
- const int *orig_coords,
+ const int *coords,
unsigned int num_coords,
const char * const *shaper_list)
{
@@ -171,49 +201,40 @@ hb_shape_plan_create2 (hb_face_t *face,
num_coords,
shaper_list);
+ assert (props->direction != HB_DIRECTION_INVALID);
+
hb_shape_plan_t *shape_plan;
- hb_feature_t *features = nullptr;
- int *coords = nullptr;
- if (unlikely (!face))
- face = hb_face_get_empty ();
if (unlikely (!props))
- return hb_shape_plan_get_empty ();
- if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
- return hb_shape_plan_get_empty ();
- if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
- {
- free (features);
- return hb_shape_plan_get_empty ();
- }
+ goto bail;
if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
- {
- free (coords);
- free (features);
- return hb_shape_plan_get_empty ();
- }
-
- assert (props->direction != HB_DIRECTION_INVALID);
+ goto bail;
+ if (unlikely (!face))
+ face = hb_face_get_empty ();
hb_face_make_immutable (face);
- shape_plan->default_shaper_list = !shaper_list;
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));
- shape_plan->num_coords = num_coords;
- shape_plan->coords = coords;
- if (num_coords)
- memcpy (coords, orig_coords, num_coords * sizeof (int));
- hb_shape_plan_plan (shape_plan,
- user_features, num_user_features,
- coords, num_coords,
- shaper_list);
+ if (unlikely (!shape_plan->key.init (true,
+ face,
+ props,
+ user_features,
+ num_user_features,
+ coords,
+ num_coords,
+ shaper_list)))
+ goto bail2;
+ if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key)))
+ goto bail3;
return shape_plan;
+
+bail3:
+ shape_plan->key.free ();
+bail2:
+ free (shape_plan);
+bail:
+ return hb_shape_plan_get_empty ();
}
/**
@@ -260,13 +281,8 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
{
if (!hb_object_destroy (shape_plan)) return;
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
- free (shape_plan->user_features);
- free (shape_plan->coords);
-
+ shape_plan->ot.fini ();
+ shape_plan->key.free ();
free (shape_plan);
}
@@ -312,6 +328,22 @@ hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
return hb_object_get_user_data (shape_plan, key);
}
+/**
+ * hb_shape_plan_get_shaper:
+ * @shape_plan: a shape plan.
+ *
+ *
+ *
+ * Return value: (transfer none):
+ *
+ * Since: 0.9.7
+ **/
+const char *
+hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
+{
+ return shape_plan->key.shaper_name;
+}
+
/**
* hb_shape_plan_execute:
@@ -337,8 +369,8 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan,
DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
"num_features=%d shaper_func=%p, shaper_name=%s",
num_features,
- shape_plan->shaper_func,
- shape_plan->shaper_name);
+ shape_plan->key.shaper_func,
+ shape_plan->key.shaper_name);
if (unlikely (!buffer->len))
return true;
@@ -350,19 +382,18 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan,
return false;
assert (shape_plan->face_unsafe == font->face);
- assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props));
+ assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props));
#define HB_SHAPER_EXECUTE(shaper) \
HB_STMT_START { \
- return HB_SHAPER_DATA (shaper, shape_plan).get () && \
- hb_##shaper##_shaper_font_data_ensure (font) && \
+ return font->data.shaper && \
_hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
} HB_STMT_END
if (false)
;
#define HB_SHAPER_IMPLEMENT(shaper) \
- else if (shape_plan->shaper_func == _hb_##shaper##_shape) \
+ else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \
HB_SHAPER_EXECUTE (shaper);
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
@@ -374,92 +405,9 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan,
/*
- * caching
+ * Caching
*/
-#if 0
-static unsigned int
-hb_shape_plan_hash (const hb_shape_plan_t *shape_plan)
-{
- return hb_segment_properties_hash (&shape_plan->props) +
- shape_plan->default_shaper_list ? 0 : (intptr_t) shape_plan->shaper_func;
-}
-#endif
-
-/* 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;
- const int *coords;
- unsigned int num_coords;
- 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 inline hb_bool_t
-hb_shape_plan_coords_match (const hb_shape_plan_t *shape_plan,
- const hb_shape_plan_proposal_t *proposal)
-{
- if (proposal->num_coords != shape_plan->num_coords)
- return false;
- for (unsigned int i = 0, n = proposal->num_coords; i < n; i++)
- if (proposal->coords[i] != shape_plan->coords[i])
- 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) &&
- hb_shape_plan_coords_match (shape_plan, proposal) &&
- ((shape_plan->default_shaper_list && !proposal->shaper_list) ||
- (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;
- num_user_features--;
- user_features++;
- }
- return false;
-}
-
-static inline hb_bool_t
-hb_coords_present (const int *coords HB_UNUSED,
- unsigned int num_coords)
-{
- return num_coords != 0;
-}
-
/**
* hb_shape_plan_create_cached:
* @face:
@@ -502,62 +450,38 @@ hb_shape_plan_create_cached2 (hb_face_t *face,
num_user_features,
shaper_list);
- hb_shape_plan_proposal_t proposal = {
- *props,
- shaper_list,
- user_features,
- num_user_features,
- nullptr
- };
-
- if (shaper_list) {
- /* Choose shaper. Adapted from hb_shape_plan_plan().
- * Must choose shaper exactly the same way as that function. */
- for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
- if (false)
- ;
-#define HB_SHAPER_IMPLEMENT(shaper) \
- else if (0 == strcmp (*shaper_item, #shaper) && \
- hb_##shaper##_shaper_face_data_ensure (face)) \
- { \
- proposal.shaper_func = _hb_##shaper##_shape; \
- break; \
- }
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
- if (unlikely (!proposal.shaper_func))
- return hb_shape_plan_get_empty ();
- }
-
-
retry:
hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
- /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */
- if (!hb_coords_present (coords, num_coords))
+ bool dont_cache = hb_object_is_inert (face);
+
+ if (likely (!dont_cache))
+ {
+ hb_shape_plan_key_t key;
+ if (!key.init (false,
+ face,
+ props,
+ user_features,
+ num_user_features,
+ coords,
+ num_coords,
+ shaper_list))
+ return hb_shape_plan_get_empty ();
+
for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
- if (hb_shape_plan_matches (node->shape_plan, &proposal))
+ if (node->shape_plan->key.equal (&key))
{
DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
return hb_shape_plan_reference (node->shape_plan);
}
+ }
- /* Not found. */
hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props,
user_features, num_user_features,
coords, num_coords,
shaper_list);
- /* Don't add to the cache if face is inert. */
- if (unlikely (hb_object_is_inert (face)))
- return shape_plan;
-
- /* 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;
- /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */
- if (hb_coords_present (coords, num_coords))
+ if (unlikely (dont_cache))
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));
@@ -577,19 +501,3 @@ retry:
return hb_shape_plan_reference (shape_plan);
}
-
-/**
- * hb_shape_plan_get_shaper:
- * @shape_plan: a shape plan.
- *
- *
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.7
- **/
-const char *
-hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
-{
- return shape_plan->shaper_name;
-}