Merge pull request #3704 from harfbuzz/64k
Towards breaking the 64k in GSUB/GPOS
This commit is contained in:
commit
87167acfe3
|
@ -12,7 +12,10 @@ struct MarkBasePos
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkBasePosFormat1 format1;
|
||||
MarkBasePosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
MarkBasePosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
|
@ -23,6 +26,9 @@ struct MarkBasePos
|
|||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,26 +12,27 @@ typedef AnchorMatrix BaseArray; /* base-major--
|
|||
* mark-minor--
|
||||
* ordered by class--zero-based. */
|
||||
|
||||
struct MarkBasePosFormat1
|
||||
template <typename Types>
|
||||
struct MarkBasePosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
markCoverage; /* Offset to MarkCoverage table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
baseCoverage; /* Offset to BaseCoverage table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
HBUINT16 classCount; /* Number of classes defined for marks */
|
||||
Offset16To<MarkArray>
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
markArray; /* Offset to MarkArray table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
Offset16To<BaseArray>
|
||||
typename Types::template OffsetTo<BaseArray>
|
||||
baseArray; /* Offset to BaseArray table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -12,7 +12,10 @@ struct MarkLigPos
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkLigPosFormat1 format1;
|
||||
MarkLigPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
MarkLigPosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
|
@ -23,6 +26,9 @@ struct MarkLigPos
|
|||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,26 +8,27 @@ namespace Layout {
|
|||
namespace GPOS_impl {
|
||||
|
||||
|
||||
struct MarkLigPosFormat1
|
||||
template <typename Types>
|
||||
struct MarkLigPosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
markCoverage; /* Offset to Mark Coverage table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
ligatureCoverage; /* Offset to Ligature Coverage
|
||||
* table--from beginning of MarkLigPos
|
||||
* subtable */
|
||||
HBUINT16 classCount; /* Number of defined mark classes */
|
||||
Offset16To<MarkArray>
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
markArray; /* Offset to MarkArray table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
Offset16To<LigatureArray>
|
||||
typename Types::template OffsetTo<LigatureArray>
|
||||
ligatureArray; /* Offset to LigatureArray table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -12,7 +12,10 @@ struct MarkMarkPos
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MarkMarkPosFormat1 format1;
|
||||
MarkMarkPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
MarkMarkPosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
|
@ -23,6 +26,9 @@ struct MarkMarkPos
|
|||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,27 +12,28 @@ typedef AnchorMatrix Mark2Array; /* mark2-major--
|
|||
* mark1-minor--
|
||||
* ordered by class--zero-based. */
|
||||
|
||||
struct MarkMarkPosFormat1
|
||||
template <typename Types>
|
||||
struct MarkMarkPosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
mark1Coverage; /* Offset to Combining Mark1 Coverage
|
||||
* table--from beginning of MarkMarkPos
|
||||
* subtable */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
mark2Coverage; /* Offset to Combining Mark2 Coverage
|
||||
* table--from beginning of MarkMarkPos
|
||||
* subtable */
|
||||
HBUINT16 classCount; /* Number of defined mark classes */
|
||||
Offset16To<MarkArray>
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
mark1Array; /* Offset to Mark1Array table--from
|
||||
* beginning of MarkMarkPos subtable */
|
||||
Offset16To<Mark2Array>
|
||||
typename Types::template OffsetTo<Mark2Array>
|
||||
mark2Array; /* Offset to Mark2Array table--from
|
||||
* beginning of MarkMarkPos subtable */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -13,8 +13,12 @@ struct PairPos
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
PairPosFormat1 format1;
|
||||
PairPosFormat2 format2;
|
||||
PairPosFormat1_3<SmallTypes> format1;
|
||||
PairPosFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
PairPosFormat1_3<MediumTypes> format3;
|
||||
PairPosFormat2_4<MediumTypes> format4;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
|
@ -26,6 +30,10 @@ struct PairPos
|
|||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, 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 ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,15 @@ namespace Layout {
|
|||
namespace GPOS_impl {
|
||||
|
||||
|
||||
struct PairPosFormat1
|
||||
template <typename Types>
|
||||
struct PairPosFormat1_3
|
||||
{
|
||||
using PairSet = GPOS_impl::PairSet<Types>;
|
||||
using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat[2]; /* [0] Defines the types of data in
|
||||
|
@ -21,11 +25,11 @@ struct PairPosFormat1
|
|||
/* [1] Defines the types of data in
|
||||
* ValueRecord2--for the second glyph
|
||||
* in the pair--may be zero (0) */
|
||||
Array16OfOffset16To<PairSet>
|
||||
Array16Of<typename Types::template OffsetTo<PairSet>>
|
||||
pairSet; /* Array of PairSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (10, pairSet);
|
||||
DEFINE_SIZE_ARRAY (8 + Types::size, pairSet);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -35,7 +39,7 @@ struct PairPosFormat1
|
|||
|
||||
unsigned int len1 = valueFormat[0].get_len ();
|
||||
unsigned int len2 = valueFormat[1].get_len ();
|
||||
PairSet::sanitize_closure_t closure =
|
||||
typename PairSet::sanitize_closure_t closure =
|
||||
{
|
||||
valueFormat,
|
||||
len1,
|
||||
|
@ -51,7 +55,7 @@ struct PairPosFormat1
|
|||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (*glyphs, hb_first)
|
||||
| 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); })
|
||||
| hb_any
|
||||
;
|
||||
|
@ -127,7 +131,7 @@ struct PairPosFormat1
|
|||
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| 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 *o = out->pairSet.serialize_append (c->serializer);
|
||||
|
@ -160,7 +164,7 @@ struct PairPosFormat1
|
|||
|
||||
unsigned format1 = 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))
|
||||
{
|
||||
const PairSet& set = (this + _);
|
||||
|
|
|
@ -7,11 +7,12 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct PairPosFormat2
|
||||
template <typename Types>
|
||||
struct PairPosFormat2_4
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat1; /* ValueRecord definition--for the
|
||||
|
@ -20,11 +21,11 @@ struct PairPosFormat2
|
|||
ValueFormat valueFormat2; /* ValueRecord definition--for the
|
||||
* second glyph of the pair--may be
|
||||
* zero (0) */
|
||||
Offset16To<ClassDef>
|
||||
typename Types::template OffsetTo<ClassDef>
|
||||
classDef1; /* Offset to ClassDef table--from
|
||||
* beginning of PairPos subtable--for
|
||||
* the first glyph of the pair */
|
||||
Offset16To<ClassDef>
|
||||
typename Types::template OffsetTo<ClassDef>
|
||||
classDef2; /* Offset to ClassDef table--from
|
||||
* beginning of PairPos subtable--for
|
||||
* the second glyph of the pair */
|
||||
|
@ -36,7 +37,7 @@ struct PairPosFormat2
|
|||
* class1-major, class2-minor,
|
||||
* Each entry has value1 and value2 */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (16, values);
|
||||
DEFINE_SIZE_ARRAY (10 + 3 * Types::size, values);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -8,9 +8,13 @@ namespace Layout {
|
|||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct PairSet
|
||||
{
|
||||
friend struct PairPosFormat1;
|
||||
template <typename Types2>
|
||||
friend struct PairPosFormat1_3;
|
||||
|
||||
using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
|
||||
|
||||
protected:
|
||||
HBUINT16 len; /* Number of PairValueRecords */
|
||||
|
@ -136,7 +140,7 @@ struct PairSet
|
|||
unsigned len2 = valueFormats[1].get_len ();
|
||||
unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
|
||||
|
||||
PairValueRecord::context_t context =
|
||||
typename PairValueRecord::context_t context =
|
||||
{
|
||||
this,
|
||||
valueFormats,
|
||||
|
|
|
@ -6,18 +6,21 @@ namespace Layout {
|
|||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct PairValueRecord
|
||||
{
|
||||
template <typename Types2>
|
||||
friend struct PairSet;
|
||||
|
||||
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
|
||||
* Coverage table */
|
||||
ValueRecord values; /* Positioning data for the first glyph
|
||||
* followed by for second glyph */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, values);
|
||||
DEFINE_SIZE_ARRAY (Types::size, values);
|
||||
|
||||
int cmp (hb_codepoint_t k) const
|
||||
{ return secondGlyph.cmp (k); }
|
||||
|
|
|
@ -7,10 +7,11 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct AlternateSet
|
||||
{
|
||||
protected:
|
||||
Array16Of<HBGlyphID16>
|
||||
Array16Of<typename Types::HBGlyphID>
|
||||
alternates; /* Array of alternate GlyphIDs--in
|
||||
* arbitrary order */
|
||||
public:
|
||||
|
|
|
@ -13,7 +13,10 @@ struct AlternateSubst
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
AlternateSubstFormat1 format1;
|
||||
AlternateSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
AlternateSubstFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
public:
|
||||
|
||||
|
@ -24,10 +27,15 @@ struct AlternateSubst
|
|||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> alternate_len_list,
|
||||
|
@ -42,6 +50,9 @@ struct AlternateSubst
|
|||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO subset() should choose format. */
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -8,18 +8,19 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct AlternateSubstFormat1
|
||||
template <typename Types>
|
||||
struct AlternateSubstFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
Array16OfOffset16To<AlternateSet>
|
||||
Array16Of<typename Types::template OffsetTo<AlternateSet<Types>>>
|
||||
alternateSet; /* Array of AlternateSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, alternateSet);
|
||||
DEFINE_SIZE_ARRAY (2 + 2 * Types::size, alternateSet);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -39,7 +40,7 @@ struct AlternateSubstFormat1
|
|||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| 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_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
|
||||
| hb_apply ([c] (const AlternateSet<Types> &_) { _.collect_glyphs (c); })
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,16 +7,18 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct Ligature
|
||||
{
|
||||
protected:
|
||||
HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */
|
||||
HeadlessArrayOf<HBGlyphID16>
|
||||
typename Types::HBGlyphID
|
||||
ligGlyph; /* GlyphID of ligature to substitute */
|
||||
HeadlessArrayOf<typename Types::HBGlyphID>
|
||||
component; /* Array of component GlyphIDs--start
|
||||
* with the second component--ordered
|
||||
* in writing direction */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, component);
|
||||
DEFINE_SIZE_ARRAY (Types::size + 2, component);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -8,10 +8,11 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct LigatureSet
|
||||
{
|
||||
protected:
|
||||
Array16OfOffset16To<Ligature>
|
||||
Array16OfOffset16To<Ligature<Types>>
|
||||
ligature; /* Array LigatureSet tables
|
||||
* ordered by preference */
|
||||
public:
|
||||
|
@ -28,7 +29,7 @@ struct LigatureSet
|
|||
return
|
||||
+ hb_iter (ligature)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
|
||||
| hb_map ([glyphs] (const Ligature<Types> &_) { return _.intersects (glyphs); })
|
||||
| hb_any
|
||||
;
|
||||
}
|
||||
|
@ -37,7 +38,7 @@ struct LigatureSet
|
|||
{
|
||||
+ hb_iter (ligature)
|
||||
| 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_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
|
||||
+ hb_iter (ligature)
|
||||
| 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
|
||||
;
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ struct LigatureSet
|
|||
unsigned int num_ligs = ligature.len;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,10 @@ struct LigatureSubst
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
LigatureSubstFormat1 format1;
|
||||
LigatureSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
LigatureSubstFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
|
@ -24,10 +27,16 @@ struct LigatureSubst
|
|||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
hb_sorted_array_t<const HBGlyphID16> first_glyphs,
|
||||
hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
|
||||
|
@ -49,6 +58,9 @@ struct LigatureSubst
|
|||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO subset() should choose format. */
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,18 +8,19 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct LigatureSubstFormat1
|
||||
template <typename Types>
|
||||
struct LigatureSubstFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
Array16OfOffset16To<LigatureSet>
|
||||
Array16Of<typename Types::template OffsetTo<LigatureSet<Types>>>
|
||||
ligatureSet; /* Array LigatureSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, ligatureSet);
|
||||
DEFINE_SIZE_ARRAY (4 + Types::size, ligatureSet);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -33,7 +34,7 @@ struct LigatureSubstFormat1
|
|||
+ hb_zip (this+coverage, ligatureSet)
|
||||
| hb_filter (*glyphs, hb_first)
|
||||
| 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); })
|
||||
| hb_any
|
||||
;
|
||||
|
@ -48,7 +49,7 @@ struct LigatureSubstFormat1
|
|||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| 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_map (hb_second)
|
||||
| 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]);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -84,7 +85,7 @@ struct LigatureSubstFormat1
|
|||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -128,7 +129,7 @@ struct LigatureSubstFormat1
|
|||
hb_set_t new_coverage;
|
||||
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter ([&] (const LigatureSet& _) {
|
||||
| hb_filter ([&] (const LigatureSet<Types>& _) {
|
||||
return _.intersects (&glyphset);
|
||||
}, hb_second)
|
||||
| hb_map (hb_first)
|
||||
|
|
|
@ -13,7 +13,10 @@ struct MultipleSubst
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
MultipleSubstFormat1 format1;
|
||||
MultipleSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
MultipleSubstFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
|
@ -25,10 +28,15 @@ struct MultipleSubst
|
|||
if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
|
||||
switch (u.format) {
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> substitute_len_list,
|
||||
|
@ -43,6 +51,9 @@ struct MultipleSubst
|
|||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO subset() should choose format. */
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,18 +8,19 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct MultipleSubstFormat1
|
||||
template <typename Types>
|
||||
struct MultipleSubstFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
Array16OfOffset16To<Sequence>
|
||||
Array16Of<typename Types::template OffsetTo<Sequence<Types>>>
|
||||
sequence; /* Array of Sequence tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, sequence);
|
||||
DEFINE_SIZE_ARRAY (4 + Types::size, sequence);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -39,7 +40,7 @@ struct MultipleSubstFormat1
|
|||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| 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_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
|
||||
| hb_apply ([c] (const Sequence<Types> &_) { _.collect_glyphs (c); })
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,10 +7,11 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct Sequence
|
||||
{
|
||||
protected:
|
||||
Array16Of<HBGlyphID16>
|
||||
Array16Of<typename Types::HBGlyphID>
|
||||
substitute; /* String of GlyphIDs to substitute */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, substitute);
|
||||
|
|
|
@ -14,8 +14,12 @@ struct SingleSubst
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
SingleSubstFormat1 format1;
|
||||
SingleSubstFormat2 format2;
|
||||
SingleSubstFormat1_3<SmallTypes> format1;
|
||||
SingleSubstFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
SingleSubstFormat1_3<MediumTypes> format3;
|
||||
SingleSubstFormat2_4<MediumTypes> format4;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
|
@ -28,6 +32,10 @@ struct SingleSubst
|
|||
switch (u.format) {
|
||||
case 1: return_trace (c->dispatch (u.format1, 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 ());
|
||||
}
|
||||
}
|
||||
|
@ -45,11 +53,24 @@ struct SingleSubst
|
|||
if (glyphs)
|
||||
{
|
||||
format = 1;
|
||||
auto get_delta = [=] (hb_codepoint_pair_t _)
|
||||
{ return (unsigned) (_.second - _.first) & 0xFFFF; };
|
||||
delta = get_delta (*glyphs);
|
||||
if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
|
||||
hb_codepoint_t mask = 0xFFFFu;
|
||||
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
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;
|
||||
switch (u.format) {
|
||||
case 1: return_trace (u.format1.serialize (c,
|
||||
|
@ -57,6 +78,13 @@ struct SingleSubst
|
|||
| hb_map_retains_sorting (hb_first),
|
||||
delta));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,18 +7,20 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct SingleSubstFormat1
|
||||
template <typename Types>
|
||||
struct SingleSubstFormat1_3
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* 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 */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
DEFINE_SIZE_STATIC (2 + 2 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -7,19 +7,20 @@ namespace OT {
|
|||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct SingleSubstFormat2
|
||||
template <typename Types>
|
||||
struct SingleSubstFormat2_4
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
Offset16To<Coverage>
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
Array16Of<HBGlyphID16>
|
||||
Array16Of<typename Types::HBGlyphID>
|
||||
substitute; /* Array of substitute
|
||||
* GlyphIDs--ordered by Coverage Index */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, substitute);
|
||||
DEFINE_SIZE_ARRAY (4 + Types::size, substitute);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
@ -103,7 +104,7 @@ struct SingleSubstFormat2
|
|||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| 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]); })
|
||||
;
|
||||
|
||||
|
|
|
@ -25,13 +25,16 @@ struct CompositeGlyphRecord
|
|||
USE_MY_METRICS = 0x0200,
|
||||
OVERLAP_COMPOUND = 0x0400,
|
||||
SCALED_COMPONENT_OFFSET = 0x0800,
|
||||
UNSCALED_COMPONENT_OFFSET = 0x1000
|
||||
UNSCALED_COMPONENT_OFFSET = 0x1000,
|
||||
GID_IS_24BIT = 0x2000
|
||||
};
|
||||
|
||||
public:
|
||||
unsigned int get_size () const
|
||||
{
|
||||
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 */
|
||||
if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
|
||||
/* arg1 and 2 are int8 */
|
||||
|
@ -60,7 +63,11 @@ struct CompositeGlyphRecord
|
|||
bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
|
||||
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)
|
||||
{
|
||||
point1 = ((const HBUINT16 *) p)[0];
|
||||
|
@ -101,8 +108,12 @@ struct CompositeGlyphRecord
|
|||
matrix[0] = matrix[3] = 1.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;
|
||||
const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
|
||||
if (flags & ARG_1_AND_2_ARE_WORDS)
|
||||
{
|
||||
tx = *(const HBINT16 *) p;
|
||||
|
@ -145,8 +156,25 @@ struct CompositeGlyphRecord
|
|||
}
|
||||
|
||||
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;
|
||||
HBGlyphID16 glyphIndex;
|
||||
HBUINT24 pad;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (4);
|
||||
};
|
||||
|
|
|
@ -146,7 +146,7 @@ struct Glyph
|
|||
for (auto &item : get_composite_iterator ())
|
||||
{
|
||||
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,
|
||||
phantom_only, depth + 1)))
|
||||
return false;
|
||||
|
|
|
@ -42,8 +42,8 @@ struct SubsetGlyph
|
|||
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
||||
{
|
||||
hb_codepoint_t new_gid;
|
||||
if (plan->new_gid_for_old_gid (_.glyphIndex, &new_gid))
|
||||
const_cast<CompositeGlyphRecord &> (_).glyphIndex = new_gid;
|
||||
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
||||
const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
|
||||
}
|
||||
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
|
|
|
@ -743,8 +743,8 @@ template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUI
|
|||
template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
|
||||
|
||||
/* Array of offsets relative to the beginning of the array itself. */
|
||||
template <typename Type>
|
||||
struct List16OfOffset16To : Array16OfOffset16To<Type>
|
||||
template <typename Type, typename OffsetType>
|
||||
struct List16OfOffsetTo : ArrayOf<OffsetTo<Type, OffsetType>, HBUINT16>
|
||||
{
|
||||
const Type& operator [] (int i_) const
|
||||
{
|
||||
|
@ -762,7 +762,7 @@ struct List16OfOffset16To : Array16OfOffset16To<Type>
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
struct List16OfOffset16To<Type> *out = c->serializer->embed (*this);
|
||||
struct List16OfOffsetTo *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
unsigned int count = this->len;
|
||||
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
|
||||
{
|
||||
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. */
|
||||
template <typename Type, typename LenType=HBUINT16>
|
||||
struct HeadlessArrayOf
|
||||
|
|
|
@ -80,8 +80,34 @@
|
|||
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>
|
||||
static inline void Coverage_serialize (hb_serialize_context_t *c,
|
||||
|
@ -510,6 +536,7 @@ struct RecordListOfScript : RecordListOf<Script>
|
|||
}
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
struct RangeRecord
|
||||
{
|
||||
int cmp (hb_codepoint_t g) const
|
||||
|
@ -528,13 +555,13 @@ struct RangeRecord
|
|||
bool collect_coverage (set_t *glyphs) const
|
||||
{ return glyphs->add_range (first, last); }
|
||||
|
||||
HBGlyphID16 first; /* First GlyphID in the range */
|
||||
HBGlyphID16 last; /* Last GlyphID in the range */
|
||||
typename Types::HBGlyphID first; /* First GlyphID in the range */
|
||||
typename Types::HBGlyphID last; /* Last GlyphID in the range */
|
||||
HBUINT16 value; /* Value */
|
||||
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>
|
||||
|
@ -1377,10 +1404,11 @@ struct Lookup
|
|||
DEFINE_SIZE_ARRAY (6, subTable);
|
||||
};
|
||||
|
||||
typedef List16OfOffset16To<Lookup> LookupList;
|
||||
template <typename Types>
|
||||
using LookupList = List16OfOffsetTo<Lookup, typename Types::HBUINT>;
|
||||
|
||||
template <typename TLookup>
|
||||
struct LookupOffsetList : List16OfOffset16To<TLookup>
|
||||
template <typename TLookup, typename OffsetType>
|
||||
struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
|
||||
{
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
|
@ -1410,7 +1438,8 @@ struct LookupOffsetList : List16OfOffset16To<TLookup>
|
|||
* Coverage Table
|
||||
*/
|
||||
|
||||
struct CoverageFormat1
|
||||
template <typename Types>
|
||||
struct CoverageFormat1_3
|
||||
{
|
||||
friend struct Coverage;
|
||||
|
||||
|
@ -1463,7 +1492,7 @@ struct CoverageFormat1
|
|||
/* Older compilers need this to be public. */
|
||||
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 () {}
|
||||
bool more () const { return i < c->glyphArray.len; }
|
||||
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; }
|
||||
|
||||
private:
|
||||
const struct CoverageFormat1 *c;
|
||||
const struct CoverageFormat1_3 *c;
|
||||
unsigned int i;
|
||||
};
|
||||
private:
|
||||
|
||||
protected:
|
||||
HBUINT16 coverageFormat; /* Format identifier--format = 1 */
|
||||
SortedArray16Of<HBGlyphID16>
|
||||
SortedArray16Of<typename Types::HBGlyphID>
|
||||
glyphArray; /* Array of GlyphIDs--in numerical order */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, glyphArray);
|
||||
};
|
||||
|
||||
struct CoverageFormat2
|
||||
template <typename Types>
|
||||
struct CoverageFormat2_4
|
||||
{
|
||||
friend struct Coverage;
|
||||
|
||||
private:
|
||||
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)
|
||||
? (unsigned int) range.value + (glyph_id - range.first)
|
||||
: NOT_COVERED;
|
||||
|
@ -1548,14 +1578,14 @@ struct CoverageFormat2
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
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
|
||||
{
|
||||
auto cmp = [] (const void *pk, const void *pr) -> int
|
||||
{
|
||||
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 > (unsigned int) range.value + (range.last - range.first)) return +1;
|
||||
return 0;
|
||||
|
@ -1596,7 +1626,7 @@ struct CoverageFormat2
|
|||
/* Older compilers need this to be public. */
|
||||
struct iter_t
|
||||
{
|
||||
void init (const CoverageFormat2 &c_)
|
||||
void init (const CoverageFormat2_4 &c_)
|
||||
{
|
||||
c = &c_;
|
||||
coverage = 0;
|
||||
|
@ -1650,7 +1680,7 @@ struct CoverageFormat2
|
|||
}
|
||||
|
||||
private:
|
||||
const struct CoverageFormat2 *c;
|
||||
const struct CoverageFormat2_4 *c;
|
||||
unsigned int i, coverage;
|
||||
hb_codepoint_t j;
|
||||
};
|
||||
|
@ -1658,7 +1688,7 @@ struct CoverageFormat2
|
|||
|
||||
protected:
|
||||
HBUINT16 coverageFormat; /* Format identifier--format = 2 */
|
||||
SortedArray16Of<RangeRecord>
|
||||
SortedArray16Of<RangeRecord<Types>>
|
||||
rangeRecord; /* Array of glyph ranges--ordered by
|
||||
* Start GlyphID. rangeCount entries
|
||||
* long */
|
||||
|
@ -1682,6 +1712,10 @@ struct Coverage
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -1705,10 +1739,19 @@ struct Coverage
|
|||
}
|
||||
u.format = count <= num_ranges * 3 ? 1 : 2;
|
||||
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
if (count && last > 0xFFFFu)
|
||||
u.format += 2;
|
||||
#endif
|
||||
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return_trace (u.format1.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);
|
||||
}
|
||||
}
|
||||
|
@ -1737,6 +1780,10 @@ struct Coverage
|
|||
{
|
||||
case 1: return_trace (u.format1.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);
|
||||
}
|
||||
}
|
||||
|
@ -1747,6 +1794,10 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -1756,6 +1807,10 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -1769,6 +1824,10 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -1779,6 +1838,10 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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 ;
|
||||
}
|
||||
}
|
||||
|
@ -1794,6 +1857,10 @@ struct Coverage
|
|||
{
|
||||
case 1: u.format1.init (c_.u.format1); 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;
|
||||
}
|
||||
}
|
||||
|
@ -1803,6 +1870,10 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -1812,6 +1883,10 @@ struct Coverage
|
|||
{
|
||||
case 1: u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -1824,6 +1899,10 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -1834,6 +1913,10 @@ struct Coverage
|
|||
{
|
||||
case 1: return u.format1 != o.u.format1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1845,6 +1928,10 @@ struct Coverage
|
|||
{
|
||||
case 1: it.u.format1 = u.format1.__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;
|
||||
}
|
||||
return it;
|
||||
|
@ -1853,8 +1940,12 @@ struct Coverage
|
|||
private:
|
||||
unsigned int format;
|
||||
union {
|
||||
CoverageFormat2::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
|
||||
CoverageFormat1::iter_t format1;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
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;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
|
@ -1862,8 +1953,12 @@ struct Coverage
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
CoverageFormat1 format1;
|
||||
CoverageFormat2 format2;
|
||||
CoverageFormat1_3<SmallTypes> format1;
|
||||
CoverageFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
CoverageFormat1_3<MediumTypes>format3;
|
||||
CoverageFormat2_4<MediumTypes>format4;
|
||||
#endif
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
|
@ -1915,7 +2010,8 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
|
|||
* Class Definition Table
|
||||
*/
|
||||
|
||||
struct ClassDefFormat1
|
||||
template <typename Types>
|
||||
struct ClassDefFormat1_3
|
||||
{
|
||||
friend struct ClassDef;
|
||||
|
||||
|
@ -2120,14 +2216,16 @@ struct ClassDefFormat1
|
|||
|
||||
protected:
|
||||
HBUINT16 classFormat; /* Format identifier--format = 1 */
|
||||
HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */
|
||||
Array16Of<HBUINT16>
|
||||
typename Types::HBGlyphID
|
||||
startGlyph; /* First GlyphID of the classValueArray */
|
||||
typename Types::template ArrayOf<HBUINT16>
|
||||
classValue; /* Array of Class Values--one per GlyphID */
|
||||
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;
|
||||
|
||||
|
@ -2156,12 +2254,12 @@ struct ClassDefFormat2
|
|||
hb_codepoint_t prev_gid = (*it).first;
|
||||
unsigned prev_klass = (*it).second;
|
||||
|
||||
RangeRecord range_rec;
|
||||
RangeRecord<Types> range_rec;
|
||||
range_rec.first = prev_gid;
|
||||
range_rec.last = prev_gid;
|
||||
range_rec.value = prev_klass;
|
||||
|
||||
RangeRecord *record = c->copy (range_rec);
|
||||
auto *record = c->copy (range_rec);
|
||||
if (unlikely (!record)) return_trace (false);
|
||||
|
||||
for (const auto gid_klass_pair : + (++it))
|
||||
|
@ -2300,7 +2398,7 @@ struct ClassDefFormat2
|
|||
}
|
||||
/* TODO Speed up, using set overlap first? */
|
||||
/* TODO(iter) Rewrite as dagger. */
|
||||
const RangeRecord *arr = rangeRecord.arrayZ;
|
||||
const auto *arr = rangeRecord.arrayZ;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (arr[i].value == klass && arr[i].intersects (glyphs))
|
||||
return true;
|
||||
|
@ -2376,18 +2474,18 @@ struct ClassDefFormat2
|
|||
if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
|
||||
intersect_classes->add (0);
|
||||
|
||||
for (const RangeRecord& record : rangeRecord.iter ())
|
||||
for (const auto& record : rangeRecord.iter ())
|
||||
if (record.intersects (glyphs))
|
||||
intersect_classes->add (record.value);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 classFormat; /* Format identifier--format = 2 */
|
||||
SortedArray16Of<RangeRecord>
|
||||
typename Types::template SortedArrayOf<RangeRecord<Types>>
|
||||
rangeRecord; /* Array of glyph ranges--ordered by
|
||||
* Start GlyphID */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, rangeRecord);
|
||||
DEFINE_SIZE_ARRAY (2 + Types::size, rangeRecord);
|
||||
};
|
||||
|
||||
struct ClassDef
|
||||
|
@ -2406,6 +2504,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -2420,10 +2522,11 @@ struct ClassDef
|
|||
auto it = + it_with_class_zero | hb_filter (hb_second);
|
||||
|
||||
unsigned format = 2;
|
||||
hb_codepoint_t glyph_max = 0;
|
||||
if (likely (it))
|
||||
{
|
||||
hb_codepoint_t glyph_min = (*it).first;
|
||||
hb_codepoint_t glyph_max = glyph_min;
|
||||
glyph_max = glyph_min;
|
||||
|
||||
unsigned num_glyphs = 0;
|
||||
unsigned num_ranges = 1;
|
||||
|
@ -2448,12 +2551,22 @@ struct ClassDef
|
|||
if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
|
||||
format = 1;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
if (glyph_max > 0xFFFFu)
|
||||
format += 2;
|
||||
#endif
|
||||
|
||||
u.format = format;
|
||||
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return_trace (u.format1.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);
|
||||
}
|
||||
}
|
||||
|
@ -2468,6 +2581,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
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));
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
@ -2479,6 +2596,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return_trace (u.format1.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);
|
||||
}
|
||||
}
|
||||
|
@ -2488,6 +2609,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -2500,6 +2625,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -2512,6 +2641,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -2521,6 +2654,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -2529,6 +2666,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -2538,6 +2679,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -2547,6 +2692,10 @@ struct ClassDef
|
|||
switch (u.format) {
|
||||
case 1: return u.format1.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;
|
||||
}
|
||||
}
|
||||
|
@ -2555,8 +2704,12 @@ struct ClassDef
|
|||
protected:
|
||||
union {
|
||||
HBUINT16 format; /* Format identifier */
|
||||
ClassDefFormat1 format1;
|
||||
ClassDefFormat2 format2;
|
||||
ClassDefFormat1_3<SmallTypes> format1;
|
||||
ClassDefFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
ClassDefFormat1_3<MediumTypes>format3;
|
||||
ClassDefFormat2_4<MediumTypes>format4;
|
||||
#endif
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -156,6 +156,71 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
|
|||
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>
|
||||
static inline void
|
||||
_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);
|
||||
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 ();
|
||||
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 ())
|
||||
operation_count =
|
||||
_glyf_add_gid_and_children (glyf,
|
||||
item.glyphIndex,
|
||||
item.get_gid (),
|
||||
gids_to_retain,
|
||||
operation_count,
|
||||
depth);
|
||||
|
|
Loading…
Reference in New Issue