diff --git a/src/Makefile.sources b/src/Makefile.sources index 63e0ddcd7..a728fc092 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -82,6 +82,8 @@ HB_FALLBACK_sources = \ $(NULL) HB_OT_sources = \ + hb-aat-layout.cc \ + hb-aat-layout-morx-table.hh \ hb-ot-font.cc \ hb-ot-layout.cc \ hb-ot-layout-common-private.hh \ diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh new file mode 100644 index 000000000..d3a694b5f --- /dev/null +++ b/src/hb-aat-layout-morx-table.hh @@ -0,0 +1,275 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_AAT_LAYOUT_MORX_TABLE_HH +#define HB_AAT_LAYOUT_MORX_TABLE_HH + +#include + +#define HB_AAT_TAG_MORT HB_TAG('m','o','r','t') +#define HB_AAT_TAG_MORX HB_TAG('m','o','r','x') + + +namespace AAT { + +using namespace OT; + + +struct RearrangementSubtable +{ + /* TODO */ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + /* TODO */ + return_trace (false); + } +}; + +struct ContextualSubtable +{ + /* TODO */ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + /* TODO */ + return_trace (false); + } +}; + +struct LigatureSubtable +{ + /* TODO */ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + /* TODO */ + return_trace (false); + } +}; + +struct NoncontextualSubtable +{ + /* TODO */ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + /* TODO */ + return_trace (false); + } +}; + +struct InsertionSubtable +{ + /* TODO */ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + /* TODO */ + return_trace (false); + } +}; + + +struct Feature +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + USHORT featureType; /* The type of feature. */ + USHORT featureSetting; /* The feature's setting (aka selector). */ + ULONG enableFlags; /* Flags for the settings that this feature + * and setting enables. */ + ULONG disableFlags; /* Complement of flags for the settings that this + * feature and setting disable. */ + + public: + DEFINE_SIZE_STATIC (12); +}; + + +template +struct ChainSubtable +{ + template struct Chain; + friend struct Chain; + + inline unsigned int get_size (void) const { return length; } + inline unsigned int get_type (void) const { return coverage & 0xFF; } + + enum Type { + Rearrangement = 0, + Contextual = 1, + Ligature = 2, + Noncontextual = 4, + Insertion = 5 + }; + + template + inline typename context_t::return_t dispatch (context_t *c) const + { + unsigned int subtable_type = get_type (); + TRACE_DISPATCH (this, subtable_type); + switch (subtable_type) { + case Rearrangement: return_trace (c->dispatch (u.rearrangement)); + case Contextual: return_trace (c->dispatch (u.contextual)); + case Ligature: return_trace (c->dispatch (u.ligature)); + case Noncontextual: return_trace (c->dispatch (u.noncontextual)); + case Insertion: return_trace (c->dispatch (u.insertion)); + default: return_trace (c->default_return_value ()); + } + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!length.sanitize (c) || + length < min_size || + !c->check_range (this, length)) + return_trace (false); + + return_trace (dispatch (c)); + } + + protected: + UINT length; /* Total subtable length, including this header. */ + UINT coverage; /* Coverage flags and subtable type. */ + ULONG subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */ + union { + RearrangementSubtable rearrangement; + ContextualSubtable contextual; + LigatureSubtable ligature; + NoncontextualSubtable noncontextual; + InsertionSubtable insertion; + } u; + public: + DEFINE_SIZE_MIN (2 * sizeof (UINT) + 4); +}; + +template +struct Chain +{ + + inline unsigned int get_size (void) const { return length; } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int major) const + { + TRACE_SANITIZE (this); + if (!length.sanitize (c) || + length < min_size || + !c->check_range (this, length)) + return_trace (false); + + if (!c->check_array (featureZ, featureZ[0].static_size, featureCount)) + return_trace (false); + + const ChainSubtable *subtable = &StructAtOffset > (featureZ, featureZ[0].static_size * featureCount); + unsigned int count = subtableCount; + for (unsigned int i = 0; i < count; i++) + { + if (!subtable->sanitize (c)) + return_trace (false); + subtable = &StructAfter > (*subtable); + } + + return_trace (true); + } + + protected: + ULONG defaultFlags; /* The default specification for subtables. */ + ULONG length; /* Total byte count, including this header. */ + UINT featureCount; /* Number of feature subtable entries. */ + UINT subtableCount; /* The number of subtables in the chain. */ + + Feature featureZ[VAR]; /* Features. */ + ChainSubtable subtableX[VAR]; /* Subtables. */ + // subtableGlyphCoverageArray if major == 3 + + public: + DEFINE_SIZE_MIN (8 + 2 * sizeof (UINT)); +}; + + +/* + * The 'mort'/'morx' Tables + */ + +template +struct mortmorx +{ + static const hb_tag_t mortTag = HB_AAT_TAG_MORT; + static const hb_tag_t morxTag = HB_AAT_TAG_MORX; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!version.sanitize (c) || + version.major >> (sizeof (UINT) == 4) != 1 || + !chainCount.sanitize (c)) + return_trace (false); + + const Chain *chain = chains; + unsigned int count = chainCount; + for (unsigned int i = 0; i < count; i++) + { + if (!chain->sanitize (c, version.major)) + return_trace (false); + chain = &StructAfter > (*chain); + } + + return_trace (true); + } + + protected: + FixedVersion<>version; /* Version number of the glyph metamorphosis table. + * 1 for mort, 2 or 3 for morx. */ + ULONG chainCount; /* Number of metamorphosis chains contained in this + * table. */ + Chain chains[VAR]; /* Chains. */ + + public: + DEFINE_SIZE_MIN (8); +}; + +struct mort : mortmorx +{ + static const hb_tag_t tableTag = HB_AAT_TAG_MORT; +}; + +struct morx : mortmorx +{ + static const hb_tag_t tableTag = HB_AAT_TAG_MORX; +}; + + +} /* namespace AAT */ + + +#endif /* HB_AAT_LAYOUT_MORX_TABLE_HH */ diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc new file mode 100644 index 000000000..c5277ed72 --- /dev/null +++ b/src/hb-aat-layout.cc @@ -0,0 +1,42 @@ +/* + * Copyright © 2017 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#include "hb-open-type-private.hh" +#include "hb-ot-layout-private.hh" + +#include "hb-aat-layout-morx-table.hh" + +/* + * mort/morx + */ + +static inline const AAT::morx& +_get_morx (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(AAT::morx); + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + return *(layout->morx.get ()); +} diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 2f4e1b9e9..a8c3ee2bc 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -160,6 +160,11 @@ static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. * Dispatch */ +#define TRACE_DISPATCH(this, format) \ + hb_auto_trace_t trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "format %d", (int) format); + template struct hb_dispatch_context_t { diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index be5695d98..39d1a6720 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -130,6 +130,10 @@ namespace OT { struct avar; } +namespace AAT { + struct morx; +} + struct hb_ot_layout_lookup_accelerator_t { template @@ -165,6 +169,7 @@ struct hb_ot_layout_t OT::hb_lazy_table_loader_t math; OT::hb_lazy_table_loader_t fvar; OT::hb_lazy_table_loader_t avar; + OT::hb_lazy_table_loader_t morx; unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 884588982..d4737393f 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -62,6 +62,7 @@ _hb_ot_layout_create (hb_face_t *face) layout->math.init (face); layout->fvar.init (face); layout->avar.init (face); + layout->morx.init (face); { /* @@ -209,6 +210,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) layout->math.fini (); layout->fvar.fini (); layout->avar.fini (); + layout->morx.fini (); free (layout); }