| Index: third_party/harfbuzz-ng/src/hb-ot-layout.cc
|
| diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.cc b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
|
| index c80ca7d7f7021413f6f02a42925a6caf978477c0..183726e63cf47e44a4626d9f5d5cdc7e447c347c 100644
|
| --- a/third_party/harfbuzz-ng/src/hb-ot-layout.cc
|
| +++ b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
|
| @@ -2,7 +2,7 @@
|
| * Copyright © 1998-2004 David Turner and Werner Lemberg
|
| * Copyright © 2006 Behdad Esfahbod
|
| * Copyright © 2007,2008,2009 Red Hat, Inc.
|
| - * Copyright © 2012 Google, Inc.
|
| + * Copyright © 2012,2013 Google, Inc.
|
| *
|
| * This is part of HarfBuzz, a text shaping library.
|
| *
|
| @@ -33,6 +33,9 @@
|
| #include "hb-ot-layout-gdef-table.hh"
|
| #include "hb-ot-layout-gsub-table.hh"
|
| #include "hb-ot-layout-gpos-table.hh"
|
| +#include "hb-ot-layout-jstf-table.hh"
|
| +
|
| +#include "hb-ot-map-private.hh"
|
|
|
| #include <stdlib.h>
|
| #include <string.h>
|
| @@ -59,26 +62,20 @@ _hb_ot_layout_create (hb_face_t *face)
|
| layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
|
| layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
|
|
|
| - layout->gsub_digests = (hb_set_digest_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_set_digest_t));
|
| - layout->gpos_digests = (hb_set_digest_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_set_digest_t));
|
| + layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
|
| + layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
|
|
|
| - if (unlikely ((layout->gsub_lookup_count && !layout->gsub_digests) ||
|
| - (layout->gpos_lookup_count && !layout->gpos_digests)))
|
| + if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
|
| + (layout->gpos_lookup_count && !layout->gpos_accels)))
|
| {
|
| _hb_ot_layout_destroy (layout);
|
| return NULL;
|
| }
|
|
|
| for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
|
| - {
|
| - layout->gsub_digests[i].init ();
|
| - layout->gsub->get_lookup (i).add_coverage (&layout->gsub_digests[i]);
|
| - }
|
| + layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
|
| for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
|
| - {
|
| - layout->gpos_digests[i].init ();
|
| - layout->gpos->get_lookup (i).add_coverage (&layout->gpos_digests[i]);
|
| - }
|
| + layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
|
|
|
| return layout;
|
| }
|
| @@ -86,13 +83,18 @@ _hb_ot_layout_create (hb_face_t *face)
|
| void
|
| _hb_ot_layout_destroy (hb_ot_layout_t *layout)
|
| {
|
| + for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
|
| + layout->gsub_accels[i].fini (layout->gsub->get_lookup (i));
|
| + for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
|
| + layout->gpos_accels[i].fini (layout->gpos->get_lookup (i));
|
| +
|
| + free (layout->gsub_accels);
|
| + free (layout->gpos_accels);
|
| +
|
| hb_blob_destroy (layout->gdef_blob);
|
| hb_blob_destroy (layout->gsub_blob);
|
| hb_blob_destroy (layout->gpos_blob);
|
|
|
| - free (layout->gsub_digests);
|
| - free (layout->gpos_digests);
|
| -
|
| free (layout);
|
| }
|
|
|
| @@ -412,6 +414,24 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face,
|
| return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
|
| }
|
|
|
| +unsigned int
|
| +hb_ot_layout_table_get_lookup_count (hb_face_t *face,
|
| + hb_tag_t table_tag)
|
| +{
|
| + switch (table_tag)
|
| + {
|
| + case HB_OT_TAG_GSUB:
|
| + {
|
| + return hb_ot_layout_from_face (face)->gsub_lookup_count;
|
| + }
|
| + case HB_OT_TAG_GPOS:
|
| + {
|
| + return hb_ot_layout_from_face (face)->gpos_lookup_count;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| static void
|
| _hb_ot_layout_collect_lookups_lookups (hb_face_t *face,
|
| hb_tag_t table_tag,
|
| @@ -445,19 +465,19 @@ _hb_ot_layout_collect_lookups_features (hb_face_t *face,
|
| const hb_tag_t *features,
|
| hb_set_t *lookup_indexes /* OUT */)
|
| {
|
| - unsigned int required_feature_index;
|
| - if (hb_ot_layout_language_get_required_feature_index (face,
|
| - table_tag,
|
| - script_index,
|
| - language_index,
|
| - &required_feature_index))
|
| - _hb_ot_layout_collect_lookups_lookups (face,
|
| - table_tag,
|
| - required_feature_index,
|
| - lookup_indexes);
|
| -
|
| if (!features)
|
| {
|
| + unsigned int required_feature_index;
|
| + if (hb_ot_layout_language_get_required_feature_index (face,
|
| + table_tag,
|
| + script_index,
|
| + language_index,
|
| + &required_feature_index))
|
| + _hb_ot_layout_collect_lookups_lookups (face,
|
| + table_tag,
|
| + required_feature_index,
|
| + lookup_indexes);
|
| +
|
| /* All features */
|
| unsigned int feature_indices[32];
|
| unsigned int offset, len;
|
| @@ -613,13 +633,13 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
|
| case HB_OT_TAG_GSUB:
|
| {
|
| const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
|
| - l.collect_glyphs_lookup (&c);
|
| + l.collect_glyphs (&c);
|
| return;
|
| }
|
| case HB_OT_TAG_GPOS:
|
| {
|
| const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
|
| - l.collect_glyphs_lookup (&c);
|
| + l.collect_glyphs (&c);
|
| return;
|
| }
|
| }
|
| @@ -659,7 +679,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
|
|
|
| const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
|
|
|
| - return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]);
|
| + return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest);
|
| }
|
|
|
| void
|
| @@ -668,22 +688,6 @@ hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
|
| OT::GSUB::substitute_start (font, buffer);
|
| }
|
|
|
| -hb_bool_t
|
| -hb_ot_layout_substitute_lookup (hb_font_t *font,
|
| - hb_buffer_t *buffer,
|
| - unsigned int lookup_index,
|
| - hb_mask_t mask,
|
| - hb_bool_t auto_zwj)
|
| -{
|
| - if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup_count)) return false;
|
| -
|
| - OT::hb_apply_context_t c (0, font, buffer, mask, auto_zwj);
|
| -
|
| - const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_lookup (lookup_index);
|
| -
|
| - return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_digests[lookup_index]);
|
| -}
|
| -
|
| void
|
| hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
|
| {
|
| @@ -718,22 +722,6 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
|
| OT::GPOS::position_start (font, buffer);
|
| }
|
|
|
| -hb_bool_t
|
| -hb_ot_layout_position_lookup (hb_font_t *font,
|
| - hb_buffer_t *buffer,
|
| - unsigned int lookup_index,
|
| - hb_mask_t mask,
|
| - hb_bool_t auto_zwj)
|
| -{
|
| - if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup_count)) return false;
|
| -
|
| - OT::hb_apply_context_t c (1, font, buffer, mask, auto_zwj);
|
| -
|
| - const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup (lookup_index);
|
| -
|
| - return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_digests[lookup_index]);
|
| -}
|
| -
|
| void
|
| hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
|
| {
|
| @@ -784,3 +772,159 @@ hb_ot_layout_get_size_params (hb_face_t *face,
|
|
|
| return false;
|
| }
|
| +
|
| +
|
| +/*
|
| + * Parts of different types are implemented here such that they have direct
|
| + * access to GSUB/GPOS lookups.
|
| + */
|
| +
|
| +
|
| +struct GSUBProxy
|
| +{
|
| + static const unsigned int table_index = 0;
|
| + static const bool inplace = false;
|
| + typedef OT::SubstLookup Lookup;
|
| +
|
| + GSUBProxy (hb_face_t *face) :
|
| + table (*hb_ot_layout_from_face (face)->gsub),
|
| + accels (hb_ot_layout_from_face (face)->gsub_accels) {}
|
| +
|
| + const OT::GSUB &table;
|
| + const hb_ot_layout_lookup_accelerator_t *accels;
|
| +};
|
| +
|
| +struct GPOSProxy
|
| +{
|
| + static const unsigned int table_index = 1;
|
| + static const bool inplace = true;
|
| + typedef OT::PosLookup Lookup;
|
| +
|
| + GPOSProxy (hb_face_t *face) :
|
| + table (*hb_ot_layout_from_face (face)->gpos),
|
| + accels (hb_ot_layout_from_face (face)->gpos_accels) {}
|
| +
|
| + const OT::GPOS &table;
|
| + const hb_ot_layout_lookup_accelerator_t *accels;
|
| +};
|
| +
|
| +
|
| +template <typename Lookup>
|
| +static inline bool apply_once (OT::hb_apply_context_t *c,
|
| + const Lookup &lookup)
|
| +{
|
| + if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
|
| + return false;
|
| + return lookup.dispatch (c);
|
| +}
|
| +
|
| +template <typename Proxy>
|
| +static inline bool
|
| +apply_string (OT::hb_apply_context_t *c,
|
| + const typename Proxy::Lookup &lookup,
|
| + const hb_ot_layout_lookup_accelerator_t &accel)
|
| +{
|
| + bool ret = false;
|
| + hb_buffer_t *buffer = c->buffer;
|
| +
|
| + if (unlikely (!buffer->len || !c->lookup_mask))
|
| + return false;
|
| +
|
| + c->set_lookup (lookup);
|
| +
|
| + if (likely (!lookup.is_reverse ()))
|
| + {
|
| + /* in/out forward substitution/positioning */
|
| + if (Proxy::table_index == 0)
|
| + buffer->clear_output ();
|
| + buffer->idx = 0;
|
| +
|
| + while (buffer->idx < buffer->len)
|
| + {
|
| + if (accel.digest.may_have (buffer->cur().codepoint) &&
|
| + (buffer->cur().mask & c->lookup_mask) &&
|
| + apply_once (c, lookup))
|
| + ret = true;
|
| + else
|
| + buffer->next_glyph ();
|
| + }
|
| + if (ret)
|
| + {
|
| + if (!Proxy::inplace)
|
| + buffer->swap_buffers ();
|
| + else
|
| + assert (!buffer->has_separate_output ());
|
| + }
|
| + }
|
| + else
|
| + {
|
| + /* in-place backward substitution/positioning */
|
| + if (Proxy::table_index == 0)
|
| + buffer->remove_output ();
|
| + buffer->idx = buffer->len - 1;
|
| + do
|
| + {
|
| + if (accel.digest.may_have (buffer->cur().codepoint) &&
|
| + (buffer->cur().mask & c->lookup_mask) &&
|
| + apply_once (c, lookup))
|
| + ret = true;
|
| + /* The reverse lookup doesn't "advance" cursor (for good reason). */
|
| + buffer->idx--;
|
| +
|
| + }
|
| + while ((int) buffer->idx >= 0);
|
| + }
|
| +
|
| + return ret;
|
| +}
|
| +
|
| +template <typename Proxy>
|
| +inline void hb_ot_map_t::apply (const Proxy &proxy,
|
| + const hb_ot_shape_plan_t *plan,
|
| + hb_font_t *font,
|
| + hb_buffer_t *buffer) const
|
| +{
|
| + const unsigned int table_index = proxy.table_index;
|
| + unsigned int i = 0;
|
| + OT::hb_apply_context_t c (table_index, font, buffer);
|
| + c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
|
| +
|
| + for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
|
| + const stage_map_t *stage = &stages[table_index][stage_index];
|
| + for (; i < stage->last_lookup; i++)
|
| + {
|
| + unsigned int lookup_index = lookups[table_index][i].index;
|
| + c.set_lookup_mask (lookups[table_index][i].mask);
|
| + c.set_auto_zwj (lookups[table_index][i].auto_zwj);
|
| + apply_string<Proxy> (&c,
|
| + proxy.table.get_lookup (lookup_index),
|
| + proxy.accels[lookup_index]);
|
| + }
|
| +
|
| + if (stage->pause_func)
|
| + {
|
| + buffer->clear_output ();
|
| + stage->pause_func (plan, font, buffer);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
|
| +{
|
| + GSUBProxy proxy (font->face);
|
| + apply (proxy, plan, font, buffer);
|
| +}
|
| +
|
| +void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
|
| +{
|
| + GPOSProxy proxy (font->face);
|
| + apply (proxy, plan, font, buffer);
|
| +}
|
| +
|
| +HB_INTERNAL void
|
| +hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
|
| + const OT::SubstLookup &lookup,
|
| + const hb_ot_layout_lookup_accelerator_t &accel)
|
| +{
|
| + apply_string<GSUBProxy> (c, lookup, accel);
|
| +}
|
|
|