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:
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 ());
}
}

View File

@ -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
{

View File

@ -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 ());
}
}

View File

@ -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
{

View File

@ -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 ());
}
}

View File

@ -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
{

View File

@ -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 ());
}
}

View File

@ -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 + _);

View File

@ -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
{

View File

@ -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,

View File

@ -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); }

View File

@ -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:

View File

@ -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. */
};
}

View File

@ -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); })
;
}

View File

@ -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
{

View File

@ -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);
}

View File

@ -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. */
};

View File

@ -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)

View File

@ -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. */
};

View File

@ -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); })
;
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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
{

View File

@ -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]); })
;

View File

@ -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);
};

View File

@ -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;

View File

@ -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)

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>;
/* 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

View File

@ -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

View File

@ -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);