Merge branch 'master' into cff-subset
This commit is contained in:
commit
d050ab8d3e
|
@ -761,11 +761,16 @@ endif ()
|
|||
|
||||
if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
||||
install(TARGETS harfbuzz
|
||||
EXPORT harfbuzzConfig
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
FRAMEWORK DESTINATION Library/Frameworks
|
||||
)
|
||||
install(EXPORT harfbuzzConfig
|
||||
NAMESPACE harfbuzz::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/harfbuzz
|
||||
)
|
||||
if (HB_BUILD_UTILS)
|
||||
install(TARGETS hb-view
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
|
|
|
@ -243,7 +243,7 @@ struct LookupSegmentArray
|
|||
|
||||
GlyphID last; /* Last 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
|
||||
* the table to the data. */
|
||||
public:
|
||||
|
@ -439,10 +439,23 @@ struct Entry<void>
|
|||
template <typename Extra>
|
||||
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
|
||||
{
|
||||
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
|
||||
|
@ -509,11 +522,11 @@ struct StateTable
|
|||
protected:
|
||||
HBUINT32 nClasses; /* Number of classes, which is the number of indices
|
||||
* in a single line in the state array. */
|
||||
LOffsetTo<Lookup<HBUINT16> >
|
||||
LOffsetTo<Lookup<HBUINT16>, false>
|
||||
classTable; /* Offset to the class table. */
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT16> >
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
|
||||
stateArrayTable;/* Offset to the state array. */
|
||||
LOffsetTo<UnsizedArrayOf<Entry<Extra> > >
|
||||
LOffsetTo<UnsizedArrayOf<Entry<Extra> >, false>
|
||||
entryTable; /* Offset to the entry array. */
|
||||
|
||||
public:
|
||||
|
@ -538,13 +551,13 @@ struct StateTableDriver
|
|||
if (!c->in_place)
|
||||
buffer->clear_output ();
|
||||
|
||||
unsigned int state = 0;
|
||||
unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT;
|
||||
bool last_was_dont_advance = false;
|
||||
for (buffer->idx = 0;;)
|
||||
{
|
||||
unsigned int klass = buffer->idx < buffer->len ?
|
||||
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);
|
||||
if (unlikely (!entry))
|
||||
break;
|
||||
|
|
|
@ -78,7 +78,7 @@ struct FeatureName
|
|||
protected:
|
||||
HBUINT16 feature; /* Feature type. */
|
||||
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
|
||||
* this feature's setting name array. The actual type of
|
||||
* record this offset refers to will depend on the
|
||||
|
|
|
@ -50,7 +50,8 @@ struct RearrangementSubtable
|
|||
struct driver_context_t
|
||||
{
|
||||
static const bool in_place = true;
|
||||
enum Flags {
|
||||
enum Flags
|
||||
{
|
||||
MarkFirst = 0x8000, /* If set, make the current glyph the first
|
||||
* glyph to be rearranged. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph
|
||||
|
@ -196,7 +197,8 @@ struct ContextualSubtable
|
|||
struct driver_context_t
|
||||
{
|
||||
static const bool in_place = true;
|
||||
enum Flags {
|
||||
enum Flags
|
||||
{
|
||||
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
|
||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||
* going to the new state. */
|
||||
|
@ -309,7 +311,7 @@ struct ContextualSubtable
|
|||
protected:
|
||||
StateTable<EntryData>
|
||||
machine;
|
||||
LOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> >
|
||||
LOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32>, false>
|
||||
substitutionTables;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (20);
|
||||
|
@ -329,7 +331,8 @@ struct LigatureSubtable
|
|||
struct driver_context_t
|
||||
{
|
||||
static const bool in_place = false;
|
||||
enum Flags {
|
||||
enum Flags
|
||||
{
|
||||
SetComponent = 0x8000, /* Push this glyph onto the component stack for
|
||||
* eventual processing. */
|
||||
DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
|
||||
|
@ -338,7 +341,8 @@ struct LigatureSubtable
|
|||
* group. */
|
||||
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
|
||||
* implies storage. */
|
||||
LigActionStore = 0x40000000, /* Store the ligature at the current cumulated index
|
||||
|
@ -469,11 +473,11 @@ struct LigatureSubtable
|
|||
protected:
|
||||
StateTable<EntryData>
|
||||
machine;
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT32> >
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT32>, false>
|
||||
ligAction; /* Offset to the ligature action table. */
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT16> >
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
|
||||
component; /* Offset to the component table. */
|
||||
LOffsetTo<UnsizedArrayOf<GlyphID> >
|
||||
LOffsetTo<UnsizedArrayOf<GlyphID>, false>
|
||||
ligature; /* Offset to the actual ligature lists. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (28);
|
||||
|
@ -517,19 +521,186 @@ struct NoncontextualSubtable
|
|||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
/* TODO */
|
||||
return_trace (true);
|
||||
/* The rest of array sanitizations are done at run-time. */
|
||||
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_type (void) const { return coverage & 0xFF; }
|
||||
|
||||
enum Type {
|
||||
enum Type
|
||||
{
|
||||
Rearrangement = 0,
|
||||
Contextual = 1,
|
||||
Ligature = 2,
|
||||
|
@ -569,11 +741,6 @@ struct ChainSubtable
|
|||
Insertion = 5
|
||||
};
|
||||
|
||||
inline void apply (hb_aat_apply_context_t *c) const
|
||||
{
|
||||
dispatch (c);
|
||||
}
|
||||
|
||||
template <typename context_t>
|
||||
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
|
||||
{
|
||||
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);
|
||||
unsigned int count = subtableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
|
||||
{
|
||||
c->set_lookup_index (c->lookup_index + 1);
|
||||
continue;
|
||||
}
|
||||
if (!(subtable->subFeatureFlags & flags))
|
||||
goto skip;
|
||||
|
||||
subtable->apply (c);
|
||||
subtable = &StructAfter<ChainSubtable> (*subtable);
|
||||
if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
|
||||
goto skip;
|
||||
|
||||
subtable->dispatch (c);
|
||||
|
||||
(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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (!length.sanitize (c) ||
|
||||
|
@ -671,7 +855,7 @@ struct Chain
|
|||
|
||||
UnsizedArrayOf<Feature> featureZ; /* Features. */
|
||||
/*ChainSubtable firstSubtable;*//* Subtables. */
|
||||
/*subtableGlyphCoverageArray*/ /* Only if major == 3. */
|
||||
/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_MIN (16);
|
||||
|
@ -701,8 +885,7 @@ struct morx
|
|||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!version.sanitize (c) ||
|
||||
(version.major >> (sizeof (HBUINT32) == 4 ? 1 : 0)) != 1 ||
|
||||
if (!version.sanitize (c) || version < 2 ||
|
||||
!chainCount.sanitize (c))
|
||||
return_trace (false);
|
||||
|
||||
|
@ -710,7 +893,7 @@ struct morx
|
|||
unsigned int count = chainCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (!chain->sanitize (c, version.major))
|
||||
if (!chain->sanitize (c, version))
|
||||
return_trace (false);
|
||||
chain = &StructAfter<Chain> (*chain);
|
||||
}
|
||||
|
@ -719,8 +902,9 @@ struct morx
|
|||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version number of the glyph metamorphosis table.
|
||||
* 1 for mort, 2 or 3 for morx. */
|
||||
HBUINT16 version; /* Version number of the glyph metamorphosis table.
|
||||
* 2 or 3. */
|
||||
HBUINT16 unused; /* Set to 0. */
|
||||
HBUINT32 chainCount; /* Number of metamorphosis chains contained in this
|
||||
* table. */
|
||||
Chain firstChain; /* Chains. */
|
||||
|
|
|
@ -68,7 +68,7 @@ struct TrackTableEntry
|
|||
protected:
|
||||
Fixed track; /* Track value for this record. */
|
||||
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
|
||||
* per-size tracking values for this track. */
|
||||
|
||||
|
@ -134,7 +134,7 @@ struct TrackData
|
|||
protected:
|
||||
HBUINT16 nTracks; /* Number of separate tracks 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. */
|
||||
UnsizedArrayOf<TrackTableEntry>
|
||||
trackTable; /* Array[nTracks] of TrackTableEntry records. */
|
||||
|
|
|
@ -46,7 +46,7 @@ struct FTStringRange
|
|||
}
|
||||
|
||||
protected:
|
||||
OffsetTo<UnsizedArrayOf<HBUINT8> >
|
||||
OffsetTo<UnsizedArrayOf<HBUINT8>, HBUINT16, false>
|
||||
tag; /* Offset from the start of the table to
|
||||
* the beginning of the string */
|
||||
HBUINT16 length; /* String length (in bytes) */
|
||||
|
|
|
@ -531,7 +531,6 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
|||
|
||||
/* Unicode-8.0 additions */
|
||||
case HB_SCRIPT_HATRAN:
|
||||
case HB_SCRIPT_OLD_HUNGARIAN:
|
||||
|
||||
/* Unicode-9.0 additions */
|
||||
case HB_SCRIPT_ADLAM:
|
||||
|
@ -545,6 +544,7 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
|||
|
||||
|
||||
/* https://github.com/harfbuzz/harfbuzz/issues/1000 */
|
||||
case HB_SCRIPT_OLD_HUNGARIAN:
|
||||
case HB_SCRIPT_OLD_ITALIC:
|
||||
case HB_SCRIPT_RUNIC:
|
||||
|
||||
|
|
|
@ -73,19 +73,6 @@ static_assert (true, "Just so we take semicolon after.")
|
|||
#define DEFINE_NULL_INSTANCE(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. */
|
||||
|
||||
/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
|
||||
|
|
|
@ -348,7 +348,7 @@ struct ResourceTypeRecord
|
|||
protected:
|
||||
Tag tag; /* Resource type. */
|
||||
HBUINT16 resCountM1; /* Number of resources minus 1. */
|
||||
OffsetTo<UnsizedArrayOf<ResourceRecord> >
|
||||
OffsetTo<UnsizedArrayOf<ResourceRecord>, HBUINT16, false>
|
||||
resourcesZ; /* Offset from beginning of resource type list
|
||||
* to reference item list for this type. */
|
||||
public:
|
||||
|
@ -387,10 +387,9 @@ struct ResourceMap
|
|||
inline bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
const void *type_base = &(this+typeList);
|
||||
return_trace (c->check_struct (this) &&
|
||||
typeList.sanitize (c, this,
|
||||
type_base,
|
||||
&(this+typeList),
|
||||
data_base));
|
||||
}
|
||||
|
||||
|
@ -405,7 +404,7 @@ struct ResourceMap
|
|||
HBUINT32 reserved1; /* Reserved for handle to next resource map */
|
||||
HBUINT16 resreved2; /* Reserved for file reference number */
|
||||
HBUINT16 attrs; /* Resource fork attribute */
|
||||
OffsetTo<ArrayOfM1<ResourceTypeRecord> >
|
||||
OffsetTo<ArrayOfM1<ResourceTypeRecord>, HBUINT16, false>
|
||||
typeList; /* Offset from beginning of map to
|
||||
* resource type list */
|
||||
Offset16 nameList; /* Offset from beginning of map to
|
||||
|
@ -437,10 +436,10 @@ struct ResourceForkHeader
|
|||
}
|
||||
|
||||
protected:
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT8> >
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT8>, false>
|
||||
data; /* Offset from beginning of resource fork
|
||||
* to resource data */
|
||||
LOffsetTo<ResourceMap>
|
||||
LOffsetTo<ResourceMap, false>
|
||||
map; /* Offset from beginning of resource fork
|
||||
* to resource map */
|
||||
HBUINT32 dataLen; /* Length of resource data */
|
||||
|
|
|
@ -226,9 +226,14 @@ struct FixedVersion
|
|||
* 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>
|
||||
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
|
||||
{
|
||||
if (unlikely (this->is_null ())) return Null(Type);
|
||||
|
@ -311,7 +316,7 @@ struct OffsetTo : Offset<OffsetType, has_null>
|
|||
}
|
||||
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>
|
||||
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>
|
||||
|
|
|
@ -264,8 +264,6 @@ struct IndexSubtableArray
|
|||
|
||||
protected:
|
||||
UnsizedArrayOf<IndexSubtableRecord> indexSubtablesZ;
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
|
||||
};
|
||||
|
||||
struct BitmapSizeTable
|
||||
|
@ -289,7 +287,7 @@ struct BitmapSizeTable
|
|||
}
|
||||
|
||||
protected:
|
||||
LOffsetTo<IndexSubtableArray>
|
||||
LOffsetTo<IndexSubtableArray, false>
|
||||
indexSubtableArrayOffset;
|
||||
HBUINT32 indexTablesSize;
|
||||
HBUINT32 numberOfIndexSubtables;
|
||||
|
|
|
@ -129,9 +129,9 @@ struct COLR
|
|||
protected:
|
||||
HBUINT16 version; /* Table version number */
|
||||
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records */
|
||||
LOffsetTo<UnsizedArrayOf<BaseGlyphRecord> >
|
||||
LOffsetTo<UnsizedArrayOf<BaseGlyphRecord>, false>
|
||||
baseGlyphsZ; /* Offset to Base Glyph records. */
|
||||
LOffsetTo<UnsizedArrayOf<LayerRecord> >
|
||||
LOffsetTo<UnsizedArrayOf<LayerRecord>, false>
|
||||
layersZ; /* Offset to Layer Records */
|
||||
HBUINT16 numLayers; /* Number of Layer Records */
|
||||
public:
|
||||
|
|
|
@ -118,15 +118,15 @@ struct CPALV1Tail
|
|||
}
|
||||
|
||||
protected:
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT32> >
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT32>, false>
|
||||
paletteFlagsZ; /* Offset from the beginning of CPAL table to
|
||||
* the Palette Type Array. Set to 0 if no array
|
||||
* is provided. */
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT16> >
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
|
||||
paletteLabelZ; /* Offset from the beginning of CPAL table to
|
||||
* the Palette Labels Array. Set to 0 if no
|
||||
* array is provided. */
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT16> >
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
|
||||
paletteEntryLabelZ; /* Offset from the beginning of CPAL table to
|
||||
* the Palette Entry Label Array. Set to 0
|
||||
* if no array is provided. */
|
||||
|
@ -207,7 +207,7 @@ struct CPAL
|
|||
HBUINT16 numPalettes; /* Number of palettes in the table. */
|
||||
HBUINT16 numColorRecords; /* Total number of color records, combined for
|
||||
* all palettes. */
|
||||
LOffsetTo<UnsizedArrayOf<BGRAColor> >
|
||||
LOffsetTo<UnsizedArrayOf<BGRAColor>, false>
|
||||
colorRecordsZ; /* Offset from the beginning of CPAL table to
|
||||
* the first ColorRecord. */
|
||||
UnsizedArrayOf<HBUINT16>
|
||||
|
|
|
@ -54,7 +54,7 @@ struct SVGDocumentIndexEntry
|
|||
* this index entry. */
|
||||
HBUINT16 endGlyphID; /* The last glyph ID in the range described by
|
||||
* this index entry. Must be >= startGlyphID. */
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT8> >
|
||||
LOffsetTo<UnsizedArrayOf<HBUINT8>, false>
|
||||
svgDoc; /* Offset from the beginning of the SVG Document Index
|
||||
* to an SVG document. Must be non-zero. */
|
||||
HBUINT32 svgDocLength; /* Length of the SVG document.
|
||||
|
|
|
@ -70,6 +70,11 @@ namespace OT {
|
|||
* Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
|
||||
*/
|
||||
|
||||
struct Record_sanitize_closure_t {
|
||||
hb_tag_t tag;
|
||||
const void *list_base;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct Record
|
||||
{
|
||||
|
@ -77,14 +82,10 @@ struct Record
|
|||
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
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -240,7 +241,7 @@ struct LangSys
|
|||
}
|
||||
|
||||
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);
|
||||
return_trace (c->check_struct (this) && featureIndex.sanitize (c));
|
||||
|
@ -291,7 +292,7 @@ struct Script
|
|||
}
|
||||
|
||||
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);
|
||||
return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
|
||||
|
@ -526,6 +527,7 @@ struct FeatureParams
|
|||
FeatureParamsStylisticSet stylisticSet;
|
||||
FeatureParamsCharacterVariants characterVariants;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (17);
|
||||
};
|
||||
|
||||
|
@ -553,7 +555,7 @@ struct Feature
|
|||
}
|
||||
|
||||
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);
|
||||
if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
|
||||
|
|
|
@ -124,7 +124,7 @@ struct JstfPriority
|
|||
struct JstfLangSys : OffsetListOf<JstfPriority>
|
||||
{
|
||||
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);
|
||||
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 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);
|
||||
return_trace (extenderGlyphs.sanitize (c, this) &&
|
||||
|
|
|
@ -245,7 +245,7 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
|
|||
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
|
||||
* 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
|
||||
* the "else if".
|
||||
*/
|
||||
props |= unicode->modified_combining_class (info->codepoint)<<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;
|
||||
}
|
||||
props |= unicode->modified_combining_class (u)<<8;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
modified_combining_class (hb_codepoint_t unicode)
|
||||
modified_combining_class (hb_codepoint_t u)
|
||||
{
|
||||
/* 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):
|
||||
* 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:
|
||||
* 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 */
|
||||
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
|
||||
|
@ -360,10 +379,9 @@ DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
|
|||
FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_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 (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL)))
|
||||
FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
|
||||
|
||||
#endif /* HB_UNICODE_HH */
|
||||
|
|
Loading…
Reference in New Issue