Merge pull request #3704 from harfbuzz/64k

Towards breaking the 64k in GSUB/GPOS
This commit is contained in:
Behdad Esfahbod 2022-07-13 14:58:09 -06:00 committed by GitHub
commit 87167acfe3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 894 additions and 394 deletions

View File

@ -12,7 +12,10 @@ struct MarkBasePos
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
MarkBasePosFormat1 format1; MarkBasePosFormat1_2<SmallTypes> format1;
#ifndef HB_NO_BORING_EXPANSION
MarkBasePosFormat1_2<MediumTypes> format2;
#endif
} u; } u;
public: public:
@ -23,6 +26,9 @@ struct MarkBasePos
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }

View File

@ -12,26 +12,27 @@ typedef AnchorMatrix BaseArray; /* base-major--
* mark-minor-- * mark-minor--
* ordered by class--zero-based. */ * ordered by class--zero-based. */
struct MarkBasePosFormat1 template <typename Types>
struct MarkBasePosFormat1_2
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 1 */ HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
markCoverage; /* Offset to MarkCoverage table--from markCoverage; /* Offset to MarkCoverage table--from
* beginning of MarkBasePos subtable */ * beginning of MarkBasePos subtable */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
baseCoverage; /* Offset to BaseCoverage table--from baseCoverage; /* Offset to BaseCoverage table--from
* beginning of MarkBasePos subtable */ * beginning of MarkBasePos subtable */
HBUINT16 classCount; /* Number of classes defined for marks */ HBUINT16 classCount; /* Number of classes defined for marks */
Offset16To<MarkArray> typename Types::template OffsetTo<MarkArray>
markArray; /* Offset to MarkArray table--from markArray; /* Offset to MarkArray table--from
* beginning of MarkBasePos subtable */ * beginning of MarkBasePos subtable */
Offset16To<BaseArray> typename Types::template OffsetTo<BaseArray>
baseArray; /* Offset to BaseArray table--from baseArray; /* Offset to BaseArray table--from
* beginning of MarkBasePos subtable */ * beginning of MarkBasePos subtable */
public: public:
DEFINE_SIZE_STATIC (12); DEFINE_SIZE_STATIC (4 + 4 * Types::size);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {

View File

@ -12,7 +12,10 @@ struct MarkLigPos
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
MarkLigPosFormat1 format1; MarkLigPosFormat1_2<SmallTypes> format1;
#ifndef HB_NO_BORING_EXPANSION
MarkLigPosFormat1_2<MediumTypes> format2;
#endif
} u; } u;
public: public:
@ -23,6 +26,9 @@ struct MarkLigPos
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }

View File

@ -8,26 +8,27 @@ namespace Layout {
namespace GPOS_impl { namespace GPOS_impl {
struct MarkLigPosFormat1 template <typename Types>
struct MarkLigPosFormat1_2
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 1 */ HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
markCoverage; /* Offset to Mark Coverage table--from markCoverage; /* Offset to Mark Coverage table--from
* beginning of MarkLigPos subtable */ * beginning of MarkLigPos subtable */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
ligatureCoverage; /* Offset to Ligature Coverage ligatureCoverage; /* Offset to Ligature Coverage
* table--from beginning of MarkLigPos * table--from beginning of MarkLigPos
* subtable */ * subtable */
HBUINT16 classCount; /* Number of defined mark classes */ HBUINT16 classCount; /* Number of defined mark classes */
Offset16To<MarkArray> typename Types::template OffsetTo<MarkArray>
markArray; /* Offset to MarkArray table--from markArray; /* Offset to MarkArray table--from
* beginning of MarkLigPos subtable */ * beginning of MarkLigPos subtable */
Offset16To<LigatureArray> typename Types::template OffsetTo<LigatureArray>
ligatureArray; /* Offset to LigatureArray table--from ligatureArray; /* Offset to LigatureArray table--from
* beginning of MarkLigPos subtable */ * beginning of MarkLigPos subtable */
public: public:
DEFINE_SIZE_STATIC (12); DEFINE_SIZE_STATIC (4 + 4 * Types::size);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {

View File

@ -12,7 +12,10 @@ struct MarkMarkPos
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
MarkMarkPosFormat1 format1; MarkMarkPosFormat1_2<SmallTypes> format1;
#ifndef HB_NO_BORING_EXPANSION
MarkMarkPosFormat1_2<MediumTypes> format2;
#endif
} u; } u;
public: public:
@ -23,6 +26,9 @@ struct MarkMarkPos
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }

View File

@ -12,27 +12,28 @@ typedef AnchorMatrix Mark2Array; /* mark2-major--
* mark1-minor-- * mark1-minor--
* ordered by class--zero-based. */ * ordered by class--zero-based. */
struct MarkMarkPosFormat1 template <typename Types>
struct MarkMarkPosFormat1_2
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 1 */ HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
mark1Coverage; /* Offset to Combining Mark1 Coverage mark1Coverage; /* Offset to Combining Mark1 Coverage
* table--from beginning of MarkMarkPos * table--from beginning of MarkMarkPos
* subtable */ * subtable */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
mark2Coverage; /* Offset to Combining Mark2 Coverage mark2Coverage; /* Offset to Combining Mark2 Coverage
* table--from beginning of MarkMarkPos * table--from beginning of MarkMarkPos
* subtable */ * subtable */
HBUINT16 classCount; /* Number of defined mark classes */ HBUINT16 classCount; /* Number of defined mark classes */
Offset16To<MarkArray> typename Types::template OffsetTo<MarkArray>
mark1Array; /* Offset to Mark1Array table--from mark1Array; /* Offset to Mark1Array table--from
* beginning of MarkMarkPos subtable */ * beginning of MarkMarkPos subtable */
Offset16To<Mark2Array> typename Types::template OffsetTo<Mark2Array>
mark2Array; /* Offset to Mark2Array table--from mark2Array; /* Offset to Mark2Array table--from
* beginning of MarkMarkPos subtable */ * beginning of MarkMarkPos subtable */
public: public:
DEFINE_SIZE_STATIC (12); DEFINE_SIZE_STATIC (4 + 4 * Types::size);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {

View File

@ -13,8 +13,12 @@ struct PairPos
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
PairPosFormat1 format1; PairPosFormat1_3<SmallTypes> format1;
PairPosFormat2 format2; PairPosFormat2_4<SmallTypes> format2;
#ifndef HB_NO_BORING_EXPANSION
PairPosFormat1_3<MediumTypes> format3;
PairPosFormat2_4<MediumTypes> format4;
#endif
} u; } u;
public: public:
@ -26,6 +30,10 @@ struct PairPos
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }

View File

