提交 385f78b3 编写于 作者: B Behdad Esfahbod

[aat] Remove deleted-glyhs after applying kerx/kern

Finally:  Fixes https://github.com/harfbuzz/harfbuzz/issues/1356

Test case:
$ ./hb-shape GeezaPro.ttc -u U+0628,U+064A,U+064E,U+0651,U+0629
[u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]

The mark positioning (kern table CrossStream kerning) only works if deleted
glyph (as result of ligation) is still in stream and pushed through the
state machine.
上级 19090722
......@@ -1106,21 +1106,6 @@ struct mortmorx
}
}
inline static void remove_deleted_glyphs (hb_buffer_t *buffer)
{
if (unlikely (!buffer->successful)) return;
buffer->clear_output ();
for (buffer->idx = 0; buffer->idx < buffer->len && buffer->successful;)
{
if (unlikely (buffer->cur().codepoint == DELETED_GLYPH))
buffer->skip_glyph ();
else
buffer->next_glyph ();
}
buffer->swap_buffers ();
}
inline void apply (hb_aat_apply_context_t *c) const
{
if (unlikely (!c->buffer->successful)) return;
......@@ -1133,7 +1118,6 @@ struct mortmorx
if (unlikely (!c->buffer->successful)) return;
chain = &StructAfter<Chain<Types> > (*chain);
}
remove_deleted_glyphs (c->buffer);
}
inline bool sanitize (hb_sanitize_context_t *c) const
......
......@@ -193,7 +193,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
}
hb_bool_t
bool
hb_aat_layout_has_substitution (hb_face_t *face)
{
return face->table.morx->has_data () ||
......@@ -224,8 +224,32 @@ hb_aat_layout_substitute (hb_ot_shape_plan_t *plan,
}
}
void
hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos;
for (unsigned int i = 0; i < count; i++)
if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
pos[i].x_advance = pos[i].y_advance = 0;
}
static bool
is_deleted_glyph (const hb_glyph_info_t *info)
{
return info->codepoint == AAT::DELETED_GLYPH;
}
void
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
{
hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
}
hb_bool_t
bool
hb_aat_layout_has_positioning (hb_face_t *face)
{
return face->table.kerx->has_data ();
......@@ -248,7 +272,7 @@ hb_aat_layout_position (hb_ot_shape_plan_t *plan,
}
hb_bool_t
bool
hb_aat_layout_has_tracking (hb_face_t *face)
{
return face->table.trak->has_data ();
......
......@@ -56,7 +56,7 @@ 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_INTERNAL bool
hb_aat_layout_has_substitution (hb_face_t *face);
HB_INTERNAL void
......@@ -64,7 +64,13 @@ hb_aat_layout_substitute (hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
HB_INTERNAL hb_bool_t
HB_INTERNAL void
hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
HB_INTERNAL void
hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer);
HB_INTERNAL bool
hb_aat_layout_has_positioning (hb_face_t *face);
HB_INTERNAL void
......@@ -72,7 +78,7 @@ hb_aat_layout_position (hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
HB_INTERNAL hb_bool_t
HB_INTERNAL bool
hb_aat_layout_has_tracking (hb_face_t *face);
HB_INTERNAL void
......
......@@ -113,7 +113,7 @@ struct ValueFormat : HBUINT16
if (!format) return ret;
hb_font_t *font = c->font;
hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
......@@ -271,10 +271,10 @@ struct AnchorFormat2
unsigned int x_ppem = font->x_ppem;
unsigned int y_ppem = font->y_ppem;
hb_position_t cx = 0, cy = 0;
hb_bool_t ret;
bool ret;
ret = (x_ppem || y_ppem) &&
font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
*x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
*y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
}
......
......@@ -57,13 +57,13 @@
* kern
*/
hb_bool_t
bool
hb_ot_layout_has_kerning (hb_face_t *face)
{
return face->table.kern->has_data ();
}
hb_bool_t
bool
hb_ot_layout_has_cross_kerning (hb_face_t *face)
{
return face->table.kern->has_cross_stream ();
......@@ -423,7 +423,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
return g.get_feature_tags (start_offset, feature_count, feature_tags);
}
hb_bool_t
bool
hb_ot_layout_table_find_feature (hb_face_t *face,
hb_tag_t table_tag,
hb_tag_t feature_tag,
......@@ -933,12 +933,12 @@ hb_ot_layout_lookup_would_substitute (hb_face_t *face,
zero_context);
}
hb_bool_t
bool
hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
unsigned int lookup_index,
const hb_codepoint_t *glyphs,
unsigned int glyphs_length,
hb_bool_t zero_context)
bool zero_context)
{
if (unlikely (lookup_index >= face->table.GSUB->lookup_count)) return false;
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
......@@ -955,6 +955,56 @@ hb_ot_layout_substitute_start (hb_font_t *font,
_hb_ot_layout_set_glyph_props (font, buffer);
}
void
hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
bool (*filter) (const hb_glyph_info_t *info))
{
/* Merge clusters and delete filtered glyphs.
* NOTE! We can't use out-buffer as we have positioning data. */
unsigned int j = 0;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos;
for (unsigned int i = 0; i < count; i++)
{
if (filter (&info[i]))
{
/* Merge clusters.
* Same logic as buffer->delete_glyph(), but for in-place removal. */
unsigned int cluster = info[i].cluster;
if (i + 1 < count && cluster == info[i + 1].cluster)
continue; /* Cluster survives; do nothing. */
if (j)
{
/* Merge cluster backward. */
if (cluster < info[j - 1].cluster)
{
unsigned int mask = info[i].mask;
unsigned int old_cluster = info[j - 1].cluster;
for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
buffer->set_cluster (info[k - 1], cluster, mask);
}
continue;
}
if (i + 1 < count)
buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
continue;
}
if (j != i)
{
info[j] = info[i];
pos[j] = pos[i];
}
j++;
}
buffer->len = j;
}
/**
* hb_ot_layout_lookup_substitute_closure:
*
......
......@@ -45,10 +45,10 @@ struct hb_ot_shape_plan_t;
* kern
*/
HB_INTERNAL hb_bool_t
HB_INTERNAL bool
hb_ot_layout_has_kerning (hb_face_t *face);
HB_INTERNAL hb_bool_t
HB_INTERNAL bool
hb_ot_layout_has_cross_kerning (hb_face_t *face);
HB_INTERNAL void
......@@ -59,7 +59,7 @@ hb_ot_layout_kern (hb_ot_shape_plan_t *plan,
/* Private API corresponding to hb-ot-layout.h: */
HB_INTERNAL hb_bool_t
HB_INTERNAL bool
hb_ot_layout_table_find_feature (hb_face_t *face,
hb_tag_t table_tag,
hb_tag_t feature_tag,
......@@ -93,12 +93,12 @@ HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
* GSUB/GPOS
*/
HB_INTERNAL hb_bool_t
HB_INTERNAL bool
hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
unsigned int lookup_index,
const hb_codepoint_t *glyphs,
unsigned int glyphs_length,
hb_bool_t zero_context);
bool zero_context);
/* Should be called before all the substitute_lookup's are done. */
......@@ -106,6 +106,9 @@ HB_INTERNAL void
hb_ot_layout_substitute_start (hb_font_t *font,
hb_buffer_t *buffer);
HB_INTERNAL void
hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
bool (*filter) (const hb_glyph_info_t *info));
namespace OT {
struct hb_ot_apply_context_t;
......@@ -306,13 +309,13 @@ _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
static inline hb_bool_t
static inline bool
_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
{
return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
!_hb_glyph_info_ligated (info);
}
static inline hb_bool_t
static inline bool
_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
{
return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
......@@ -366,17 +369,17 @@ _hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
return _hb_glyph_info_get_general_category (info) ==
HB_UNICODE_GENERAL_CATEGORY_FORMAT;
}
static inline hb_bool_t
static inline bool
_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
{
return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
}
static inline hb_bool_t
static inline bool
_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
{
return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
}
static inline hb_bool_t
static inline bool
_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
{
return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
......
......@@ -476,7 +476,9 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
}
/* Substitute */
/*
* Substitute
*/
static inline void
hb_ot_mirror_chars (const hb_ot_shape_context_t *c)
......@@ -582,10 +584,8 @@ hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c)
}
static void
hb_ot_zero_width_default_ignorables (const hb_ot_shape_context_t *c)
hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer)
{
hb_buffer_t *buffer = c->buffer;
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
(buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) ||
(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES))
......@@ -601,21 +601,19 @@ hb_ot_zero_width_default_ignorables (const hb_ot_shape_context_t *c)
}
static void
hb_ot_hide_default_ignorables (const hb_ot_shape_context_t *c)
hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
hb_font_t *font)
{
hb_buffer_t *buffer = c->buffer;
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
(buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
return;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
hb_glyph_position_t *pos = buffer->pos;
hb_codepoint_t invisible = c->buffer->invisible;
hb_codepoint_t invisible = buffer->invisible;
if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
(invisible || c->font->get_nominal_glyph (' ', &invisible)))
(invisible || font->get_nominal_glyph (' ', &invisible)))
{
/* Replace default-ignorables with a zero-advance invisible glyph. */
for (unsigned int i = 0; i < count; i++)
......@@ -625,49 +623,7 @@ hb_ot_hide_default_ignorables (const hb_ot_shape_context_t *c)
}
}
else
{
/* Merge clusters and delete default-ignorables.
* NOTE! We can't use out-buffer as we have positioning data. */
unsigned int j = 0;
for (unsigned int i = 0; i < count; i++)
{
if (_hb_glyph_info_is_default_ignorable (&info[i]))
{
/* Merge clusters.
* Same logic as buffer->delete_glyph(), but for in-place removal. */
unsigned int cluster = info[i].cluster;
if (i + 1 < count && cluster == info[i + 1].cluster)
continue; /* Cluster survives; do nothing. */
if (j)
{
/* Merge cluster backward. */
if (cluster < info[j - 1].cluster)
{
unsigned int mask = info[i].mask;
unsigned int old_cluster = info[j - 1].cluster;
for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
buffer->set_cluster (info[k - 1], cluster, mask);
}
continue;
}
if (i + 1 < count)
buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
continue;
}
if (j != i)
{
info[j] = info[i];
pos[j] = pos[i];
}
j++;
}
buffer->len = j;
}
hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable);
}
......@@ -684,10 +640,10 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
}
static inline void
hb_synthesize_glyph_classes (const hb_ot_shape_context_t *c)
hb_synthesize_glyph_classes (hb_buffer_t *buffer)
{
unsigned int count = c->buffer->len;
hb_glyph_info_t *info = c->buffer->info;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
{
hb_ot_layout_glyph_props_flags_t klass;
......@@ -739,7 +695,7 @@ hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
hb_ot_layout_substitute_start (c->font, buffer);
if (c->plan->fallback_glyph_classes)
hb_synthesize_glyph_classes (c);
hb_synthesize_glyph_classes (c->buffer);
if (unlikely (c->plan->apply_morx))
hb_aat_layout_substitute (c->plan, c->font, c->buffer);
......@@ -748,7 +704,7 @@ hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
}
static inline void
hb_ot_substitute (const hb_ot_shape_context_t *c)
hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
{
hb_ot_substitute_default (c);
......@@ -757,7 +713,21 @@ hb_ot_substitute (const hb_ot_shape_context_t *c)
hb_ot_substitute_complex (c);
}
/* Position */
static inline void
hb_ot_substitute_post (const hb_ot_shape_context_t *c)
{
hb_ot_hide_default_ignorables (c->buffer, c->font);
if (c->plan->apply_morx)
hb_aat_layout_remove_deleted_glyphs (c->buffer);
if (c->plan->shaper->postprocess_glyphs)
c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
}
/*
* Position
*/
static inline void
adjust_mark_offsets (hb_glyph_position_t *pos)
......@@ -890,9 +860,11 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
break;
}
/* Finishing off GPOS has to follow a certain order. */
/* Finish off. Has to follow a certain order. */
hb_ot_layout_position_finish_advances (c->font, c->buffer);
hb_ot_zero_width_default_ignorables (c);
hb_ot_zero_width_default_ignorables (c->buffer);
if (c->plan->apply_morx)
hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
hb_ot_layout_position_finish_offsets (c->font, c->buffer);
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
......@@ -983,13 +955,9 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
if (c->plan->shaper->preprocess_text)
c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
hb_ot_substitute (c);
hb_ot_substitute_pre (c);
hb_ot_position (c);
hb_ot_hide_default_ignorables (c);
if (c->plan->shaper->postprocess_glyphs)
c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
hb_ot_substitute_post (c);
hb_propagate_flags (c->buffer);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册