Apply TrueType/OpenType kern table when GPOS kern feature is not available
Fixes https://github.com/harfbuzz/harfbuzz/issues/250
This commit is contained in:
parent
09ad2613c8
commit
a51958819f
|
@ -37,14 +37,11 @@ struct hb_kern_machine_t
|
||||||
{
|
{
|
||||||
hb_kern_machine_t (const Driver &driver_) : driver (driver_) {}
|
hb_kern_machine_t (const Driver &driver_) : driver (driver_) {}
|
||||||
|
|
||||||
inline void kern (const hb_ot_shape_plan_t *plan,
|
inline void kern (hb_font_t *font,
|
||||||
hb_font_t *font,
|
hb_buffer_t *buffer,
|
||||||
hb_buffer_t *buffer) const
|
hb_mask_t kern_mask) const
|
||||||
{
|
{
|
||||||
if (!plan->kerning_requested) return;
|
|
||||||
|
|
||||||
OT::hb_ot_apply_context_t c (1, font, buffer);
|
OT::hb_ot_apply_context_t c (1, font, buffer);
|
||||||
hb_mask_t kern_mask = plan->kern_mask;
|
|
||||||
c.set_lookup_mask (kern_mask);
|
c.set_lookup_mask (kern_mask);
|
||||||
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
|
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
|
||||||
OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
|
OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
|
||||||
|
@ -411,6 +408,9 @@ struct kern
|
||||||
{
|
{
|
||||||
static const hb_tag_t tableTag = HB_OT_TAG_kern;
|
static const hb_tag_t tableTag = HB_OT_TAG_kern;
|
||||||
|
|
||||||
|
inline bool has_data (void) const
|
||||||
|
{ return u.version32 != 0; }
|
||||||
|
|
||||||
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
|
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
|
||||||
{
|
{
|
||||||
switch (u.major) {
|
switch (u.major) {
|
||||||
|
@ -444,22 +444,25 @@ struct kern
|
||||||
hb_blob_destroy (blob);
|
hb_blob_destroy (blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool has_data (void) const
|
||||||
|
{ return table->has_data (); }
|
||||||
|
|
||||||
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||||
{ return table->get_h_kerning (left, right, table_length); }
|
{ return table->get_h_kerning (left, right, table_length); }
|
||||||
|
|
||||||
inline int get_kerning (hb_codepoint_t first, hb_codepoint_t second) const
|
inline int get_kerning (hb_codepoint_t first, hb_codepoint_t second) const
|
||||||
{ return get_h_kerning (first, second); }
|
{ return get_h_kerning (first, second); }
|
||||||
|
|
||||||
inline void apply (hb_ot_shape_plan_t *plan,
|
inline void apply (hb_font_t *font,
|
||||||
hb_font_t *font,
|
hb_buffer_t *buffer,
|
||||||
hb_buffer_t *buffer) const
|
hb_mask_t kern_mask) const
|
||||||
{
|
{
|
||||||
if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hb_kern_machine_t<accelerator_t> machine (*this);
|
hb_kern_machine_t<accelerator_t> machine (*this);
|
||||||
|
|
||||||
machine.kern (plan, font, buffer);
|
machine.kern (font, buffer, kern_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -471,6 +474,7 @@ struct kern
|
||||||
protected:
|
protected:
|
||||||
union {
|
union {
|
||||||
HBUINT16 major;
|
HBUINT16 major;
|
||||||
|
HBUINT32 version32;
|
||||||
KernOT ot;
|
KernOT ot;
|
||||||
KernAAT aat;
|
KernAAT aat;
|
||||||
} u;
|
} u;
|
||||||
|
|
|
@ -45,17 +45,15 @@
|
||||||
#include "hb-ot-color-cpal-table.hh"
|
#include "hb-ot-color-cpal-table.hh"
|
||||||
#include "hb-ot-color-sbix-table.hh"
|
#include "hb-ot-color-sbix-table.hh"
|
||||||
#include "hb-ot-color-svg-table.hh"
|
#include "hb-ot-color-svg-table.hh"
|
||||||
|
#include "hb-ot-kern-table.hh"
|
||||||
#include "hb-ot-name-table.hh"
|
#include "hb-ot-name-table.hh"
|
||||||
|
|
||||||
|
|
||||||
// static inline const OT::BASE&
|
static const OT::kern::accelerator_t& _get_kern (hb_face_t *face)
|
||||||
// _get_base (hb_face_t *face)
|
{
|
||||||
// {
|
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::kern::accelerator_t);
|
||||||
// if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::BASE);
|
return *hb_ot_face_data (face)->kern;
|
||||||
// hb_ot_face_data_t *data = hb_ot_face_data (face);
|
}
|
||||||
// return *(data->base.get ());
|
|
||||||
// }
|
|
||||||
|
|
||||||
const OT::GDEF& _get_gdef (hb_face_t *face)
|
const OT::GDEF& _get_gdef (hb_face_t *face)
|
||||||
{
|
{
|
||||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
|
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
|
||||||
|
@ -91,6 +89,25 @@ const OT::GPOS& _get_gpos_relaxed (hb_face_t *face)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kern
|
||||||
|
*/
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_has_kerning (hb_face_t *face)
|
||||||
|
{
|
||||||
|
return _get_kern (face).has_data ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ot_layout_kern (hb_font_t *font,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
hb_mask_t kern_mask)
|
||||||
|
{
|
||||||
|
_get_kern (font->face).apply (font, buffer, kern_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GDEF
|
* GDEF
|
||||||
*/
|
*/
|
||||||
|
@ -1306,27 +1323,3 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
|
||||||
{
|
{
|
||||||
apply_string<GSUBProxy> (c, lookup, accel);
|
apply_string<GSUBProxy> (c, lookup, accel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OT::BASE
|
|
||||||
*/
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * hb_ot_base_has_data:
|
|
||||||
// * @face: #hb_face_t to test
|
|
||||||
// *
|
|
||||||
// * This function allows to verify the presence of an OpenType BASE table on the
|
|
||||||
// * face.
|
|
||||||
// *
|
|
||||||
// * Return value: true if face has a BASE table, false otherwise
|
|
||||||
// *
|
|
||||||
// * Since: XXX
|
|
||||||
// **/
|
|
||||||
// hb_bool_t
|
|
||||||
// hb_ot_base_has_data (hb_face_t *face)
|
|
||||||
// {
|
|
||||||
// return _get_base (face).has_data ();
|
|
||||||
// }
|
|
||||||
|
|
|
@ -49,6 +49,19 @@ HB_INTERNAL const OT::GSUB& _get_gsub_relaxed (hb_face_t *face);
|
||||||
HB_INTERNAL const OT::GPOS& _get_gpos_relaxed (hb_face_t *face);
|
HB_INTERNAL const OT::GPOS& _get_gpos_relaxed (hb_face_t *face);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kern
|
||||||
|
*/
|
||||||
|
|
||||||
|
HB_INTERNAL hb_bool_t
|
||||||
|
hb_ot_layout_has_kerning (hb_face_t *face);
|
||||||
|
|
||||||
|
HB_INTERNAL void
|
||||||
|
hb_ot_layout_kern (hb_font_t *font,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
hb_mask_t kern_mask);
|
||||||
|
|
||||||
|
|
||||||
/* Private API corresponding to hb-ot-layout.h: */
|
/* Private API corresponding to hb-ot-layout.h: */
|
||||||
|
|
||||||
HB_INTERNAL hb_bool_t
|
HB_INTERNAL hb_bool_t
|
||||||
|
|
|
@ -439,7 +439,7 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
|
||||||
void
|
void
|
||||||
_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
|
_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
|
||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
hb_buffer_t *buffer)
|
hb_buffer_t *buffer)
|
||||||
{
|
{
|
||||||
struct driver_t
|
struct driver_t
|
||||||
{
|
{
|
||||||
|
@ -462,7 +462,7 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
|
||||||
|
|
||||||
hb_kern_machine_t<driver_t> machine (driver);
|
hb_kern_machine_t<driver_t> machine (driver);
|
||||||
|
|
||||||
machine.kern (plan, font, buffer);
|
machine.kern (font, buffer, plan->kern_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,8 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
|
||||||
bool disable_gpos = plan.shaper->gpos_tag &&
|
bool disable_gpos = plan.shaper->gpos_tag &&
|
||||||
plan.shaper->gpos_tag != plan.map.chosen_script[1];
|
plan.shaper->gpos_tag != plan.map.chosen_script[1];
|
||||||
plan.apply_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
|
plan.apply_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
|
||||||
|
plan.apply_kern = !plan.apply_gpos && hb_ot_layout_has_kerning (face);
|
||||||
plan.fallback_kerning = !plan.apply_gpos;
|
plan.fallback_kerning = !plan.apply_gpos && !plan.apply_kern;
|
||||||
plan.fallback_mark_positioning = !plan.apply_gpos;
|
plan.fallback_mark_positioning = !plan.apply_gpos;
|
||||||
plan.fallback_glyph_classes = !hb_ot_layout_has_glyph_classes (face);
|
plan.fallback_glyph_classes = !hb_ot_layout_has_glyph_classes (face);
|
||||||
}
|
}
|
||||||
|
@ -835,7 +835,11 @@ hb_ot_position (const hb_ot_shape_context_t *c)
|
||||||
|
|
||||||
/* Visual fallback goes here. */
|
/* Visual fallback goes here. */
|
||||||
|
|
||||||
if (c->plan->fallback_kerning)
|
if (!c->plan->kerning_requested)
|
||||||
|
;
|
||||||
|
else if (c->plan->apply_kern)
|
||||||
|
hb_ot_layout_kern (c->font, c->buffer, c->plan->kern_mask);
|
||||||
|
else if (c->plan->fallback_kerning)
|
||||||
_hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
|
_hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
|
||||||
|
|
||||||
_hb_buffer_deallocate_gsubgpos_vars (c->buffer);
|
_hb_buffer_deallocate_gsubgpos_vars (c->buffer);
|
||||||
|
|
|
@ -51,6 +51,7 @@ struct hb_ot_shape_plan_t
|
||||||
bool fallback_mark_positioning : 1;
|
bool fallback_mark_positioning : 1;
|
||||||
|
|
||||||
bool apply_morx : 1;
|
bool apply_morx : 1;
|
||||||
|
bool apply_kern : 1;
|
||||||
bool apply_gpos : 1;
|
bool apply_gpos : 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue