Merge branch 'master' into cff-subset

This commit is contained in:
Michiharu Ariza 2018-09-17 13:07:29 -07:00
commit d050ab8d3e
18 changed files with 306 additions and 105 deletions

View File

@ -761,11 +761,16 @@ endif ()
if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
install(TARGETS harfbuzz install(TARGETS harfbuzz
EXPORT harfbuzzConfig
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
FRAMEWORK DESTINATION Library/Frameworks FRAMEWORK DESTINATION Library/Frameworks
) )
install(EXPORT harfbuzzConfig
NAMESPACE harfbuzz::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/harfbuzz
)
if (HB_BUILD_UTILS) if (HB_BUILD_UTILS)
install(TARGETS hb-view install(TARGETS hb-view
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}

View File

@ -243,7 +243,7 @@ struct LookupSegmentArray
GlyphID last; /* Last GlyphID in this segment */ GlyphID last; /* Last GlyphID in this segment */
GlyphID first; /* First GlyphID in this segment */ GlyphID first; /* First GlyphID in this segment */
OffsetTo<UnsizedArrayOf<T> > OffsetTo<UnsizedArrayOf<T>, HBUINT16, false>
valuesZ; /* A 16-bit offset from the start of valuesZ; /* A 16-bit offset from the start of
* the table to the data. */ * the table to the data. */
public: public:
@ -439,10 +439,23 @@ struct Entry<void>
template <typename Extra> template <typename Extra>
struct StateTable struct StateTable
{ {
enum State
{
STATE_START_OF_TEXT = 0,
STATE_START_OF_LINE = 1,
};
enum Class
{
CLASS_END_OF_TEXT = 0,
CLASS_OUT_OF_BOUNDS = 1,
CLASS_DELETED_GLYPH = 2,
CLASS_END_OF_LINE = 3,
};
inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
{ {
const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs); const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs);
return v ? *v : 1; return v ? (unsigned) *v : (unsigned) CLASS_OUT_OF_BOUNDS;
} }
inline const Entry<Extra> *get_entries () const inline const Entry<Extra> *get_entries () const
@ -509,11 +522,11 @@ struct StateTable
protected: protected:
HBUINT32 nClasses; /* Number of classes, which is the number of indices HBUINT32 nClasses; /* Number of classes, which is the number of indices
* in a single line in the state array. */ * in a single line in the state array. */
LOffsetTo<Lookup<HBUINT16> > LOffsetTo<Lookup<HBUINT16>, false>
classTable; /* Offset to the class table. */ classTable; /* Offset to the class table. */
LOffsetTo<UnsizedArrayOf<HBUINT16> > LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
stateArrayTable;/* Offset to the state array. */ stateArrayTable;/* Offset to the state array. */
LOffsetTo<UnsizedArrayOf<Entry<Extra> > > LOffsetTo<UnsizedArrayOf<Entry<Extra> >, false>
entryTable; /* Offset to the entry array. */ entryTable; /* Offset to the entry array. */
public: public:
@ -538,13 +551,13 @@ struct StateTableDriver
if (!c->in_place) if (!c->in_place)
buffer->clear_output (); buffer->clear_output ();
unsigned int state = 0; unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT;
bool last_was_dont_advance = false; bool last_was_dont_advance = false;
for (buffer->idx = 0;;) for (buffer->idx = 0;;)
{ {
unsigned int klass = buffer->idx < buffer->len ? unsigned int klass = buffer->idx < buffer->len ?
machine.get_class (info[buffer->idx].codepoint, num_glyphs) : machine.get_class (info[buffer->idx].codepoint, num_glyphs) :
0 /* End of text */; (unsigned) StateTable<EntryData>::CLASS_END_OF_TEXT;
const Entry<EntryData> *entry = machine.get_entryZ (state, klass); const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
if (unlikely (!entry)) if (unlikely (!entry))
break; break;

View File

@ -78,7 +78,7 @@ struct FeatureName
protected: protected:
HBUINT16 feature; /* Feature type. */ HBUINT16 feature; /* Feature type. */
HBUINT16 nSettings; /* The number of records in the setting name array. */ HBUINT16 nSettings; /* The number of records in the setting name array. */
LOffsetTo<UnsizedArrayOf<SettingName> > LOffsetTo<UnsizedArrayOf<SettingName>, false>
settingTable; /* Offset in bytes from the beginning of this table to settingTable; /* Offset in bytes from the beginning of this table to
* this feature's setting name array. The actual type of * this feature's setting name array. The actual type of
* record this offset refers to will depend on the * record this offset refers to will depend on the

View File

@ -50,7 +50,8 @@ struct RearrangementSubtable
struct driver_context_t struct driver_context_t
{ {
static const bool in_place = true; static const bool in_place = true;
enum Flags { enum Flags
{
MarkFirst = 0x8000, /* If set, make the current glyph the first MarkFirst = 0x8000, /* If set, make the current glyph the first
* glyph to be rearranged. */ * glyph to be rearranged. */
DontAdvance = 0x4000, /* If set, don't advance to the next glyph DontAdvance = 0x4000, /* If set, don't advance to the next glyph
@ -196,7 +197,8 @@ struct ContextualSubtable
struct driver_context_t struct driver_context_t
{ {
static const bool in_place = true; static const bool in_place = true;
enum Flags { enum Flags
{
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */ SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
* going to the new state. */ * going to the new state. */
@ -309,7 +311,7 @@ struct ContextualSubtable
protected: protected:
StateTable<EntryData> StateTable<EntryData>
machine; machine;
LOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> > LOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32>, false>
substitutionTables; substitutionTables;
public: public:
DEFINE_SIZE_STATIC (20); DEFINE_SIZE_STATIC (20);
@ -329,7 +331,8 @@ struct LigatureSubtable
struct driver_context_t struct driver_context_t
{ {
static const bool in_place = false; static const bool in_place = false;
enum Flags { enum Flags
{
SetComponent = 0x8000, /* Push this glyph onto the component stack for SetComponent = 0x8000, /* Push this glyph onto the component stack for
* eventual processing. */ * eventual processing. */
DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
@ -338,7 +341,8 @@ struct LigatureSubtable
* group. */ * group. */
Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */ Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
}; };
enum LigActionFlags { enum LigActionFlags
{
LigActionLast = 0x80000000, /* This is the last action in the list. This also LigActionLast = 0x80000000, /* This is the last action in the list. This also
* implies storage. */ * implies storage. */
LigActionStore = 0x40000000, /* Store the ligature at the current cumulated index LigActionStore = 0x40000000, /* Store the ligature at the current cumulated index
@ -469,11 +473,11 @@ struct LigatureSubtable
protected: protected:
StateTable<EntryData> StateTable<EntryData>
machine; machine;
LOffsetTo<UnsizedArrayOf<HBUINT32> > LOffsetTo<UnsizedArrayOf<HBUINT32>, false>
ligAction; /* Offset to the ligature action table. */ ligAction; /* Offset to the ligature action table. */
LOffsetTo<UnsizedArrayOf<HBUINT16> > LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
component; /* Offset to the component table. */ component; /* Offset to the component table. */
LOffsetTo<UnsizedArrayOf<GlyphID> > LOffsetTo<UnsizedArrayOf<GlyphID>, false>
ligature; /* Offset to the actual ligature lists. */ ligature; /* Offset to the actual ligature lists. */
public: public:
DEFINE_SIZE_STATIC (28); DEFINE_SIZE_STATIC (28);
@ -517,19 +521,186 @@ struct NoncontextualSubtable
struct InsertionSubtable struct InsertionSubtable
{ {
struct EntryData
{
HBUINT16 currentInsertIndex; /* Zero-based index into the insertion glyph table.
* The number of glyphs to be inserted is contained
* in the currentInsertCount field in the flags.
* A value of 0xFFFF indicates no insertion is to
* be done. */
HBUINT16 markedInsertIndex; /* Zero-based index into the insertion glyph table.
* The number of glyphs to be inserted is contained
* in the markedInsertCount field in the flags.
* A value of 0xFFFF indicates no insertion is to
* be done. */
public:
DEFINE_SIZE_STATIC (4);
};
struct driver_context_t
{
static const bool in_place = false;
enum Flags
{
SetMark = 0x8000, /* If set, mark the current glyph. */
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
* going to the new state. This does not mean
* that the glyph pointed to is the same one as
* before. If you've made insertions immediately
* downstream of the current glyph, the next glyph
* processed would in fact be the first one
* inserted. */
CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero,
* then the specified glyph list will be inserted
* as a kashida-like insertion, either before or
* after the current glyph (depending on the state
* of the currentInsertBefore flag). If clear, and
* the currentInsertList is nonzero, then the
* specified glyph list will be inserted as a
* split-vowel-like insertion, either before or
* after the current glyph (depending on the state
* of the currentInsertBefore flag). */
MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero,
* then the specified glyph list will be inserted
* as a kashida-like insertion, either before or
* after the marked glyph (depending on the state
* of the markedInsertBefore flag). If clear, and
* the markedInsertList is nonzero, then the
* specified glyph list will be inserted as a
* split-vowel-like insertion, either before or
* after the marked glyph (depending on the state
* of the markedInsertBefore flag). */
CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made
* to the left of the current glyph. If clear,
* they're made to the right of the current glyph. */
MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be
* made to the left of the marked glyph. If clear,
* they're made to the right of the marked glyph. */
CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the
* number of glyphs to insert at the current
* position. Since zero means no insertions, the
* largest number of insertions at any given
* current location is 31 glyphs. */
MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the
* number of glyphs to insert at the marked
* position. Since zero means no insertions, the
* largest number of insertions at any given
* marked location is 31 glyphs. */
};
inline driver_context_t (const InsertionSubtable *table,
hb_aat_apply_context_t *c_) :
ret (false),
c (c_),
mark_set (false),
mark (0),
insertionAction (table+table->insertionAction) {}
inline bool is_actionable (StateTableDriver<EntryData> *driver,
const Entry<EntryData> *entry)
{
return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) &&
(entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF);
}
inline bool transition (StateTableDriver<EntryData> *driver,
const Entry<EntryData> *entry)
{
hb_buffer_t *buffer = driver->buffer;
unsigned int flags = entry->flags;
if (entry->data.markedInsertIndex != 0xFFFF)
{
unsigned int count = (entry->flags & MarkedInsertCount);
unsigned int start = entry->data.markedInsertIndex;
const GlyphID *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false;
bool before = entry->flags & MarkedInsertBefore;
if (unlikely (!mark_set)) return false;
unsigned int end = buffer->out_len;
buffer->move_to (mark);
if (!before)
buffer->copy_glyph ();
/* TODO We ignore KashidaLike setting. */
for (unsigned int i = 0; i < count; i++)
buffer->output_glyph (glyphs[i]);
if (!before)
buffer->skip_glyph ();
buffer->move_to (end + count);
}
if (entry->data.currentInsertIndex != 0xFFFF)
{
unsigned int count = (entry->flags & CurrentInsertCount) >> 5;
unsigned int start = entry->data.currentInsertIndex;
const GlyphID *glyphs = &insertionAction[start];
if (unlikely (!c->sanitizer.check_array (glyphs, count))) return false;
bool before = entry->flags & CurrentInsertBefore;
unsigned int end = buffer->out_len;
if (!before)
buffer->copy_glyph ();
/* TODO We ignore KashidaLike setting. */
for (unsigned int i = 0; i < count; i++)
buffer->output_glyph (glyphs[i]);
if (!before)
buffer->skip_glyph ();
buffer->move_to (end);
}
if (flags & SetMark)
{
mark_set = true;
mark = buffer->out_len;
}
return true;
}
public:
bool ret;
private:
hb_aat_apply_context_t *c;
bool mark_set;
unsigned int mark;
const UnsizedArrayOf<GlyphID> &insertionAction;
};
inline bool apply (hb_aat_apply_context_t *c) const inline bool apply (hb_aat_apply_context_t *c) const
{ {
TRACE_APPLY (this); TRACE_APPLY (this);
/* TODO */
return_trace (false); driver_context_t dc (this, c);
StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
} }
inline bool sanitize (hb_sanitize_context_t *c) const inline bool sanitize (hb_sanitize_context_t *c) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
/* TODO */ /* The rest of array sanitizations are done at run-time. */
return_trace (true); return_trace (c->check_struct (this) && machine.sanitize (c) &&
insertionAction);
} }
protected:
StateTable<EntryData>
machine;
LOffsetTo<UnsizedArrayOf<GlyphID>, false>
insertionAction; /* Byte offset from stateHeader to the start of
* the insertion glyph table. */
public:
DEFINE_SIZE_STATIC (20);
}; };
@ -561,7 +732,8 @@ struct ChainSubtable
inline unsigned int get_size (void) const { return length; } inline unsigned int get_size (void) const { return length; }
inline unsigned int get_type (void) const { return coverage & 0xFF; } inline unsigned int get_type (void) const { return coverage & 0xFF; }
enum Type { enum Type
{
Rearrangement = 0, Rearrangement = 0,
Contextual = 1, Contextual = 1,
Ligature = 2, Ligature = 2,
@ -569,11 +741,6 @@ struct ChainSubtable
Insertion = 5 Insertion = 5
}; };
inline void apply (hb_aat_apply_context_t *c) const
{
dispatch (c);
}
template <typename context_t> template <typename context_t>
inline typename context_t::return_t dispatch (context_t *c) const inline typename context_t::return_t dispatch (context_t *c) const
{ {
@ -619,28 +786,45 @@ struct Chain
{ {
inline void apply (hb_aat_apply_context_t *c) const inline void apply (hb_aat_apply_context_t *c) const
{ {
uint32_t flags = defaultFlags;
{
/* Compute applicable flags. TODO Should move this to planning
* stage and take user-requested features into account. */
unsigned int count = featureCount;
for (unsigned i = 0; i < count; i++)
{
const Feature &feature = featureZ[i];
if (false) /* XXX Check if feature enabled... */
{
flags &= feature.disableFlags;
flags |= feature.enableFlags;
}
}
}
const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount); const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount);
unsigned int count = subtableCount; unsigned int count = subtableCount;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index)) if (!(subtable->subFeatureFlags & flags))
{ goto skip;
c->set_lookup_index (c->lookup_index + 1);
continue;
}
subtable->apply (c); if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
subtable = &StructAfter<ChainSubtable> (*subtable); goto skip;
subtable->dispatch (c);
(void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index); (void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index);
skip:
subtable = &StructAfter<ChainSubtable> (*subtable);
c->set_lookup_index (c->lookup_index + 1); c->set_lookup_index (c->lookup_index + 1);
} }
} }
inline unsigned int get_size (void) const { return length; } inline unsigned int get_size (void) const { return length; }
inline bool sanitize (hb_sanitize_context_t *c, unsigned int major) const inline bool sanitize (hb_sanitize_context_t *c, unsigned int version) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!length.sanitize (c) || if (!length.sanitize (c) ||
@ -671,7 +855,7 @@ struct Chain
UnsizedArrayOf<Feature> featureZ; /* Features. */ UnsizedArrayOf<Feature> featureZ; /* Features. */
/*ChainSubtable firstSubtable;*//* Subtables. */ /*ChainSubtable firstSubtable;*//* Subtables. */
/*subtableGlyphCoverageArray*/ /* Only if major == 3. */ /*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
public: public:
DEFINE_SIZE_MIN (16); DEFINE_SIZE_MIN (16);
@ -701,8 +885,7 @@ struct morx
inline bool sanitize (hb_sanitize_context_t *c) const inline bool sanitize (hb_sanitize_context_t *c) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (!version.sanitize (c) || if (!version.sanitize (c) || version < 2 ||
(version.major >> (sizeof (HBUINT32) == 4 ? 1 : 0)) != 1 ||
!chainCount.sanitize (c)) !chainCount.sanitize (c))
return_trace (false); return_trace (false);
@ -710,7 +893,7 @@ struct morx
unsigned int count = chainCount; unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
if (!chain->sanitize (c, version.major)) if (!chain->sanitize (c, version))
return_trace (false); return_trace (false);
chain = &StructAfter<Chain> (*chain); chain = &StructAfter<Chain> (*chain);
} }
@ -719,8 +902,9 @@ struct morx
} }
protected: protected:
FixedVersion<>version; /* Version number of the glyph metamorphosis table. HBUINT16 version; /* Version number of the glyph metamorphosis table.
* 1 for mort, 2 or 3 for morx. */ * 2 or 3. */
HBUINT16 unused; /* Set to 0. */
HBUINT32 chainCount; /* Number of metamorphosis chains contained in this HBUINT32 chainCount; /* Number of metamorphosis chains contained in this
* table. */ * table. */
Chain firstChain; /* Chains. */ Chain firstChain; /* Chains. */

View File

@ -68,7 +68,7 @@ struct TrackTableEntry
protected: protected:
Fixed track; /* Track value for this record. */ Fixed track; /* Track value for this record. */
NameID trackNameID; /* The 'name' table index for this track */ NameID trackNameID; /* The 'name' table index for this track */
OffsetTo<UnsizedArrayOf<FWORD> > OffsetTo<UnsizedArrayOf<FWORD>, HBUINT16, false>
valuesZ; /* Offset from start of tracking table to valuesZ; /* Offset from start of tracking table to
* per-size tracking values for this track. */ * per-size tracking values for this track. */
@ -134,7 +134,7 @@ struct TrackData
protected: protected:
HBUINT16 nTracks; /* Number of separate tracks included in this table. */ HBUINT16 nTracks; /* Number of separate tracks included in this table. */
HBUINT16 nSizes; /* Number of point sizes included in this table. */ HBUINT16 nSizes; /* Number of point sizes included in this table. */
LOffsetTo<UnsizedArrayOf<Fixed> > LOffsetTo<UnsizedArrayOf<Fixed>, false>
sizeTable; /* Offset to array[nSizes] of size values. */ sizeTable; /* Offset to array[nSizes] of size values. */
UnsizedArrayOf<TrackTableEntry> UnsizedArrayOf<TrackTableEntry>
trackTable; /* Array[nTracks] of TrackTableEntry records. */ trackTable; /* Array[nTracks] of TrackTableEntry records. */

View File

@ -46,7 +46,7 @@ struct FTStringRange
} }
protected: protected:
OffsetTo<UnsizedArrayOf<HBUINT8> > OffsetTo<UnsizedArrayOf<HBUINT8>, HBUINT16, false>
tag; /* Offset from the start of the table to tag; /* Offset from the start of the table to
* the beginning of the string */ * the beginning of the string */
HBUINT16 length; /* String length (in bytes) */ HBUINT16 length; /* String length (in bytes) */

View File

@ -531,7 +531,6 @@ hb_script_get_horizontal_direction (hb_script_t script)
/* Unicode-8.0 additions */ /* Unicode-8.0 additions */
case HB_SCRIPT_HATRAN: case HB_SCRIPT_HATRAN:
case HB_SCRIPT_OLD_HUNGARIAN:
/* Unicode-9.0 additions */ /* Unicode-9.0 additions */
case HB_SCRIPT_ADLAM: case HB_SCRIPT_ADLAM:
@ -545,6 +544,7 @@ hb_script_get_horizontal_direction (hb_script_t script)
/* https://github.com/harfbuzz/harfbuzz/issues/1000 */ /* https://github.com/harfbuzz/harfbuzz/issues/1000 */
case HB_SCRIPT_OLD_HUNGARIAN:
case HB_SCRIPT_OLD_ITALIC: case HB_SCRIPT_OLD_ITALIC:
case HB_SCRIPT_RUNIC: case HB_SCRIPT_RUNIC:

View File

@ -73,19 +73,6 @@ static_assert (true, "Just so we take semicolon after.")
#define DEFINE_NULL_INSTANCE(Type) \ #define DEFINE_NULL_INSTANCE(Type) \
const Type _hb_Null_##Type const Type _hb_Null_##Type
/* Specializaiton to disallow Null objects. */
#define DECLARE_NULL_DISALLOW(Type) \
template <> inline const Type& Null<Type> (void)
#define DECLARE_NULL_NAMSPACE_DISALLOW(Namespace, Type) \
} /* Close namespace. */ \
template <> \
/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
extern void *_hb_undefined; \
return *reinterpret_cast<const Namespace::Type *> (_hb_undefined); \
} \
namespace Namespace { \
static_assert (true, "Just so we take semicolon after.")
/* Global writable pool. Enlarge as necessary. */ /* Global writable pool. Enlarge as necessary. */
/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool /* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool

View File

@ -348,7 +348,7 @@ struct ResourceTypeRecord
protected: protected:
Tag tag; /* Resource type. */ Tag tag; /* Resource type. */
HBUINT16 resCountM1; /* Number of resources minus 1. */ HBUINT16 resCountM1; /* Number of resources minus 1. */
OffsetTo<UnsizedArrayOf<ResourceRecord> > OffsetTo<UnsizedArrayOf<ResourceRecord>, HBUINT16, false>
resourcesZ; /* Offset from beginning of resource type list resourcesZ; /* Offset from beginning of resource type list
* to reference item list for this type. */ * to reference item list for this type. */
public: public:
@ -387,10 +387,9 @@ struct ResourceMap
inline bool sanitize (hb_sanitize_context_t *c, const void *data_base) const inline bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
const void *type_base = &(this+typeList);
return_trace (c->check_struct (this) && return_trace (c->check_struct (this) &&
typeList.sanitize (c, this, typeList.sanitize (c, this,
type_base, &(this+typeList),
data_base)); data_base));
} }
@ -405,7 +404,7 @@ struct ResourceMap
HBUINT32 reserved1; /* Reserved for handle to next resource map */ HBUINT32 reserved1; /* Reserved for handle to next resource map */
HBUINT16 resreved2; /* Reserved for file reference number */ HBUINT16 resreved2; /* Reserved for file reference number */
HBUINT16 attrs; /* Resource fork attribute */ HBUINT16 attrs; /* Resource fork attribute */
OffsetTo<ArrayOfM1<ResourceTypeRecord> > OffsetTo<ArrayOfM1<ResourceTypeRecord>, HBUINT16, false>
typeList; /* Offset from beginning of map to typeList; /* Offset from beginning of map to
* resource type list */ * resource type list */
Offset16 nameList; /* Offset from beginning of map to Offset16 nameList; /* Offset from beginning of map to
@ -437,10 +436,10 @@ struct ResourceForkHeader
} }
protected: protected:
LOffsetTo<UnsizedArrayOf<HBUINT8> > LOffsetTo<UnsizedArrayOf<HBUINT8>, false>
data; /* Offset from beginning of resource fork data; /* Offset from beginning of resource fork
* to resource data */ * to resource data */
LOffsetTo<ResourceMap> LOffsetTo<ResourceMap, false>
map; /* Offset from beginning of resource fork map; /* Offset from beginning of resource fork
* to resource map */ * to resource map */
HBUINT32 dataLen; /* Length of resource data */ HBUINT32 dataLen; /* Length of resource data */

View File

@ -226,9 +226,14 @@ struct FixedVersion
* Use: (base+offset) * Use: (base+offset)
*/ */
template <typename Type, bool has_null_> struct assert_has_min_size { static_assert (Type::min_size > 0, ""); };
template <typename Type> struct assert_has_min_size<Type, false> {};
template <typename Type, typename OffsetType=HBUINT16, bool has_null=true> template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
struct OffsetTo : Offset<OffsetType, has_null> struct OffsetTo : Offset<OffsetType, has_null>
{ {
static_assert (sizeof (assert_has_min_size<Type, has_null>) || true, "");
inline const Type& operator () (const void *base) const inline const Type& operator () (const void *base) const
{ {
if (unlikely (this->is_null ())) return Null(Type); if (unlikely (this->is_null ())) return Null(Type);
@ -311,7 +316,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
} }
DEFINE_SIZE_STATIC (sizeof(OffsetType)); DEFINE_SIZE_STATIC (sizeof(OffsetType));
}; };
template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {}; template <typename Type, bool has_null=true> struct LOffsetTo : OffsetTo<Type, HBUINT32, has_null> {};
template <typename Base, typename OffsetType, bool has_null, typename Type> template <typename Base, typename OffsetType, bool has_null, typename Type>
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); } static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
template <typename Base, typename OffsetType, bool has_null, typename Type> template <typename Base, typename OffsetType, bool has_null, typename Type>

View File

@ -264,8 +264,6 @@ struct IndexSubtableArray
protected: protected:
UnsizedArrayOf<IndexSubtableRecord> indexSubtablesZ; UnsizedArrayOf<IndexSubtableRecord> indexSubtablesZ;
public:
DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
}; };
struct BitmapSizeTable struct BitmapSizeTable
@ -289,7 +287,7 @@ struct BitmapSizeTable
} }
protected: protected:
LOffsetTo<IndexSubtableArray> LOffsetTo<IndexSubtableArray, false>
indexSubtableArrayOffset; indexSubtableArrayOffset;
HBUINT32 indexTablesSize; HBUINT32 indexTablesSize;
HBUINT32 numberOfIndexSubtables; HBUINT32 numberOfIndexSubtables;

View File

@ -129,9 +129,9 @@ struct COLR
protected: protected:
HBUINT16 version; /* Table version number */ HBUINT16 version; /* Table version number */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records */ HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records */
LOffsetTo<UnsizedArrayOf<BaseGlyphRecord> > LOffsetTo<UnsizedArrayOf<BaseGlyphRecord>, false>
baseGlyphsZ; /* Offset to Base Glyph records. */ baseGlyphsZ; /* Offset to Base Glyph records. */
LOffsetTo<UnsizedArrayOf<LayerRecord> > LOffsetTo<UnsizedArrayOf<LayerRecord>, false>
layersZ; /* Offset to Layer Records */ layersZ; /* Offset to Layer Records */
HBUINT16 numLayers; /* Number of Layer Records */ HBUINT16 numLayers; /* Number of Layer Records */
public: public:

View File

@ -118,15 +118,15 @@ struct CPALV1Tail
} }
protected: protected:
LOffsetTo<UnsizedArrayOf<HBUINT32> > LOffsetTo<UnsizedArrayOf<HBUINT32>, false>
paletteFlagsZ; /* Offset from the beginning of CPAL table to paletteFlagsZ; /* Offset from the beginning of CPAL table to
* the Palette Type Array. Set to 0 if no array * the Palette Type Array. Set to 0 if no array
* is provided. */ * is provided. */
LOffsetTo<UnsizedArrayOf<HBUINT16> > LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
paletteLabelZ; /* Offset from the beginning of CPAL table to paletteLabelZ; /* Offset from the beginning of CPAL table to
* the Palette Labels Array. Set to 0 if no * the Palette Labels Array. Set to 0 if no
* array is provided. */ * array is provided. */
LOffsetTo<UnsizedArrayOf<HBUINT16> > LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
paletteEntryLabelZ; /* Offset from the beginning of CPAL table to paletteEntryLabelZ; /* Offset from the beginning of CPAL table to
* the Palette Entry Label Array. Set to 0 * the Palette Entry Label Array. Set to 0
* if no array is provided. */ * if no array is provided. */
@ -207,7 +207,7 @@ struct CPAL
HBUINT16 numPalettes; /* Number of palettes in the table. */ HBUINT16 numPalettes; /* Number of palettes in the table. */
HBUINT16 numColorRecords; /* Total number of color records, combined for HBUINT16 numColorRecords; /* Total number of color records, combined for
* all palettes. */ * all palettes. */
LOffsetTo<UnsizedArrayOf<BGRAColor> > LOffsetTo<UnsizedArrayOf<BGRAColor>, false>
colorRecordsZ; /* Offset from the beginning of CPAL table to colorRecordsZ; /* Offset from the beginning of CPAL table to
* the first ColorRecord. */ * the first ColorRecord. */
UnsizedArrayOf<HBUINT16> UnsizedArrayOf<HBUINT16>

View File

@ -54,7 +54,7 @@ struct SVGDocumentIndexEntry
* this index entry. */ * this index entry. */
HBUINT16 endGlyphID; /* The last glyph ID in the range described by HBUINT16 endGlyphID; /* The last glyph ID in the range described by
* this index entry. Must be >= startGlyphID. */ * this index entry. Must be >= startGlyphID. */
LOffsetTo<UnsizedArrayOf<HBUINT8> > LOffsetTo<UnsizedArrayOf<HBUINT8>, false>
svgDoc; /* Offset from the beginning of the SVG Document Index svgDoc; /* Offset from the beginning of the SVG Document Index
* to an SVG document. Must be non-zero. */ * to an SVG document. Must be non-zero. */
HBUINT32 svgDocLength; /* Length of the SVG document. HBUINT32 svgDocLength; /* Length of the SVG document.

View File

@ -70,6 +70,11 @@ namespace OT {
* Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
*/ */
struct Record_sanitize_closure_t {
hb_tag_t tag;
const void *list_base;
};
template <typename Type> template <typename Type>
struct Record struct Record
{ {
@ -77,14 +82,10 @@ struct Record
return tag.cmp (a); return tag.cmp (a);
} }
struct sanitize_closure_t {
hb_tag_t tag;
const void *list_base;
};
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
const sanitize_closure_t closure = {tag, base}; const Record_sanitize_closure_t closure = {tag, base};
return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure)); return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
} }
@ -240,7 +241,7 @@ struct LangSys
} }
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<LangSys>::sanitize_closure_t * = nullptr) const const Record_sanitize_closure_t * = nullptr) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && featureIndex.sanitize (c)); return_trace (c->check_struct (this) && featureIndex.sanitize (c));
@ -291,7 +292,7 @@ struct Script
} }
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<Script>::sanitize_closure_t * = nullptr) const const Record_sanitize_closure_t * = nullptr) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this)); return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
@ -526,6 +527,7 @@ struct FeatureParams
FeatureParamsStylisticSet stylisticSet; FeatureParamsStylisticSet stylisticSet;
FeatureParamsCharacterVariants characterVariants; FeatureParamsCharacterVariants characterVariants;
} u; } u;
public:
DEFINE_SIZE_STATIC (17); DEFINE_SIZE_STATIC (17);
}; };
@ -553,7 +555,7 @@ struct Feature
} }
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<Feature>::sanitize_closure_t *closure = nullptr) const const Record_sanitize_closure_t *closure = nullptr) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c)))) if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))

View File

@ -124,7 +124,7 @@ struct JstfPriority
struct JstfLangSys : OffsetListOf<JstfPriority> struct JstfLangSys : OffsetListOf<JstfPriority>
{ {
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<JstfLangSys>::sanitize_closure_t * = nullptr) const const Record_sanitize_closure_t * = nullptr) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (OffsetListOf<JstfPriority>::sanitize (c)); return_trace (OffsetListOf<JstfPriority>::sanitize (c));
@ -165,7 +165,7 @@ struct JstfScript
inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
inline bool sanitize (hb_sanitize_context_t *c, inline bool sanitize (hb_sanitize_context_t *c,
const Record<JstfScript>::sanitize_closure_t * = nullptr) const const Record_sanitize_closure_t * = nullptr) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (extenderGlyphs.sanitize (c, this) && return_trace (extenderGlyphs.sanitize (c, this) &&

View File

@ -245,7 +245,7 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
props |= UPROPS_MASK_HIDDEN; props |= UPROPS_MASK_HIDDEN;
} }
} }
else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat))) else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK (gen_cat)))
{ {
/* The above check is just an optimization to let in only things we need further /* The above check is just an optimization to let in only things we need further
* processing on. */ * processing on. */
@ -263,17 +263,7 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
* Also, all Mn's that are Default_Ignorable, have ccc=0, hence * Also, all Mn's that are Default_Ignorable, have ccc=0, hence
* the "else if". * the "else if".
*/ */
props |= unicode->modified_combining_class (info->codepoint)<<8; props |= unicode->modified_combining_class (u)<<8;
/* Recategorize emoji skin-tone modifiers as Unicode mark, so they
* behave correctly in non-native directionality. They originally
* are MODIFIER_SYMBOL. Fixes:
* https://github.com/harfbuzz/harfbuzz/issues/169
*/
if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
{
props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
}
} }
} }

View File

@ -102,23 +102,42 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
} }
inline hb_unicode_general_category_t
modified_general_category (hb_codepoint_t u)
{
hb_unicode_general_category_t cat = general_category (u);
if (unlikely (cat == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL))
{
/* Recategorize emoji skin-tone modifiers as Unicode mark, so they
* behave correctly in non-native directionality. They originally
* are MODIFIER_SYMBOL. Fixes:
* https://github.com/harfbuzz/harfbuzz/issues/169
*/
if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1F3FBu, 0x1F3FFu)))
cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
}
return cat;
}
inline unsigned int inline unsigned int
modified_combining_class (hb_codepoint_t unicode) modified_combining_class (hb_codepoint_t u)
{ {
/* XXX This hack belongs to the Myanmar shaper. */ /* XXX This hack belongs to the Myanmar shaper. */
if (unlikely (unicode == 0x1037u)) unicode = 0x103Au; if (unlikely (u == 0x1037u)) u = 0x103Au;
/* XXX This hack belongs to the USE shaper (for Tai Tham): /* XXX This hack belongs to the USE shaper (for Tai Tham):
* Reorder SAKOT to ensure it comes after any tone marks. */ * Reorder SAKOT to ensure it comes after any tone marks. */
if (unlikely (unicode == 0x1A60u)) return 254; if (unlikely (u == 0x1A60u)) return 254;
/* XXX This hack belongs to the Tibetan shaper: /* XXX This hack belongs to the Tibetan shaper:
* Reorder PADMA to ensure it comes after any vowel marks. */ * Reorder PADMA to ensure it comes after any vowel marks. */
if (unlikely (unicode == 0x0FC6u)) return 254; if (unlikely (u == 0x0FC6u)) return 254;
/* Reorder TSA -PHRU to reorder before U+0F74 */ /* Reorder TSA -PHRU to reorder before U+0F74 */
if (unlikely (unicode == 0x0F39u)) return 127; if (unlikely (u == 0x0F39u)) return 127;
return _hb_modified_combining_class[combining_class (unicode)]; return _hb_modified_combining_class[combining_class (u)];
} }
static inline hb_bool_t static inline hb_bool_t
@ -360,10 +379,9 @@ DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \ FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL(gen_cat) \ #define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK(gen_cat) \
(FLAG_UNSAFE (gen_cat) & \ (FLAG_UNSAFE (gen_cat) & \
(FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \ (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL)))
#endif /* HB_UNICODE_HH */ #endif /* HB_UNICODE_HH */