[subset] Anchor should only use format 1 when hints are dropped.

Refactor Anchor to have a subset method instead of copy. This also allows
use to use serialize_subset in several places which simplifies calculating
offset bases.
This commit is contained in:
Garret Rieger 2021-04-02 14:37:10 -07:00 committed by Behdad Esfahbod
parent 71d6d15600
commit 6f98a8ed46
1 changed files with 98 additions and 97 deletions

View File

@ -346,7 +346,9 @@ struct AnchorFormat1
AnchorFormat1* copy (hb_serialize_context_t *c) const AnchorFormat1* copy (hb_serialize_context_t *c) const
{ {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
return_trace (c->embed<AnchorFormat1> (this)); AnchorFormat1* out = c->embed<AnchorFormat1> (this);
out->format = 1;
return_trace (out);
} }
protected: protected:
@ -485,14 +487,20 @@ struct Anchor
} }
} }
Anchor* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SERIALIZE (this); TRACE_SUBSET (this);
if (c->plan->drop_hints)
// AnchorFormat 2 and 3 just containing extra hinting information, so
// if hints are being dropped convert to format 1.
return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
switch (u.format) { switch (u.format) {
case 1: return_trace (reinterpret_cast<Anchor *> (u.format1.copy (c))); case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
case 2: return_trace (reinterpret_cast<Anchor *> (u.format2.copy (c))); case 2: return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
case 3: return_trace (reinterpret_cast<Anchor *> (u.format3.copy (c, layout_variation_idx_map))); case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
default:return_trace (nullptr); c->plan->layout_variation_idx_map))));
default:return_trace (false);
} }
} }
@ -541,48 +549,26 @@ struct AnchorMatrix
} }
template <typename Iterator, template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))> hb_requires (hb_is_iterator (Iterator))>
bool serialize (hb_serialize_context_t *c,
unsigned num_rows,
AnchorMatrix const *offset_matrix,
const hb_map_t *layout_variation_idx_map,
Iterator index_iter)
{
TRACE_SERIALIZE (this);
if (!index_iter) return_trace (false);
if (unlikely (!c->extend_min ((*this)))) return_trace (false);
this->rows = num_rows;
for (const unsigned i : index_iter)
{
auto *offset = c->embed (offset_matrix->matrixZ[i]);
if (!offset) return_trace (false);
offset->serialize_copy (c, offset_matrix->matrixZ[i],
offset_matrix, c->to_bias (this),
hb_serialize_context_t::Head,
layout_variation_idx_map);
}
return_trace (true);
}
bool subset (hb_subset_context_t *c, bool subset (hb_subset_context_t *c,
unsigned cols, unsigned num_rows,
const hb_map_t *klass_mapping) const Iterator index_iter) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
auto *out = c->serializer->start_embed (*this);
auto indexes = auto *out = c->serializer->start_embed (this);
+ hb_range (rows * cols)
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); }) if (!index_iter) return_trace (false);
; if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->rows = num_rows;
for (const unsigned i : index_iter)
{
auto *offset = c->serializer->embed (matrixZ[i]);
if (!offset) return_trace (false);
offset->serialize_subset (c, matrixZ[i], this);
}
out->serialize (c->serializer,
(unsigned) rows,
this,
c->plan->layout_variation_idx_map,
indexes);
return_trace (true); return_trace (true);
} }
@ -618,18 +604,16 @@ struct MarkRecord
return_trace (c->check_struct (this) && markAnchor.sanitize (c, base)); return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
} }
MarkRecord *copy (hb_serialize_context_t *c, MarkRecord *subset (hb_subset_context_t *c,
const void *src_base, const void *src_base,
unsigned dst_bias, const hb_map_t *klass_mapping) const
const hb_map_t *klass_mapping,
const hb_map_t *layout_variation_idx_map) const
{ {
TRACE_SERIALIZE (this); TRACE_SUBSET (this);
auto *out = c->embed (this); auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (nullptr); if (unlikely (!out)) return_trace (nullptr);
out->klass = klass_mapping->get (klass); out->klass = klass_mapping->get (klass);
out->markAnchor.serialize_copy (c, markAnchor, src_base, dst_bias, hb_serialize_context_t::Head, layout_variation_idx_map); out->markAnchor.serialize_subset (c, markAnchor, src_base);
return_trace (out); return_trace (out);
} }
@ -684,18 +668,35 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage or
return_trace (true); return_trace (true);
} }
template<typename Iterator, template <typename Iterator,
hb_requires (hb_is_source_of (Iterator, MarkRecord))> hb_requires (hb_is_iterator (Iterator))>
bool serialize (hb_serialize_context_t *c, bool subset (hb_subset_context_t *c,
const hb_map_t *klass_mapping, Iterator coverage,
const hb_map_t *layout_variation_idx_map, const hb_map_t *klass_mapping) const
const void *base,
Iterator it)
{ {
TRACE_SERIALIZE (this); TRACE_SUBSET (this);
if (unlikely (!c->extend_min (*this))) return_trace (false); const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
if (unlikely (!c->check_assign (len, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return_trace (false);
c->copy_all (it, base, c->to_bias (this), klass_mapping, layout_variation_idx_map); auto* out = c->serializer->start_embed (this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
auto mark_iter =
+ hb_zip (coverage, this->iter ())
| hb_filter (glyphset, hb_first)
| hb_map (hb_second)
;
unsigned new_length = 0;
for (const auto& mark_record : mark_iter) {
if (unlikely (!mark_record.subset (c, this, klass_mapping)))
return_trace (false);
new_length++;
}
if (unlikely (!c->serializer->check_assign (out->len, new_length,
HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
return_trace (false);
return_trace (true); return_trace (true);
} }
@ -1567,17 +1568,15 @@ struct EntryExitRecord
(src_base+exitAnchor).collect_variation_indices (c); (src_base+exitAnchor).collect_variation_indices (c);
} }
EntryExitRecord* copy (hb_serialize_context_t *c, EntryExitRecord* subset (hb_subset_context_t *c,
const void *src_base, const void *src_base) const
const void *dst_base,
const hb_map_t *layout_variation_idx_map) const
{ {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
auto *out = c->embed (this); auto *out = c->serializer->embed (this);
if (unlikely (!out)) return_trace (nullptr); if (unlikely (!out)) return_trace (nullptr);
out->entryAnchor.serialize_copy (c, entryAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map); out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
out->exitAnchor.serialize_copy (c, exitAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map); out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
return_trace (out); return_trace (out);
} }
@ -1727,25 +1726,24 @@ struct CursivePosFormat1
template <typename Iterator, template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))> hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c, void serialize (hb_subset_context_t *c,
Iterator it, Iterator it,
const void *src_base, const void *src_base)
const hb_map_t *layout_variation_idx_map)
{ {
if (unlikely (!c->extend_min ((*this)))) return; if (unlikely (!c->serializer->extend_min ((*this)))) return;
this->format = 1; this->format = 1;
this->entryExitRecord.len = it.len (); this->entryExitRecord.len = it.len ();
for (const EntryExitRecord& entry_record : + it for (const EntryExitRecord& entry_record : + it
| hb_map (hb_second)) | hb_map (hb_second))
c->copy (entry_record, src_base, this, layout_variation_idx_map); entry_record.subset (c, src_base);
auto glyphs = auto glyphs =
+ it + it
| hb_map_retains_sorting (hb_first) | hb_map_retains_sorting (hb_first)
; ;
coverage.serialize (c, this).serialize (c, glyphs); coverage.serialize (c->serializer, this).serialize (c->serializer, glyphs);
} }
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
@ -1765,7 +1763,7 @@ struct CursivePosFormat1
; ;
bool ret = bool (it); bool ret = bool (it);
out->serialize (c->serializer, it, this, c->plan->layout_variation_idx_map); out->serialize (c, it, this);
return_trace (ret); return_trace (ret);
} }
@ -1956,9 +1954,9 @@ struct MarkBasePosFormat1
.serialize (c->serializer, new_coverage.iter ())) .serialize (c->serializer, new_coverage.iter ()))
return_trace (false); return_trace (false);
out->markArray.serialize (c->serializer, out) out->markArray.serialize_subset (c, markArray, this,
.serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+markArray), + mark_iter (this+markCoverage).iter (),
| hb_map (hb_second)); &klass_mapping);
unsigned basecount = (this+baseArray).rows; unsigned basecount = (this+baseArray).rows;
auto base_iter = auto base_iter =
@ -1987,8 +1985,10 @@ struct MarkBasePosFormat1
| hb_sink (base_indexes) | hb_sink (base_indexes)
; ;
} }
out->baseArray.serialize (c->serializer, out)
.serialize (c->serializer, base_iter.len (), &(this+baseArray), c->plan->layout_variation_idx_map, base_indexes.iter ()); out->baseArray.serialize_subset (c, baseArray, this,
base_iter.len (),
base_indexes.iter ());
return_trace (true); return_trace (true);
} }
@ -2054,7 +2054,7 @@ struct LigatureArray : List16OfOffset16To<LigatureAttach>
template <typename Iterator, template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))> hb_requires (hb_is_iterator (Iterator))>
bool subset (hb_subset_context_t *c, bool subset (hb_subset_context_t *c,
Iterator coverage, Iterator coverage,
unsigned class_count, unsigned class_count,
const hb_map_t *klass_mapping) const const hb_map_t *klass_mapping) const
{ {
@ -2070,11 +2070,16 @@ struct LigatureArray : List16OfOffset16To<LigatureAttach>
auto *matrix = out->serialize_append (c->serializer); auto *matrix = out->serialize_append (c->serializer);
if (unlikely (!matrix)) return_trace (false); if (unlikely (!matrix)) return_trace (false);
const LigatureAttach& src = (this + _.second);
auto indexes =
+ hb_range (src.rows * class_count)
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
;
matrix->serialize_subset (c, matrix->serialize_subset (c,
_.second, _.second,
this, this,
class_count, src.rows,
klass_mapping); indexes);
} }
return_trace (this->len); return_trace (this->len);
} }
@ -2208,13 +2213,9 @@ struct MarkLigPosFormat1
.serialize (c->serializer, new_mark_coverage)) .serialize (c->serializer, new_mark_coverage))
return_trace (false); return_trace (false);
out->markArray.serialize (c->serializer, out) out->markArray.serialize_subset (c, markArray, this,
.serialize (c->serializer, (this+markCoverage).iter (),
&klass_mapping, &klass_mapping);
c->plan->layout_variation_idx_map,
&(this+markArray),
+ mark_iter
| hb_map (hb_second));
auto new_ligature_coverage = auto new_ligature_coverage =
+ hb_iter (this + ligatureCoverage) + hb_iter (this + ligatureCoverage)
@ -2416,9 +2417,9 @@ struct MarkMarkPosFormat1
.serialize (c->serializer, new_coverage.iter ())) .serialize (c->serializer, new_coverage.iter ()))
return_trace (false); return_trace (false);
out->mark1Array.serialize (c->serializer, out) out->mark1Array.serialize_subset (c, mark1Array, this,
.serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+mark1Array), + mark1_iter (this+mark1Coverage).iter (),
| hb_map (hb_second)); &klass_mapping);
unsigned mark2count = (this+mark2Array).rows; unsigned mark2count = (this+mark2Array).rows;
auto mark2_iter = auto mark2_iter =
@ -2447,8 +2448,8 @@ struct MarkMarkPosFormat1
| hb_sink (mark2_indexes) | hb_sink (mark2_indexes)
; ;
} }
out->mark2Array.serialize (c->serializer, out)
.serialize (c->serializer, mark2_iter.len (), &(this+mark2Array), c->plan->layout_variation_idx_map, mark2_indexes.iter ()); out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
return_trace (true); return_trace (true);
} }