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)
|
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}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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) */
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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))))
|
||||||
|
|
|
@ -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) &&
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue