[GX] Hook up feature variations

Shape-plan caching is not implemented.
This commit is contained in:
Behdad Esfahbod 2016-09-10 03:57:24 -07:00
parent ec87ba9ba3
commit 72ada4f0c6
14 changed files with 183 additions and 41 deletions

View File

@ -288,7 +288,9 @@ struct hb_coretext_shaper_shape_plan_data_t {};
hb_coretext_shaper_shape_plan_data_t *
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED)
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
@ -1280,7 +1282,9 @@ struct hb_coretext_aat_shaper_shape_plan_data_t {};
hb_coretext_aat_shaper_shape_plan_data_t *
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED)
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}

View File

@ -258,8 +258,10 @@ struct hb_directwrite_shaper_shape_plan_data_t {};
hb_directwrite_shaper_shape_plan_data_t *
_hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED)
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}

View File

@ -73,7 +73,9 @@ struct hb_fallback_shaper_shape_plan_data_t {};
hb_fallback_shaper_shape_plan_data_t *
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED)
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}

View File

@ -1253,8 +1253,7 @@ hb_font_destroy (hb_font_t *font)
hb_face_destroy (font->face);
hb_font_funcs_destroy (font->klass);
if (font->coords)
free (font->coords);
free (font->coords);
free (font);
}
@ -1561,8 +1560,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
if (unlikely (coords_length && !copy))
return;
if (font->coords)
free (font->coords);
free (font->coords);
if (coords_length)
memcpy (copy, coords, coords_length * sizeof (coords[0]));

View File

@ -195,7 +195,9 @@ struct hb_graphite2_shaper_shape_plan_data_t {};
hb_graphite2_shaper_shape_plan_data_t *
_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED)
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}

View File

@ -176,7 +176,9 @@ struct hb_ot_map_builder_t
inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
{ add_pause (1, pause_func); }
HB_INTERNAL void compile (hb_ot_map_t &m);
HB_INTERNAL void compile (hb_ot_map_t &m,
const int *coords,
unsigned int num_coords);
inline void finish (void) {
feature_infos.finish ();
@ -188,12 +190,13 @@ struct hb_ot_map_builder_t
private:
HB_INTERNAL void add_lookups (hb_ot_map_t &m,
hb_face_t *face,
unsigned int table_index,
unsigned int feature_index,
hb_mask_t mask,
bool auto_zwj);
HB_INTERNAL void add_lookups (hb_ot_map_t &m,
hb_face_t *face,
unsigned int table_index,
unsigned int feature_index,
unsigned int variations_index,
hb_mask_t mask,
bool auto_zwj);
struct feature_info_t {
hb_tag_t tag;

View File

@ -83,6 +83,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
hb_face_t *face,
unsigned int table_index,
unsigned int feature_index,
unsigned int variations_index,
hb_mask_t mask,
bool auto_zwj)
{
@ -95,11 +96,12 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
offset = 0;
do {
len = ARRAY_LENGTH (lookup_indices);
hb_ot_layout_feature_get_lookups (face,
table_tags[table_index],
feature_index,
offset, &len,
lookup_indices);
hb_ot_layout_feature_with_variations_get_lookups (face,
table_tags[table_index],
feature_index,
variations_index,
offset, &len,
lookup_indices);
for (unsigned int i = 0; i < len; i++)
{
@ -130,7 +132,9 @@ void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus
}
void
hb_ot_map_builder_t::compile (hb_ot_map_t &m)
hb_ot_map_builder_t::compile (hb_ot_map_t &m,
const int *coords,
unsigned int num_coords)
{
m.global_mask = 1;
@ -264,6 +268,13 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
{
/* Collect lookup indices for features */
unsigned int variations_index;
hb_ot_layout_table_find_feature_variations (face,
table_tags[table_index],
coords,
num_coords,
&variations_index);
unsigned int stage_index = 0;
unsigned int last_num_lookups = 0;
for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
@ -272,6 +283,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
required_feature_stage[table_index] == stage)
add_lookups (m, face, table_index,
required_feature_index[table_index],
variations_index,
1 /* mask */,
true /* auto_zwj */);
@ -279,6 +291,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
if (m.features[i].stage[table_index] == stage)
add_lookups (m, face, table_index,
m.features[i].index[table_index],
variations_index,
m.features[i].mask,
m.features[i].auto_zwj);

View File

@ -77,11 +77,13 @@ struct hb_ot_shape_planner_t
map (face, &props) {}
~hb_ot_shape_planner_t (void) { map.finish (); }
inline void compile (hb_ot_shape_plan_t &plan)
inline void compile (hb_ot_shape_plan_t &plan,
const int *coords,
unsigned int num_coords)
{
plan.props = props;
plan.shaper = shaper;
map.compile (plan.map);
map.compile (plan.map, coords, num_coords);
plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));

View File

@ -163,7 +163,9 @@ _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
hb_ot_shaper_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)
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))
@ -173,9 +175,10 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
planner.shaper = hb_ot_shape_complex_categorize (&planner);
hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features);
hb_ot_shape_collect_features (&planner, &shape_plan->props,
user_features, num_user_features);
planner.compile (*plan);
planner.compile (*plan, coords, num_coords);
if (plan->shaper->data_create) {
plan->data = plan->shaper->data_create (plan);

View File

@ -47,12 +47,17 @@ struct hb_shape_plan_t
hb_feature_t *user_features;
unsigned int num_user_features;
int *coords;
unsigned int num_coords;
struct hb_shaper_data_t shaper_data;
};
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
, const hb_feature_t *user_features \
, unsigned int num_user_features
, const hb_feature_t *user_features \
, unsigned int num_user_features \
, const int *coords \
, unsigned int num_coords
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan);
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT

View File

@ -46,11 +46,14 @@ 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)
{
DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
"num_features=%d shaper_list=%p",
"num_features=%d num_coords=%d shaper_list=%p",
num_user_features,
num_coords,
shaper_list);
const hb_shaper_pair_t *shapers = _hb_shapers_get ();
@ -59,7 +62,9 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan,
HB_STMT_START { \
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); \
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; \
@ -114,15 +119,32 @@ hb_shape_plan_create (hb_face_t *face,
const hb_feature_t *user_features,
unsigned int num_user_features,
const char * const *shaper_list)
{
return hb_shape_plan_create2 (face, props,
user_features, num_user_features,
NULL, 0,
shaper_list);
}
hb_shape_plan_t *
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,
unsigned int num_coords,
const char * const *shaper_list)
{
DEBUG_MSG_FUNC (SHAPE_PLAN, NULL,
"face=%p num_features=%d shaper_list=%p",
"face=%p num_features=%d num_coords=%d shaper_list=%p",
face,
num_user_features,
num_coords,
shaper_list);
hb_shape_plan_t *shape_plan;
hb_feature_t *features = NULL;
int *coords = NULL;
if (unlikely (!face))
face = hb_face_get_empty ();
@ -130,7 +152,14 @@ hb_shape_plan_create (hb_face_t *face,
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 (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) {
if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
{
free (features);
return hb_shape_plan_get_empty ();
}
if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
{
free (coords);
free (features);
return hb_shape_plan_get_empty ();
}
@ -145,8 +174,15 @@ hb_shape_plan_create (hb_face_t *face,
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, shaper_list);
hb_shape_plan_plan (shape_plan,
user_features, num_user_features,
coords, num_coords,
shaper_list);
return shape_plan;
}
@ -176,6 +212,9 @@ hb_shape_plan_get_empty (void)
NULL, /* user_features */
0, /* num_user_featurs */
NULL, /* coords */
0, /* num_coords */
{
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
#include "hb-shaper-list.hh"
@ -220,6 +259,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
#undef HB_SHAPER_IMPLEMENT
free (shape_plan->user_features);
free (shape_plan->coords);
free (shape_plan);
}
@ -351,6 +391,8 @@ struct hb_shape_plan_proposal_t
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;
};
@ -358,12 +400,26 @@ 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;
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;
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;
}
@ -373,6 +429,7 @@ hb_shape_plan_matches (const hb_shape_plan_t *shape_plan,
{
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 == NULL) ||
(shape_plan->shaper_func == proposal->shaper_func));
}
@ -389,6 +446,13 @@ hb_non_global_user_features_present (const hb_feature_t *user_features,
return false;
}
static inline hb_bool_t
hb_coords_present (const int *coords,
unsigned int num_coords)
{
return num_coords != 0;
}
/**
* hb_shape_plan_create_cached:
* @face:
@ -409,6 +473,21 @@ hb_shape_plan_create_cached (hb_face_t *face,
const hb_feature_t *user_features,
unsigned int num_user_features,
const char * const *shaper_list)
{
return hb_shape_plan_create_cached2 (face, props,
user_features, num_user_features,
NULL, 0,
shaper_list);
}
hb_shape_plan_t *
hb_shape_plan_create_cached2 (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, NULL,
"face=%p num_features=%d shaper_list=%p",
@ -456,16 +535,21 @@ retry:
/* Not found. */
hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list);
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))
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))

View File

@ -52,6 +52,25 @@ hb_shape_plan_create_cached (hb_face_t *face,
unsigned int num_user_features,
const char * const *shaper_list);
HB_EXTERN hb_shape_plan_t *
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 *coords,
unsigned int num_coords,
const char * const *shaper_list);
HB_EXTERN hb_shape_plan_t *
hb_shape_plan_create_cached2 (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);
HB_EXTERN hb_shape_plan_t *
hb_shape_plan_get_empty (void);

View File

@ -373,7 +373,10 @@ hb_shape_full (hb_font_t *font,
unsigned int num_features,
const char * const *shaper_list)
{
hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
features, num_features,
font->coords, font->num_coords,
shaper_list);
hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
hb_shape_plan_destroy (shape_plan);

View File

@ -587,7 +587,9 @@ struct hb_uniscribe_shaper_shape_plan_data_t {};
hb_uniscribe_shaper_shape_plan_data_t *
_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
unsigned int num_user_features HB_UNUSED)
unsigned int num_user_features HB_UNUSED,
const int *coords HB_UNUSED,
unsigned int num_coords HB_UNUSED)
{
return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}