@ -8,11 +8,15 @@ namespace Layout {
namespace GPOS_impl { namespace GPOS_impl {
struct PairPosFormat1 template <typename Types>
struct PairPosFormat1_3
{ {
using PairSet = GPOS_impl::PairSet<Types>;
using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
protected: protected:
HBUINT16 format; /* Format identifier--format = 1 */ HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from coverage; /* Offset to Coverage table--from
* beginning of subtable */ * beginning of subtable */
ValueFormat valueFormat[2]; /* [0] Defines the types of data in ValueFormat valueFormat[2]; /* [0] Defines the types of data in
@ -21,11 +25,11 @@ struct PairPosFormat1
/* [1] Defines the types of data in /* [1] Defines the types of data in
* ValueRecord2--for the second glyph * ValueRecord2--for the second glyph
* in the pair--may be zero (0) */ * in the pair--may be zero (0) */
Array16OfOffset16To<PairSet> Array16Of<typename Types::template OffsetTo<PairSet>>
pairSet; /* Array of PairSet tables pairSet; /* Array of PairSet tables
* ordered by Coverage Index */ * ordered by Coverage Index */
public: public:
DEFINE_SIZE_ARRAY (10, pairSet); DEFINE_SIZE_ARRAY (8 + Types::size, pairSet);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {
@ -35,7 +39,7 @@ struct PairPosFormat1
unsigned int len1 = valueFormat[0].get_len (); unsigned int len1 = valueFormat[0].get_len ();
unsigned int len2 = valueFormat[1].get_len (); unsigned int len2 = valueFormat[1].get_len ();
PairSet::sanitize_closure_t closure = typename PairSet::sanitize_closure_t closure =
{ {
valueFormat, valueFormat,
len1, len1,
@ -51,7 +55,7 @@ struct PairPosFormat1
+ hb_zip (this+coverage, pairSet) + hb_zip (this+coverage, pairSet)
| hb_filter (*glyphs, hb_first) | hb_filter (*glyphs, hb_first)
| hb_map (hb_second) | hb_map (hb_second)
| hb_map ([glyphs, this] (const Offset16To<PairSet> &_) | hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
{ return (this+_).intersects (glyphs, valueFormat); }) { return (this+_).intersects (glyphs, valueFormat); })
| hb_any | hb_any
; ;
@ -127,7 +131,7 @@ struct PairPosFormat1
+ hb_zip (this+coverage, pairSet) + hb_zip (this+coverage, pairSet)
| hb_filter (glyphset, hb_first) | hb_filter (glyphset, hb_first)
| hb_filter ([this, c, out] (const Offset16To<PairSet>& _) | hb_filter ([this, c, out] (const typename Types::template OffsetTo<PairSet>& _)
{ {
auto snap = c->serializer->snapshot (); auto snap = c->serializer->snapshot ();
auto *o = out->pairSet.serialize_append (c->serializer); auto *o = out->pairSet.serialize_append (c->serializer);
@ -160,7 +164,7 @@ struct PairPosFormat1
unsigned format1 = 0; unsigned format1 = 0;
unsigned format2 = 0; unsigned format2 = 0;
for (const Offset16To<PairSet>& _ : for (const auto & _ :
+ hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second)) + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
{ {
const PairSet& set = (this + _); const PairSet& set = (this + _);

View File

@ -7,11 +7,12 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GPOS_impl { namespace GPOS_impl {
struct PairPosFormat2 template <typename Types>
struct PairPosFormat2_4
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 2 */ HBUINT16 format; /* Format identifier--format = 2 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from coverage; /* Offset to Coverage table--from
* beginning of subtable */ * beginning of subtable */
ValueFormat valueFormat1; /* ValueRecord definition--for the ValueFormat valueFormat1; /* ValueRecord definition--for the
@ -20,11 +21,11 @@ struct PairPosFormat2
ValueFormat valueFormat2; /* ValueRecord definition--for the ValueFormat valueFormat2; /* ValueRecord definition--for the
* second glyph of the pair--may be * second glyph of the pair--may be
* zero (0) */ * zero (0) */
Offset16To<ClassDef> typename Types::template OffsetTo<ClassDef>
classDef1; /* Offset to ClassDef table--from classDef1; /* Offset to ClassDef table--from
* beginning of PairPos subtable--for * beginning of PairPos subtable--for
* the first glyph of the pair */ * the first glyph of the pair */
Offset16To<ClassDef> typename Types::template OffsetTo<ClassDef>
classDef2; /* Offset to ClassDef table--from classDef2; /* Offset to ClassDef table--from
* beginning of PairPos subtable--for * beginning of PairPos subtable--for
* the second glyph of the pair */ * the second glyph of the pair */
@ -36,7 +37,7 @@ struct PairPosFormat2
* class1-major, class2-minor, * class1-major, class2-minor,
* Each entry has value1 and value2 */ * Each entry has value1 and value2 */
public: public:
DEFINE_SIZE_ARRAY (16, values); DEFINE_SIZE_ARRAY (10 + 3 * Types::size, values);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {

View File

@ -8,9 +8,13 @@ namespace Layout {
namespace GPOS_impl { namespace GPOS_impl {
template <typename Types>
struct PairSet struct PairSet
{ {
friend struct PairPosFormat1; template <typename Types2>
friend struct PairPosFormat1_3;
using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
protected: protected:
HBUINT16 len; /* Number of PairValueRecords */ HBUINT16 len; /* Number of PairValueRecords */
@ -136,7 +140,7 @@ struct PairSet
unsigned len2 = valueFormats[1].get_len (); unsigned len2 = valueFormats[1].get_len ();
unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
PairValueRecord::context_t context = typename PairValueRecord::context_t context =
{ {
this, this,
valueFormats, valueFormats,

View File

@ -6,18 +6,21 @@ namespace Layout {
namespace GPOS_impl { namespace GPOS_impl {
template <typename Types>
struct PairValueRecord struct PairValueRecord
{ {
template <typename Types2>
friend struct PairSet; friend struct PairSet;
protected: protected:
HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the typename Types::HBGlyphID
secondGlyph; /* GlyphID of second glyph in the
* pair--first glyph is listed in the * pair--first glyph is listed in the
* Coverage table */ * Coverage table */
ValueRecord values; /* Positioning data for the first glyph ValueRecord values; /* Positioning data for the first glyph
* followed by for second glyph */ * followed by for second glyph */
public: public:
DEFINE_SIZE_ARRAY (2, values); DEFINE_SIZE_ARRAY (Types::size, values);
int cmp (hb_codepoint_t k) const int cmp (hb_codepoint_t k) const
{ return secondGlyph.cmp (k); } { return secondGlyph.cmp (k); }

View File

@ -7,10 +7,11 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
template <typename Types>
struct AlternateSet struct AlternateSet
{ {
protected: protected:
Array16Of<HBGlyphID16> Array16Of<typename Types::HBGlyphID>
alternates; /* Array of alternate GlyphIDs--in alternates; /* Array of alternate GlyphIDs--in
* arbitrary order */ * arbitrary order */
public: public:

View File

@ -13,7 +13,10 @@ struct AlternateSubst
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
AlternateSubstFormat1 format1; AlternateSubstFormat1_2<SmallTypes> format1;
#ifndef HB_NO_BORING_EXPANSION
AlternateSubstFormat1_2<MediumTypes> format2;
#endif
} u; } u;
public: public:
@ -24,10 +27,15 @@ struct AlternateSubst
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }
/* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
* iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
bool serialize (hb_serialize_context_t *c, bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const HBGlyphID16> glyphs, hb_sorted_array_t<const HBGlyphID16> glyphs,
hb_array_t<const unsigned int> alternate_len_list, hb_array_t<const unsigned int> alternate_len_list,
@ -42,6 +50,9 @@ struct AlternateSubst
default:return_trace (false); default:return_trace (false);
} }
} }
/* TODO subset() should choose format. */
}; };
} }

View File

@ -8,18 +8,19 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
struct AlternateSubstFormat1 template <typename Types>
struct AlternateSubstFormat1_2
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 1 */ HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from coverage; /* Offset to Coverage table--from
* beginning of Substitution table */ * beginning of Substitution table */
Array16OfOffset16To<AlternateSet> Array16Of<typename Types::template OffsetTo<AlternateSet<Types>>>
alternateSet; /* Array of AlternateSet tables alternateSet; /* Array of AlternateSet tables
* ordered by Coverage Index */ * ordered by Coverage Index */
public: public:
DEFINE_SIZE_ARRAY (6, alternateSet); DEFINE_SIZE_ARRAY (2 + 2 * Types::size, alternateSet);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {
@ -39,7 +40,7 @@ struct AlternateSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first) | hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second) | hb_map (hb_second)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([c] (const AlternateSet &_) { _.closure (c); }) | hb_apply ([c] (const AlternateSet<Types> &_) { _.closure (c); })
; ;
} }
@ -52,7 +53,7 @@ struct AlternateSubstFormat1
+ hb_zip (this+coverage, alternateSet) + hb_zip (this+coverage, alternateSet)
| hb_map (hb_second) | hb_map (hb_second)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); }) | hb_apply ([c] (const AlternateSet<Types> &_) { _.collect_glyphs (c); })
; ;
} }

View File

@ -7,16 +7,18 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
template <typename Types>
struct Ligature struct Ligature
{ {
protected: protected:
HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */ typename Types::HBGlyphID
HeadlessArrayOf<HBGlyphID16> ligGlyph; /* GlyphID of ligature to substitute */
HeadlessArrayOf<typename Types::HBGlyphID>
component; /* Array of component GlyphIDs--start component; /* Array of component GlyphIDs--start
* with the second component--ordered * with the second component--ordered
* in writing direction */ * in writing direction */
public: public:
DEFINE_SIZE_ARRAY (4, component); DEFINE_SIZE_ARRAY (Types::size + 2, component);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {

View File

@ -8,10 +8,11 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
template <typename Types>
struct LigatureSet struct LigatureSet
{ {
protected: protected:
Array16OfOffset16To<Ligature> Array16OfOffset16To<Ligature<Types>>
ligature; /* Array LigatureSet tables ligature; /* Array LigatureSet tables
* ordered by preference */ * ordered by preference */
public: public:
@ -28,7 +29,7 @@ struct LigatureSet
return return
+ hb_iter (ligature) + hb_iter (ligature)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); }) | hb_map ([glyphs] (const Ligature<Types> &_) { return _.intersects (glyphs); })
| hb_any | hb_any
; ;
} }
@ -37,7 +38,7 @@ struct LigatureSet
{ {
+ hb_iter (ligature) + hb_iter (ligature)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([c] (const Ligature &_) { _.closure (c); }) | hb_apply ([c] (const Ligature<Types> &_) { _.closure (c); })
; ;
} }
@ -45,7 +46,7 @@ struct LigatureSet
{ {
+ hb_iter (ligature) + hb_iter (ligature)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); }) | hb_apply ([c] (const Ligature<Types> &_) { _.collect_glyphs (c); })
; ;
} }
@ -54,7 +55,7 @@ struct LigatureSet
return return
+ hb_iter (ligature) + hb_iter (ligature)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_map ([c] (const Ligature &_) { return _.would_apply (c); }) | hb_map ([c] (const Ligature<Types> &_) { return _.would_apply (c); })
| hb_any | hb_any
; ;
} }
@ -65,7 +66,7 @@ struct LigatureSet
unsigned int num_ligs = ligature.len; unsigned int num_ligs = ligature.len;
for (unsigned int i = 0; i < num_ligs; i++) for (unsigned int i = 0; i < num_ligs; i++)
{ {
const Ligature &lig = this+ligature[i]; const auto &lig = this+ligature[i];
if (lig.apply (c)) return_trace (true); if (lig.apply (c)) return_trace (true);
} }

View File

@ -13,7 +13,10 @@ struct LigatureSubst
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
LigatureSubstFormat1 format1; LigatureSubstFormat1_2<SmallTypes> format1;
#ifndef HB_NO_BORING_EXPANSION
LigatureSubstFormat1_2<MediumTypes> format2;
#endif
} u; } u;
public: public:
@ -24,10 +27,16 @@ struct LigatureSubst
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }
/* TODO This function is only used by small GIDs, and not updated to 24bit GIDs. Should
* be done by using iterators. While at it perhaps using iterator of arrays of hb_codepoint_t
* instead. */
bool serialize (hb_serialize_context_t *c, bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const HBGlyphID16> first_glyphs, hb_sorted_array_t<const HBGlyphID16> first_glyphs,
hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
@ -49,6 +58,9 @@ struct LigatureSubst
default:return_trace (false); default:return_trace (false);
} }
} }
/* TODO subset() should choose format. */
}; };

View File

@ -8,18 +8,19 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
struct LigatureSubstFormat1 template <typename Types>
struct LigatureSubstFormat1_2
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 1 */ HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from coverage; /* Offset to Coverage table--from
* beginning of Substitution table */ * beginning of Substitution table */
Array16OfOffset16To<LigatureSet> Array16Of<typename Types::template OffsetTo<LigatureSet<Types>>>
ligatureSet; /* Array LigatureSet tables ligatureSet; /* Array LigatureSet tables
* ordered by Coverage Index */ * ordered by Coverage Index */
public: public:
DEFINE_SIZE_ARRAY (6, ligatureSet); DEFINE_SIZE_ARRAY (4 + Types::size, ligatureSet);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {
@ -33,7 +34,7 @@ struct LigatureSubstFormat1
+ hb_zip (this+coverage, ligatureSet) + hb_zip (this+coverage, ligatureSet)
| hb_filter (*glyphs, hb_first) | hb_filter (*glyphs, hb_first)
| hb_map (hb_second) | hb_map (hb_second)
| hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_) | hb_map ([this, glyphs] (const typename Types::template OffsetTo<LigatureSet<Types>> &_)
{ return (this+_).intersects (glyphs); }) { return (this+_).intersects (glyphs); })
| hb_any | hb_any
; ;
@ -48,7 +49,7 @@ struct LigatureSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first) | hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second) | hb_map (hb_second)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([c] (const LigatureSet &_) { _.closure (c); }) | hb_apply ([c] (const LigatureSet<Types> &_) { _.closure (c); })
; ;
} }
@ -62,7 +63,7 @@ struct LigatureSubstFormat1
+ hb_zip (this+coverage, ligatureSet) + hb_zip (this+coverage, ligatureSet)
| hb_map (hb_second) | hb_map (hb_second)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); }) | hb_apply ([c] (const LigatureSet<Types> &_) { _.collect_glyphs (c); })
; ;
} }
@ -73,7 +74,7 @@ struct LigatureSubstFormat1
unsigned int index = (this+coverage).get_coverage (c->glyphs[0]); unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
if (likely (index == NOT_COVERED)) return false; if (likely (index == NOT_COVERED)) return false;
const LigatureSet &lig_set = this+ligatureSet[index]; const auto &lig_set = this+ligatureSet[index];
return lig_set.would_apply (c); return lig_set.would_apply (c);
} }
@ -84,7 +85,7 @@ struct LigatureSubstFormat1
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint); unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false); if (likely (index == NOT_COVERED)) return_trace (false);
const LigatureSet &lig_set = this+ligatureSet[index]; const auto &lig_set = this+ligatureSet[index];
return_trace (lig_set.apply (c)); return_trace (lig_set.apply (c));
} }
@ -128,7 +129,7 @@ struct LigatureSubstFormat1
hb_set_t new_coverage; hb_set_t new_coverage;
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this))) + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
| hb_filter (glyphset, hb_first) | hb_filter (glyphset, hb_first)
| hb_filter ([&] (const LigatureSet& _) { | hb_filter ([&] (const LigatureSet<Types>& _) {
return _.intersects (&glyphset); return _.intersects (&glyphset);
}, hb_second) }, hb_second)
| hb_map (hb_first) | hb_map (hb_first)

View File

@ -13,7 +13,10 @@ struct MultipleSubst
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
MultipleSubstFormat1 format1; MultipleSubstFormat1_2<SmallTypes> format1;
#ifndef HB_NO_BORING_EXPANSION
MultipleSubstFormat1_2<MediumTypes> format2;
#endif
} u; } u;
public: public:
@ -25,10 +28,15 @@ struct MultipleSubst
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }
/* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
* iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
bool serialize (hb_serialize_context_t *c, bool serialize (hb_serialize_context_t *c,
hb_sorted_array_t<const HBGlyphID16> glyphs, hb_sorted_array_t<const HBGlyphID16> glyphs,
hb_array_t<const unsigned int> substitute_len_list, hb_array_t<const unsigned int> substitute_len_list,
@ -43,6 +51,9 @@ struct MultipleSubst
default:return_trace (false); default:return_trace (false);
} }
} }
/* TODO subset() should choose format. */
}; };

View File

@ -8,18 +8,19 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
struct MultipleSubstFormat1 template <typename Types>
struct MultipleSubstFormat1_2
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 1 */ HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from coverage; /* Offset to Coverage table--from
* beginning of Substitution table */ * beginning of Substitution table */
Array16OfOffset16To<Sequence> Array16Of<typename Types::template OffsetTo<Sequence<Types>>>
sequence; /* Array of Sequence tables sequence; /* Array of Sequence tables
* ordered by Coverage Index */ * ordered by Coverage Index */
public: public:
DEFINE_SIZE_ARRAY (6, sequence); DEFINE_SIZE_ARRAY (4 + Types::size, sequence);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {
@ -39,7 +40,7 @@ struct MultipleSubstFormat1
| hb_filter (c->parent_active_glyphs (), hb_first) | hb_filter (c->parent_active_glyphs (), hb_first)
| hb_map (hb_second) | hb_map (hb_second)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([c] (const Sequence &_) { _.closure (c); }) | hb_apply ([c] (const Sequence<Types> &_) { _.closure (c); })
; ;
} }
@ -51,7 +52,7 @@ struct MultipleSubstFormat1
+ hb_zip (this+coverage, sequence) + hb_zip (this+coverage, sequence)
| hb_map (hb_second) | hb_map (hb_second)
| hb_map (hb_add (this)) | hb_map (hb_add (this))
| hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); }) | hb_apply ([c] (const Sequence<Types> &_) { _.collect_glyphs (c); })
; ;
} }

View File

@ -7,10 +7,11 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
template <typename Types>
struct Sequence struct Sequence
{ {
protected: protected:
Array16Of<HBGlyphID16> Array16Of<typename Types::HBGlyphID>
substitute; /* String of GlyphIDs to substitute */ substitute; /* String of GlyphIDs to substitute */
public: public:
DEFINE_SIZE_ARRAY (2, substitute); DEFINE_SIZE_ARRAY (2, substitute);

View File

@ -14,8 +14,12 @@ struct SingleSubst
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
SingleSubstFormat1 format1; SingleSubstFormat1_3<SmallTypes> format1;
SingleSubstFormat2 format2; SingleSubstFormat2_4<SmallTypes> format2;
#ifndef HB_NO_BORING_EXPANSION
SingleSubstFormat1_3<MediumTypes> format3;
SingleSubstFormat2_4<MediumTypes> format4;
#endif
} u; } u;
public: public:
@ -28,6 +32,10 @@ struct SingleSubst
switch (u.format) { switch (u.format) {
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
#endif
default:return_trace (c->default_return_value ()); default:return_trace (c->default_return_value ());
} }
} }
@ -45,11 +53,24 @@ struct SingleSubst
if (glyphs) if (glyphs)
{ {
format = 1; format = 1;
auto get_delta = [=] (hb_codepoint_pair_t _) hb_codepoint_t mask = 0xFFFFu;
{ return (unsigned) (_.second - _.first) & 0xFFFF; };
delta = get_delta (*glyphs); #ifndef HB_NO_BORING_EXPANSION
if (!hb_all (++(+glyphs), delta, get_delta)) format = 2; if (+ glyphs
| hb_map_retains_sorting (hb_first)
| hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
{
format += 2;
mask = 0xFFFFFFu;
} }
#endif
auto get_delta = [=] (hb_codepoint_pair_t _)
{ return (unsigned) (_.second - _.first) & mask; };
delta = get_delta (*glyphs);
if (!hb_all (++(+glyphs), delta, get_delta)) format += 1;
}
u.format = format; u.format = format;
switch (u.format) { switch (u.format) {
case 1: return_trace (u.format1.serialize (c, case 1: return_trace (u.format1.serialize (c,
@ -57,6 +78,13 @@ struct SingleSubst
| hb_map_retains_sorting (hb_first), | hb_map_retains_sorting (hb_first),
delta)); delta));
case 2: return_trace (u.format2.serialize (c, glyphs)); case 2: return_trace (u.format2.serialize (c, glyphs));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (u.format3.serialize (c,
+ glyphs
| hb_map_retains_sorting (hb_first),
delta));
case 4: return_trace (u.format4.serialize (c, glyphs));
#endif
default:return_trace (false); default:return_trace (false);
} }
} }

View File

