[aat] Start implementing Apple AAT morx table

This commit is contained in:
Behdad Esfahbod 2017-08-14 17:24:36 -07:00
parent 3c7aeb5c64
commit c71b55a223
6 changed files with 331 additions and 0 deletions

View File

@ -82,6 +82,8 @@ HB_FALLBACK_sources = \
$(NULL) $(NULL)
HB_OT_sources = \ HB_OT_sources = \
hb-aat-layout.cc \
hb-aat-layout-morx-table.hh \
hb-ot-font.cc \ hb-ot-font.cc \
hb-ot-layout.cc \ hb-ot-layout.cc \
hb-ot-layout-common-private.hh \ hb-ot-layout-common-private.hh \

View File

@ -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 <hb-open-type-private.hh>
#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 <typename UINT>
struct ChainSubtable
{
template <typename> struct Chain;
friend struct Chain<UINT>;
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 <typename context_t>
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 <typename UINT>
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<UINT> *subtable = &StructAtOffset<ChainSubtable<UINT> > (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<ChainSubtable<UINT> > (*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<UINT> subtableX[VAR]; /* Subtables. */
// subtableGlyphCoverageArray if major == 3
public:
DEFINE_SIZE_MIN (8 + 2 * sizeof (UINT));
};
/*
* The 'mort'/'morx' Tables
*/
template <typename UINT>
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<UINT> *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<UINT> > (*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<UINT> chains[VAR]; /* Chains. */
public:
DEFINE_SIZE_MIN (8);
};
struct mort : mortmorx<USHORT>
{
static const hb_tag_t tableTag = HB_AAT_TAG_MORT;
};
struct morx : mortmorx<ULONG>
{
static const hb_tag_t tableTag = HB_AAT_TAG_MORX;
};
} /* namespace AAT */
#endif /* HB_AAT_LAYOUT_MORX_TABLE_HH */

42
src/hb-aat-layout.cc Normal file
View File

@ -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 ());
}

View File

@ -160,6 +160,11 @@ static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small.
* Dispatch * Dispatch
*/ */
#define TRACE_DISPATCH(this, format) \
hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
"format %d", (int) format);
template <typename Context, typename Return, unsigned int MaxDebugDepth> template <typename Context, typename Return, unsigned int MaxDebugDepth>
struct hb_dispatch_context_t struct hb_dispatch_context_t
{ {

View File

@ -130,6 +130,10 @@ namespace OT {
struct avar; struct avar;
} }
namespace AAT {
struct morx;
}
struct hb_ot_layout_lookup_accelerator_t struct hb_ot_layout_lookup_accelerator_t
{ {
template <typename TLookup> template <typename TLookup>
@ -165,6 +169,7 @@ struct hb_ot_layout_t
OT::hb_lazy_table_loader_t<struct OT::MATH> math; OT::hb_lazy_table_loader_t<struct OT::MATH> math;
OT::hb_lazy_table_loader_t<struct OT::fvar> fvar; OT::hb_lazy_table_loader_t<struct OT::fvar> fvar;
OT::hb_lazy_table_loader_t<struct OT::avar> avar; OT::hb_lazy_table_loader_t<struct OT::avar> avar;
OT::hb_lazy_table_loader_t<struct AAT::morx> morx;
unsigned int gsub_lookup_count; unsigned int gsub_lookup_count;
unsigned int gpos_lookup_count; unsigned int gpos_lookup_count;

View File

@ -62,6 +62,7 @@ _hb_ot_layout_create (hb_face_t *face)
layout->math.init (face); layout->math.init (face);
layout->fvar.init (face); layout->fvar.init (face);
layout->avar.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->math.fini ();
layout->fvar.fini (); layout->fvar.fini ();
layout->avar.fini (); layout->avar.fini ();
layout->morx.fini ();
free (layout); free (layout);
} }