[aat] Allow enabling/disabling features

Only works at entire-buffer range, not sub-ranges.

Test with:

$ hb-shape Zapfino.dfont Zapfino
[Z_a_p_f_i_n_o=0+2333]

$ hb-shape Zapfino.dfont Zapfino --features=-dlig
[Z=0+416|a=1@-21,0+264|p_f=2+433|i=4+181|n=5+261|o=6+250]

$ hb-shape Zapfino.dfont Zapfino --features=+dlig
[Z_a_p_f_i_n_o=0+2333]

Fixes https://github.com/harfbuzz/harfbuzz/issues/1303
This commit is contained in:
Behdad Esfahbod 2018-10-23 14:14:03 -07:00
parent 8be0e5fd45
commit ffe3478448
6 changed files with 47 additions and 4 deletions

View File

@ -101,6 +101,8 @@ HB_OT_sources = \
hb-aat-layout-trak-table.hh \
hb-aat-layout.hh \
hb-aat-ltag-table.hh \
hb-aat-map.cc \
hb-aat-map.hh \
hb-ot-face.hh \
hb-ot-face.cc \
hb-ot-font.cc \

View File

@ -30,6 +30,7 @@
#include "hb-open-type.hh"
#include "hb-aat-layout-common.hh"
#include "hb-ot-layout-common.hh"
#include "hb-aat-map.hh"
/*
* morx -- Extended Glyph Metamorphosis
@ -839,9 +840,9 @@ struct ChainSubtable
struct Chain
{
inline void apply (hb_aat_apply_context_t *c) const
inline hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
{
uint32_t flags = defaultFlags;
hb_mask_t flags = defaultFlags;
{
/* Compute applicable flags. TODO Should move this to planning
* stage and take user-requested features into account. */
@ -849,14 +850,22 @@ struct Chain
for (unsigned i = 0; i < count; i++)
{
const Feature &feature = featureZ[i];
if (false) /* XXX Check if feature enabled... */
uint16_t type = feature.featureType;
uint16_t setting = feature.featureSetting;
const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
if (info && info->setting == setting)
{
flags &= feature.disableFlags;
flags |= feature.enableFlags;
}
}
}
return flags;
}
inline void apply (hb_aat_apply_context_t *c,
hb_mask_t flags) const
{
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount);
unsigned int count = subtableCount;
for (unsigned int i = 0; i < count; i++)
@ -976,6 +985,18 @@ struct morx
inline bool has_data (void) const { return version != 0; }
inline void compile_flags (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map) const
{
const Chain *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
map->chain_flags.push (chain->compile_flags (mapper));
chain = &StructAfter<Chain> (*chain);
}
}
inline void apply (hb_aat_apply_context_t *c) const
{
if (unlikely (!c->buffer->successful)) return;
@ -984,7 +1005,7 @@ struct morx
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
chain->apply (c);
chain->apply (c, c->plan->aat_map.chain_flags[i]);
if (unlikely (!c->buffer->successful)) return;
chain = &StructAfter<Chain> (*chain);
}

View File

@ -183,6 +183,14 @@ _get_trak (hb_face_t *face)
}
void
hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map)
{
_get_morx (mapper->face).compile_flags (mapper, map);
}
hb_bool_t
hb_aat_layout_has_substitution (hb_face_t *face)
{

View File

@ -52,6 +52,9 @@ struct hb_aat_feature_mapping_t
HB_INTERNAL const hb_aat_feature_mapping_t *
hb_aat_layout_find_feature_mapping (hb_tag_t tag);
HB_INTERNAL void
hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map);
HB_INTERNAL hb_bool_t
hb_aat_layout_has_substitution (hb_face_t *face);

View File

@ -57,6 +57,7 @@ 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),
apply_morx (_hb_apply_morx (face)),
shaper (apply_morx ?
&_hb_ot_complex_shaper_default :
@ -70,6 +71,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
plan.props = props;
plan.shaper = shaper;
map.compile (plan.map, coords, num_coords);
aat_map.compile (plan.aat_map, coords, num_coords);
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'));
@ -160,6 +162,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
unsigned int num_user_features)
{
hb_ot_map_builder_t *map = &planner->map;
hb_aat_map_builder_t *aat_map = &planner->aat_map;
map->enable_feature (HB_TAG('r','v','r','n'));
map->add_gsub_pause (nullptr);
@ -225,6 +228,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
(feature->start == HB_FEATURE_GLOBAL_START &&
feature->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE,
feature->value);
aat_map->add_feature (feature->tag, feature->value);
}
}

View File

@ -30,6 +30,7 @@
#include "hb.hh"
#include "hb-ot-map.hh"
#include "hb-aat-map.hh"
#include "hb-shape-plan.hh"
@ -39,6 +40,7 @@ struct hb_ot_shape_plan_t
hb_segment_properties_t props;
const struct hb_ot_complex_shaper_t *shaper;
hb_ot_map_t map;
hb_aat_map_t aat_map;
const void *data;
hb_mask_t frac_mask, numr_mask, dnom_mask;
hb_mask_t rtlm_mask;
@ -77,9 +79,11 @@ struct hb_ot_shape_plan_t
{
memset (this, 0, sizeof (*this));
map.init ();
aat_map.init ();
}
void fini (void) {
map.fini ();
aat_map.fini ();
}
};
@ -89,6 +93,7 @@ struct hb_ot_shape_planner_t
hb_face_t *face;
hb_segment_properties_t props;
hb_ot_map_builder_t map;
hb_aat_map_builder_t aat_map;
bool apply_morx : 1;
const struct hb_ot_complex_shaper_t *shaper;