@ -7,18 +7,20 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
struct SingleSubstFormat1 template <typename Types>
struct SingleSubstFormat1_3
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 1 */ HBUINT16 format; /* Format identifier--format = 1 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from coverage; /* Offset to Coverage table--from
* beginning of Substitution table */ * beginning of Substitution table */
HBUINT16 deltaGlyphID; /* Add to original GlyphID to get typename Types::HBUINT
deltaGlyphID; /* Add to original GlyphID to get
* substitute GlyphID, modulo 0x10000 */ * substitute GlyphID, modulo 0x10000 */
public: public:
DEFINE_SIZE_STATIC (6); DEFINE_SIZE_STATIC (2 + 2 * Types::size);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {

View File

@ -7,19 +7,20 @@ namespace OT {
namespace Layout { namespace Layout {
namespace GSUB_impl { namespace GSUB_impl {
struct SingleSubstFormat2 template <typename Types>
struct SingleSubstFormat2_4
{ {
protected: protected:
HBUINT16 format; /* Format identifier--format = 2 */ HBUINT16 format; /* Format identifier--format = 2 */
Offset16To<Coverage> typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from coverage; /* Offset to Coverage table--from
* beginning of Substitution table */ * beginning of Substitution table */
Array16Of<HBGlyphID16> Array16Of<typename Types::HBGlyphID>
substitute; /* Array of substitute substitute; /* Array of substitute
* GlyphIDs--ordered by Coverage Index */ * GlyphIDs--ordered by Coverage Index */
public: public:
DEFINE_SIZE_ARRAY (6, substitute); DEFINE_SIZE_ARRAY (4 + Types::size, substitute);
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
{ {
@ -103,7 +104,7 @@ struct SingleSubstFormat2
+ hb_zip (this+coverage, substitute) + hb_zip (this+coverage, substitute)
| hb_filter (glyphset, hb_first) | hb_filter (glyphset, hb_first)
| hb_filter (glyphset, hb_second) | hb_filter (glyphset, hb_second)
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const typename Types::HBGlyphID &> p) -> hb_codepoint_pair_t
{ return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
; ;

View File

@ -25,13 +25,16 @@ struct CompositeGlyphRecord
USE_MY_METRICS = 0x0200, USE_MY_METRICS = 0x0200,
OVERLAP_COMPOUND = 0x0400, OVERLAP_COMPOUND = 0x0400,
SCALED_COMPONENT_OFFSET = 0x0800, SCALED_COMPONENT_OFFSET = 0x0800,
UNSCALED_COMPONENT_OFFSET = 0x1000 UNSCALED_COMPONENT_OFFSET = 0x1000,
GID_IS_24BIT = 0x2000
}; };
public: public:
unsigned int get_size () const unsigned int get_size () const
{ {
unsigned int size = min_size; unsigned int size = min_size;
/* glyphIndex is 24bit instead of 16bit */
if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size;
/* arg1 and 2 are int16 */ /* arg1 and 2 are int16 */
if (flags & ARG_1_AND_2_ARE_WORDS) size += 4; if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
/* arg1 and 2 are int8 */ /* arg1 and 2 are int8 */
@ -60,7 +63,11 @@ struct CompositeGlyphRecord
bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); } bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
void get_anchor_points (unsigned int &point1, unsigned int &point2) const void get_anchor_points (unsigned int &point1, unsigned int &point2) const
{ {
const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex); const auto *p = &StructAfter<const HBUINT8> (flags);
if (flags & GID_IS_24BIT)
p += HBGlyphID24::static_size;
else
p += HBGlyphID16::static_size;
if (flags & ARG_1_AND_2_ARE_WORDS) if (flags & ARG_1_AND_2_ARE_WORDS)
{ {
point1 = ((const HBUINT16 *) p)[0]; point1 = ((const HBUINT16 *) p)[0];
@ -101,8 +108,12 @@ struct CompositeGlyphRecord
matrix[0] = matrix[3] = 1.f; matrix[0] = matrix[3] = 1.f;
matrix[1] = matrix[2] = 0.f; matrix[1] = matrix[2] = 0.f;
const auto *p = &StructAfter<const HBINT8> (flags);
if (flags & GID_IS_24BIT)
p += HBGlyphID24::static_size;
else
p += HBGlyphID16::static_size;
int tx, ty; int tx, ty;
const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
if (flags & ARG_1_AND_2_ARE_WORDS) if (flags & ARG_1_AND_2_ARE_WORDS)
{ {
tx = *(const HBINT16 *) p; tx = *(const HBINT16 *) p;
@ -145,8 +156,25 @@ struct CompositeGlyphRecord
} }
public: public:
hb_codepoint_t get_gid () const
{
if (flags & GID_IS_24BIT)
return StructAfter<const HBGlyphID24> (flags);
else
return StructAfter<const HBGlyphID16> (flags);
}
void set_gid (hb_codepoint_t gid)
{
if (flags & GID_IS_24BIT)
StructAfter<HBGlyphID24> (flags) = gid;
else
/* TODO assert? */
StructAfter<HBGlyphID16> (flags) = gid;
}
protected:
HBUINT16 flags; HBUINT16 flags;
HBGlyphID16 glyphIndex; HBUINT24 pad;
public: public:
DEFINE_SIZE_MIN (4); DEFINE_SIZE_MIN (4);
}; };

View File

@ -146,7 +146,7 @@ struct Glyph
for (auto &item : get_composite_iterator ()) for (auto &item : get_composite_iterator ())
{ {
comp_points.reset (); comp_points.reset ();
if (unlikely (!glyf_accelerator.glyph_for_gid (item.glyphIndex) if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
.get_points (font, glyf_accelerator, comp_points, .get_points (font, glyf_accelerator, comp_points,
phantom_only, depth + 1))) phantom_only, depth + 1)))
return false; return false;

View File

@ -42,8 +42,8 @@ struct SubsetGlyph
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ()) for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
{ {
hb_codepoint_t new_gid; hb_codepoint_t new_gid;
if (plan->new_gid_for_old_gid (_.glyphIndex, &new_gid)) if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
const_cast<CompositeGlyphRecord &> (_).glyphIndex = new_gid; const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
} }
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)

View File

@ -743,8 +743,8 @@ template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUI
template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>; template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
/* Array of offsets relative to the beginning of the array itself. */ /* Array of offsets relative to the beginning of the array itself. */
template <typename Type> template <typename Type, typename OffsetType>
struct List16OfOffset16To : Array16OfOffset16To<Type> struct List16OfOffsetTo : ArrayOf<OffsetTo<Type, OffsetType>, HBUINT16>
{ {
const Type& operator [] (int i_) const const Type& operator [] (int i_) const
{ {
@ -762,7 +762,7 @@ struct List16OfOffset16To : Array16OfOffset16To<Type>
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
struct List16OfOffset16To<Type> *out = c->serializer->embed (*this); struct List16OfOffsetTo *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false); if (unlikely (!out)) return_trace (false);
unsigned int count = this->len; unsigned int count = this->len;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
@ -774,10 +774,13 @@ struct List16OfOffset16To : Array16OfOffset16To<Type>
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
return_trace (Array16OfOffset16To<Type>::sanitize (c, this, std::forward<Ts> (ds)...)); return_trace ((Array16Of<OffsetTo<Type, OffsetType>>::sanitize (c, this, std::forward<Ts> (ds)...)));
} }
}; };
template <typename Type>
using List16OfOffset16To = List16OfOffsetTo<Type, HBUINT16>;
/* An array starting at second element. */ /* An array starting at second element. */
template <typename Type, typename LenType=HBUINT16> template <typename Type, typename LenType=HBUINT16>
struct HeadlessArrayOf struct HeadlessArrayOf

View File

@ -80,8 +80,34 @@
namespace OT { namespace OT {
#define NOT_COVERED ((unsigned int) -1) struct SmallTypes {
static constexpr unsigned size = 2;
using HBUINT = HBUINT16;
using HBGlyphID = HBGlyphID16;
using Offset = Offset16;
template <typename Type, bool has_null=true>
using OffsetTo = OT::Offset16To<Type, has_null>;
template <typename Type>
using ArrayOf = OT::Array16Of<Type>;
template <typename Type>
using SortedArrayOf = OT::SortedArray16Of<Type>;
};
struct MediumTypes {
static constexpr unsigned size = 3;
using HBUINT = HBUINT24;
using HBGlyphID = HBGlyphID24;
using Offset = Offset24;
template <typename Type, bool has_null=true>
using OffsetTo = OT::Offset24To<Type, has_null>;
template <typename Type>
using ArrayOf = OT::Array24Of<Type>;
template <typename Type>
using SortedArrayOf = OT::SortedArray24Of<Type>;
};
#define NOT_COVERED ((unsigned int) -1)
template<typename Iterator> template<typename Iterator>
static inline void Coverage_serialize (hb_serialize_context_t *c, static inline void Coverage_serialize (hb_serialize_context_t *c,
@ -510,6 +536,7 @@ struct RecordListOfScript : RecordListOf<Script>
} }
}; };
template <typename Types>
struct RangeRecord struct RangeRecord
{ {
int cmp (hb_codepoint_t g) const int cmp (hb_codepoint_t g) const
@ -528,13 +555,13 @@ struct RangeRecord
bool collect_coverage (set_t *glyphs) const bool collect_coverage (set_t *glyphs) const
{ return glyphs->add_range (first, last); } { return glyphs->add_range (first, last); }
HBGlyphID16 first; /* First GlyphID in the range */ typename Types::HBGlyphID first; /* First GlyphID in the range */
HBGlyphID16 last; /* Last GlyphID in the range */ typename Types::HBGlyphID last; /* Last GlyphID in the range */
HBUINT16 value; /* Value */ HBUINT16 value; /* Value */
public: public:
DEFINE_SIZE_STATIC (6); DEFINE_SIZE_STATIC (2 + 2 * Types::size);
}; };
DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord); DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
struct IndexArray : Array16Of<Index> struct IndexArray : Array16Of<Index>
@ -1377,10 +1404,11 @@ struct Lookup
DEFINE_SIZE_ARRAY (6, subTable); DEFINE_SIZE_ARRAY (6, subTable);
}; };
typedef List16OfOffset16To<Lookup> LookupList; template <typename Types>
using LookupList = List16OfOffsetTo<Lookup, typename Types::HBUINT>;
template <typename TLookup> template <typename TLookup, typename OffsetType>
struct LookupOffsetList : List16OfOffset16To<TLookup> struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
{ {
bool subset (hb_subset_context_t *c, bool subset (hb_subset_context_t *c,
hb_subset_layout_context_t *l) const hb_subset_layout_context_t *l) const
@ -1410,7 +1438,8 @@ struct LookupOffsetList : List16OfOffset16To<TLookup>
* Coverage Table * Coverage Table
*/ */
struct CoverageFormat1 template <typename Types>
struct CoverageFormat1_3
{ {
friend struct Coverage; friend struct Coverage;
@ -1463,7 +1492,7 @@ struct CoverageFormat1
/* Older compilers need this to be public. */ /* Older compilers need this to be public. */
struct iter_t struct iter_t
{ {
void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; } void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; }
void fini () {} void fini () {}
bool more () const { return i < c->glyphArray.len; } bool more () const { return i < c->glyphArray.len; }
void next () { i++; } void next () { i++; }
@ -1473,27 +1502,28 @@ struct CoverageFormat1
iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; } iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
private: private:
const struct CoverageFormat1 *c; const struct CoverageFormat1_3 *c;
unsigned int i; unsigned int i;
}; };
private: private:
protected: protected:
HBUINT16 coverageFormat; /* Format identifier--format = 1 */ HBUINT16 coverageFormat; /* Format identifier--format = 1 */
SortedArray16Of<HBGlyphID16> SortedArray16Of<typename Types::HBGlyphID>
glyphArray; /* Array of GlyphIDs--in numerical order */ glyphArray; /* Array of GlyphIDs--in numerical order */
public: public:
DEFINE_SIZE_ARRAY (4, glyphArray); DEFINE_SIZE_ARRAY (4, glyphArray);
}; };
struct CoverageFormat2 template <typename Types>
struct CoverageFormat2_4
{ {
friend struct Coverage; friend struct Coverage;
private: private:
unsigned int get_coverage (hb_codepoint_t glyph_id) const unsigned int get_coverage (hb_codepoint_t glyph_id) const
{ {
const RangeRecord &range = rangeRecord.bsearch (glyph_id); const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
return likely (range.first <= range.last) return likely (range.first <= range.last)
? (unsigned int) range.value + (glyph_id - range.first) ? (unsigned int) range.value + (glyph_id - range.first)
: NOT_COVERED; : NOT_COVERED;
@ -1548,14 +1578,14 @@ struct CoverageFormat2
bool intersects (const hb_set_t *glyphs) const bool intersects (const hb_set_t *glyphs) const
{ {
return hb_any (+ hb_iter (rangeRecord.as_array ()) return hb_any (+ hb_iter (rangeRecord.as_array ())
| hb_map ([glyphs] (const RangeRecord &range) { return range.intersects (glyphs); })); | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (glyphs); }));
} }
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
{ {
auto cmp = [] (const void *pk, const void *pr) -> int auto cmp = [] (const void *pk, const void *pr) -> int
{ {
unsigned index = * (const unsigned *) pk; unsigned index = * (const unsigned *) pk;
const RangeRecord &range = * (const RangeRecord *) pr; const RangeRecord<Types> &range = * (const RangeRecord<Types> *) pr;
if (index < range.value) return -1; if (index < range.value) return -1;
if (index > (unsigned int) range.value + (range.last - range.first)) return +1; if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
return 0; return 0;
@ -1596,7 +1626,7 @@ struct CoverageFormat2
/* Older compilers need this to be public. */ /* Older compilers need this to be public. */
struct iter_t struct iter_t
{ {
void init (const CoverageFormat2 &c_) void init (const CoverageFormat2_4 &c_)
{ {
c = &c_; c = &c_;
coverage = 0; coverage = 0;
@ -1650,7 +1680,7 @@ struct CoverageFormat2
} }
private: private:
const struct CoverageFormat2 *c; const struct CoverageFormat2_4 *c;
unsigned int i, coverage; unsigned int i, coverage;
hb_codepoint_t j; hb_codepoint_t j;
}; };
@ -1658,7 +1688,7 @@ struct CoverageFormat2
protected: protected:
HBUINT16 coverageFormat; /* Format identifier--format = 2 */ HBUINT16 coverageFormat; /* Format identifier--format = 2 */
SortedArray16Of<RangeRecord> SortedArray16Of<RangeRecord<Types>>
rangeRecord; /* Array of glyph ranges--ordered by rangeRecord; /* Array of glyph ranges--ordered by
* Start GlyphID. rangeCount entries * Start GlyphID. rangeCount entries
* long */ * long */
@ -1682,6 +1712,10 @@ struct Coverage
switch (u.format) { switch (u.format) {
case 1: return u.format1.get_coverage (glyph_id); case 1: return u.format1.get_coverage (glyph_id);
case 2: return u.format2.get_coverage (glyph_id); case 2: return u.format2.get_coverage (glyph_id);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.get_coverage (glyph_id);
case 4: return u.format4.get_coverage (glyph_id);
#endif
default:return NOT_COVERED; default:return NOT_COVERED;
} }
} }
@ -1705,10 +1739,19 @@ struct Coverage
} }
u.format = count <= num_ranges * 3 ? 1 : 2; u.format = count <= num_ranges * 3 ? 1 : 2;
#ifndef HB_NO_BORING_EXPANSION
if (count && last > 0xFFFFu)
u.format += 2;
#endif
switch (u.format) switch (u.format)
{ {
case 1: return_trace (u.format1.serialize (c, glyphs)); case 1: return_trace (u.format1.serialize (c, glyphs));
case 2: return_trace (u.format2.serialize (c, glyphs)); case 2: return_trace (u.format2.serialize (c, glyphs));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (u.format3.serialize (c, glyphs));
case 4: return_trace (u.format4.serialize (c, glyphs));
#endif
default:return_trace (false); default:return_trace (false);
} }
} }
@ -1737,6 +1780,10 @@ struct Coverage
{ {
case 1: return_trace (u.format1.sanitize (c)); case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c)); case 2: return_trace (u.format2.sanitize (c));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (u.format3.sanitize (c));
case 4: return_trace (u.format4.sanitize (c));
#endif
default:return_trace (true); default:return_trace (true);
} }
} }
@ -1747,6 +1794,10 @@ struct Coverage
{ {
case 1: return u.format1.intersects (glyphs); case 1: return u.format1.intersects (glyphs);
case 2: return u.format2.intersects (glyphs); case 2: return u.format2.intersects (glyphs);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.intersects (glyphs);
case 4: return u.format4.intersects (glyphs);
#endif
default:return false; default:return false;
} }
} }
@ -1756,6 +1807,10 @@ struct Coverage
{ {
case 1: return u.format1.intersects_coverage (glyphs, index); case 1: return u.format1.intersects_coverage (glyphs, index);
case 2: return u.format2.intersects_coverage (glyphs, index); case 2: return u.format2.intersects_coverage (glyphs, index);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.intersects_coverage (glyphs, index);
case 4: return u.format4.intersects_coverage (glyphs, index);
#endif
default:return false; default:return false;
} }
} }
@ -1769,6 +1824,10 @@ struct Coverage
{ {
case 1: return u.format1.collect_coverage (glyphs); case 1: return u.format1.collect_coverage (glyphs);
case 2: return u.format2.collect_coverage (glyphs); case 2: return u.format2.collect_coverage (glyphs);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.collect_coverage (glyphs);
case 4: return u.format4.collect_coverage (glyphs);
#endif
default:return false; default:return false;
} }
} }
@ -1779,6 +1838,10 @@ struct Coverage
{ {
case 1: return u.format1.intersected_coverage_glyphs (glyphs, intersect_glyphs); case 1: return u.format1.intersected_coverage_glyphs (glyphs, intersect_glyphs);
case 2: return u.format2.intersected_coverage_glyphs (glyphs, intersect_glyphs); case 2: return u.format2.intersected_coverage_glyphs (glyphs, intersect_glyphs);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.intersected_coverage_glyphs (glyphs, intersect_glyphs);
case 4: return u.format4.intersected_coverage_glyphs (glyphs, intersect_glyphs);
#endif
default:return ; default:return ;
} }
} }
@ -1794,6 +1857,10 @@ struct Coverage
{ {
case 1: u.format1.init (c_.u.format1); return; case 1: u.format1.init (c_.u.format1); return;
case 2: u.format2.init (c_.u.format2); return; case 2: u.format2.init (c_.u.format2); return;
#ifndef HB_NO_BORING_EXPANSION
case 3: u.format3.init (c_.u.format3); return;
case 4: u.format4.init (c_.u.format4); return;
#endif
default: return; default: return;
} }
} }
@ -1803,6 +1870,10 @@ struct Coverage
{ {
case 1: return u.format1.more (); case 1: return u.format1.more ();
case 2: return u.format2.more (); case 2: return u.format2.more ();
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.more ();
case 4: return u.format4.more ();
#endif
default:return false; default:return false;
} }
} }
@ -1812,6 +1883,10 @@ struct Coverage
{ {
case 1: u.format1.next (); break; case 1: u.format1.next (); break;
case 2: u.format2.next (); break; case 2: u.format2.next (); break;
#ifndef HB_NO_BORING_EXPANSION
case 3: u.format3.next (); break;
case 4: u.format4.next (); break;
#endif
default: break; default: break;
} }
} }
@ -1824,6 +1899,10 @@ struct Coverage
{ {
case 1: return u.format1.get_glyph (); case 1: return u.format1.get_glyph ();
case 2: return u.format2.get_glyph (); case 2: return u.format2.get_glyph ();
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.get_glyph ();
case 4: return u.format4.get_glyph ();
#endif
default:return 0; default:return 0;
} }
} }
@ -1834,6 +1913,10 @@ struct Coverage
{ {
case 1: return u.format1 != o.u.format1; case 1: return u.format1 != o.u.format1;
case 2: return u.format2 != o.u.format2; case 2: return u.format2 != o.u.format2;
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3 != o.u.format3;
case 4: return u.format4 != o.u.format4;
#endif
default:return false; default:return false;
} }
} }
@ -1845,6 +1928,10 @@ struct Coverage
{ {
case 1: it.u.format1 = u.format1.__end__ (); break; case 1: it.u.format1 = u.format1.__end__ (); break;
case 2: it.u.format2 = u.format2.__end__ (); break; case 2: it.u.format2 = u.format2.__end__ (); break;
#ifndef HB_NO_BORING_EXPANSION
case 3: it.u.format3 = u.format3.__end__ (); break;
case 4: it.u.format4 = u.format4.__end__ (); break;
#endif
default: break; default: break;
} }
return it; return it;
@ -1853,8 +1940,12 @@ struct Coverage
private: private:
unsigned int format; unsigned int format;
union { union {
CoverageFormat2::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */ #ifndef HB_NO_BORING_EXPANSION
CoverageFormat1::iter_t format1; CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
CoverageFormat1_3<MediumTypes>::iter_t format3;
#endif
CoverageFormat2_4<SmallTypes>::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
CoverageFormat1_3<SmallTypes>::iter_t format1;
} u; } u;
}; };
iter_t iter () const { return iter_t (*this); } iter_t iter () const { return iter_t (*this); }
@ -1862,8 +1953,12 @@ struct Coverage
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
CoverageFormat1 format1; CoverageFormat1_3<SmallTypes> format1;
CoverageFormat2 format2; CoverageFormat2_4<SmallTypes> format2;
#ifndef HB_NO_BORING_EXPANSION
CoverageFormat1_3<MediumTypes>format3;
CoverageFormat2_4<MediumTypes>format4;
#endif
} u; } u;
public: public:
DEFINE_SIZE_UNION (2, format); DEFINE_SIZE_UNION (2, format);
@ -1915,7 +2010,8 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
* Class Definition Table * Class Definition Table
*/ */
struct ClassDefFormat1 template <typename Types>
struct ClassDefFormat1_3
{ {
friend struct ClassDef; friend struct ClassDef;
@ -2120,14 +2216,16 @@ struct ClassDefFormat1
protected: protected:
HBUINT16 classFormat; /* Format identifier--format = 1 */ HBUINT16 classFormat; /* Format identifier--format = 1 */
HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */ typename Types::HBGlyphID
Array16Of<HBUINT16> startGlyph; /* First GlyphID of the classValueArray */
typename Types::template ArrayOf<HBUINT16>
classValue; /* Array of Class Values--one per GlyphID */ classValue; /* Array of Class Values--one per GlyphID */
public: public:
DEFINE_SIZE_ARRAY (6, classValue); DEFINE_SIZE_ARRAY (2 + 2 * Types::size, classValue);
}; };
struct ClassDefFormat2 template <typename Types>
struct ClassDefFormat2_4
{ {
friend struct ClassDef; friend struct ClassDef;
@ -2156,12 +2254,12 @@ struct ClassDefFormat2
hb_codepoint_t prev_gid = (*it).first; hb_codepoint_t prev_gid = (*it).first;
unsigned prev_klass = (*it).second; unsigned prev_klass = (*it).second;
RangeRecord range_rec; RangeRecord<Types> range_rec;
range_rec.first = prev_gid; range_rec.first = prev_gid;
range_rec.last = prev_gid; range_rec.last = prev_gid;
range_rec.value = prev_klass; range_rec.value = prev_klass;
RangeRecord *record = c->copy (range_rec); auto *record = c->copy (range_rec);
if (unlikely (!record)) return_trace (false); if (unlikely (!record)) return_trace (false);
for (const auto gid_klass_pair : + (++it)) for (const auto gid_klass_pair : + (++it))
@ -2300,7 +2398,7 @@ struct ClassDefFormat2
} }
/* TODO Speed up, using set overlap first? */ /* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */ /* TODO(iter) Rewrite as dagger. */
const RangeRecord *arr = rangeRecord.arrayZ; const auto *arr = rangeRecord.arrayZ;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
if (arr[i].value == klass && arr[i].intersects (glyphs)) if (arr[i].value == klass && arr[i].intersects (glyphs))
return true; return true;
@ -2376,18 +2474,18 @@ struct ClassDefFormat2
if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g)) if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
intersect_classes->add (0); intersect_classes->add (0);
for (const RangeRecord& record : rangeRecord.iter ()) for (const auto& record : rangeRecord.iter ())
if (record.intersects (glyphs)) if (record.intersects (glyphs))
intersect_classes->add (record.value); intersect_classes->add (record.value);
} }
protected: protected:
HBUINT16 classFormat; /* Format identifier--format = 2 */ HBUINT16 classFormat; /* Format identifier--format = 2 */
SortedArray16Of<RangeRecord> typename Types::template SortedArrayOf<RangeRecord<Types>>
rangeRecord; /* Array of glyph ranges--ordered by rangeRecord; /* Array of glyph ranges--ordered by
* Start GlyphID */ * Start GlyphID */
public: public:
DEFINE_SIZE_ARRAY (4, rangeRecord); DEFINE_SIZE_ARRAY (2 + Types::size, rangeRecord);
}; };
struct ClassDef struct ClassDef
@ -2406,6 +2504,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return u.format1.get_class (glyph_id); case 1: return u.format1.get_class (glyph_id);
case 2: return u.format2.get_class (glyph_id); case 2: return u.format2.get_class (glyph_id);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.get_class (glyph_id);
case 4: return u.format4.get_class (glyph_id);
#endif
default:return 0; default:return 0;
} }
} }
@ -2420,10 +2522,11 @@ struct ClassDef
auto it = + it_with_class_zero | hb_filter (hb_second); auto it = + it_with_class_zero | hb_filter (hb_second);
unsigned format = 2; unsigned format = 2;
hb_codepoint_t glyph_max = 0;
if (likely (it)) if (likely (it))
{ {
hb_codepoint_t glyph_min = (*it).first; hb_codepoint_t glyph_min = (*it).first;
hb_codepoint_t glyph_max = glyph_min; glyph_max = glyph_min;
unsigned num_glyphs = 0; unsigned num_glyphs = 0;
unsigned num_ranges = 1; unsigned num_ranges = 1;
@ -2448,12 +2551,22 @@ struct ClassDef
if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3) if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
format = 1; format = 1;
} }
#ifndef HB_NO_BORING_EXPANSION
if (glyph_max > 0xFFFFu)
format += 2;
#endif
u.format = format; u.format = format;
switch (u.format) switch (u.format)
{ {
case 1: return_trace (u.format1.serialize (c, it)); case 1: return_trace (u.format1.serialize (c, it));
case 2: return_trace (u.format2.serialize (c, it)); case 2: return_trace (u.format2.serialize (c, it));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (u.format3.serialize (c, it));
case 4: return_trace (u.format4.serialize (c, it));
#endif
default:return_trace (false); default:return_trace (false);
} }
} }
@ -2468,6 +2581,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter)); case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
case 4: return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
#endif
default:return_trace (false); default:return_trace (false);
} }
} }
@ -2479,6 +2596,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return_trace (u.format1.sanitize (c)); case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c)); case 2: return_trace (u.format2.sanitize (c));
#ifndef HB_NO_BORING_EXPANSION
case 3: return_trace (u.format3.sanitize (c));
case 4: return_trace (u.format4.sanitize (c));
#endif
default:return_trace (true); default:return_trace (true);
} }
} }
@ -2488,6 +2609,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return u.format1.cost (); case 1: return u.format1.cost ();
case 2: return u.format2.cost (); case 2: return u.format2.cost ();
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.cost ();
case 4: return u.format4.cost ();
#endif
default:return 0u; default:return 0u;
} }
} }
@ -2500,6 +2625,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return u.format1.collect_coverage (glyphs); case 1: return u.format1.collect_coverage (glyphs);
case 2: return u.format2.collect_coverage (glyphs); case 2: return u.format2.collect_coverage (glyphs);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.collect_coverage (glyphs);
case 4: return u.format4.collect_coverage (glyphs);
#endif
default:return false; default:return false;
} }
} }
@ -2512,6 +2641,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return u.format1.collect_class (glyphs, klass); case 1: return u.format1.collect_class (glyphs, klass);
case 2: return u.format2.collect_class (glyphs, klass); case 2: return u.format2.collect_class (glyphs, klass);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.collect_class (glyphs, klass);
case 4: return u.format4.collect_class (glyphs, klass);
#endif
default:return false; default:return false;
} }
} }
@ -2521,6 +2654,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return u.format1.intersects (glyphs); case 1: return u.format1.intersects (glyphs);
case 2: return u.format2.intersects (glyphs); case 2: return u.format2.intersects (glyphs);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.intersects (glyphs);
case 4: return u.format4.intersects (glyphs);
#endif
default:return false; default:return false;
} }
} }
@ -2529,6 +2666,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return u.format1.intersects_class (glyphs, klass); case 1: return u.format1.intersects_class (glyphs, klass);
case 2: return u.format2.intersects_class (glyphs, klass); case 2: return u.format2.intersects_class (glyphs, klass);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.intersects_class (glyphs, klass);
case 4: return u.format4.intersects_class (glyphs, klass);
#endif
default:return false; default:return false;
} }
} }
@ -2538,6 +2679,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs); case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs); case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
case 4: return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
#endif
default:return; default:return;
} }
} }
@ -2547,6 +2692,10 @@ struct ClassDef
switch (u.format) { switch (u.format) {
case 1: return u.format1.intersected_classes (glyphs, intersect_classes); case 1: return u.format1.intersected_classes (glyphs, intersect_classes);
case 2: return u.format2.intersected_classes (glyphs, intersect_classes); case 2: return u.format2.intersected_classes (glyphs, intersect_classes);
#ifndef HB_NO_BORING_EXPANSION
case 3: return u.format3.intersected_classes (glyphs, intersect_classes);
case 4: return u.format4.intersected_classes (glyphs, intersect_classes);
#endif
default:return; default:return;
} }
} }
@ -2555,8 +2704,12 @@ struct ClassDef
protected: protected:
union { union {
HBUINT16 format; /* Format identifier */ HBUINT16 format; /* Format identifier */
ClassDefFormat1 format1; ClassDefFormat1_3<SmallTypes> format1;
ClassDefFormat2 format2; ClassDefFormat2_4<SmallTypes> format2;
#ifndef HB_NO_BORING_EXPANSION
ClassDefFormat1_3<MediumTypes>format3;
ClassDefFormat2_4<MediumTypes>format4;
#endif
} u; } u;
public: public:
DEFINE_SIZE_UNION (2, format); DEFINE_SIZE_UNION (2, format);

File diff suppressed because it is too large Load Diff

View File

@ -156,6 +156,71 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
indices); indices);
} }
static inline void
_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
const hb_map_t *lookup_indices,
const hb_set_t *feature_indices,
hb_map_t *duplicate_feature_map /* OUT */)
{
if (feature_indices->is_empty ()) return;
hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features;
//find out duplicate features after subset
for (unsigned i : feature_indices->iter ())
{
hb_tag_t t = g.get_feature_tag (i);
if (t == HB_MAP_VALUE_INVALID) continue;
if (!unique_features.has (t))
{
if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
return;
if (unique_features.has (t))
unique_features.get (t)->add (i);
duplicate_feature_map->set (i, i);
continue;
}
bool found = false;
hb_set_t* same_tag_features = unique_features.get (t);
for (unsigned other_f_index : same_tag_features->iter ())
{
const OT::Feature& f = g.get_feature (i);
const OT::Feature& other_f = g.get_feature (other_f_index);
auto f_iter =
+ hb_iter (f.lookupIndex)
| hb_filter (lookup_indices)
;
auto other_f_iter =
+ hb_iter (other_f.lookupIndex)
| hb_filter (lookup_indices)
;
bool is_equal = true;
for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
{
unsigned a = *f_iter;
unsigned b = *other_f_iter;
if (a != b) { is_equal = false; break; }
}
if (is_equal == false || f_iter || other_f_iter) continue;
found = true;
duplicate_feature_map->set (i, other_f_index);
break;
}
if (found == false)
{
same_tag_features->add (i);
duplicate_feature_map->set (i, i);
}
}
}
template <typename T> template <typename T>
static inline void static inline void
_closure_glyphs_lookups_features (hb_subset_plan_t *plan, _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
@ -190,7 +255,7 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
table->prune_features (lookups, &feature_indices); table->prune_features (lookups, &feature_indices);
hb_map_t duplicate_feature_map; hb_map_t duplicate_feature_map;
table->find_duplicate_features (lookups, &feature_indices, &duplicate_feature_map); _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, &duplicate_feature_map);
feature_indices.clear (); feature_indices.clear ();
table->prune_langsys (&duplicate_feature_map, langsys_map, &feature_indices); table->prune_langsys (&duplicate_feature_map, langsys_map, &feature_indices);
@ -374,7 +439,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
for (auto item : glyf.glyph_for_gid (gid).get_composite_iterator ()) for (auto item : glyf.glyph_for_gid (gid).get_composite_iterator ())
operation_count = operation_count =
_glyf_add_gid_and_children (glyf, _glyf_add_gid_and_children (glyf,
item.glyphIndex, item.get_gid (),
gids_to_retain, gids_to_retain,
operation_count, operation_count,
depth); depth);