[subset] Add subset () method for COLRv1 Paint tables, BaseGlyphV1List and LayerV1List
Also add support for Offset24 in serializer and repacker
This commit is contained in:
parent
413769bf86
commit
b23f29bf05
@ -180,6 +180,15 @@ struct NoVariable
|
||||
template <template<typename> class Var>
|
||||
struct ColorIndex
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colrv1_palettes->get (paletteIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -195,6 +204,13 @@ struct ColorIndex
|
||||
template <template<typename> class Var>
|
||||
struct ColorStop
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (unlikely (!c->serializer->embed (stopOffset))) return_trace (false);
|
||||
return_trace (color.subset (c));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -221,6 +237,23 @@ struct Extend : HBUINT8
|
||||
template <template<typename> class Var>
|
||||
struct ColorLine
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
|
||||
if (!c->serializer->check_assign (out->stops.len, stops.len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)) return_trace (false);
|
||||
|
||||
for (const auto& stop : stops.iter ())
|
||||
{
|
||||
if (!stop.subset (c)) return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -306,6 +339,17 @@ struct PaintColrLayers
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers->get (firstLayerIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -325,6 +369,13 @@ struct PaintSolid
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ c->add_palette_index (color.paletteIndex); }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (unlikely (!c->serializer->embed (format))) return_trace (false);
|
||||
return_trace (color.subset (c));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -346,6 +397,15 @@ struct PaintLinearGradient
|
||||
c->add_palette_index (stop.color.paletteIndex);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -368,6 +428,15 @@ struct PaintLinearGradient
|
||||
template <template<typename> class Var>
|
||||
struct PaintRadialGradient
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
for (const auto &stop : (this+colorLine).stops.iter ())
|
||||
@ -396,6 +465,15 @@ struct PaintRadialGradient
|
||||
template <template<typename> class Var>
|
||||
struct PaintSweepGradient
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{
|
||||
for (const auto &stop : (this+colorLine).stops.iter ())
|
||||
@ -425,6 +503,19 @@ struct PaintGlyph
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (! c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->paint.serialize_subset (c, paint, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -442,6 +533,16 @@ struct PaintColrGlyph
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -459,6 +560,15 @@ struct PaintTransform
|
||||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -477,6 +587,15 @@ struct PaintTranslate
|
||||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -496,6 +615,15 @@ struct PaintRotate
|
||||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -516,6 +644,15 @@ struct PaintSkew
|
||||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -536,6 +673,16 @@ struct PaintComposite
|
||||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!out->src.serialize_subset (c, src, this)) return_trace (false);
|
||||
return_trace (out->backdrop.serialize_subset (c, backdrop, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -615,6 +762,19 @@ struct BaseGlyphV1Record
|
||||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
|
||||
|
||||
bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
|
||||
const void* src_base, hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = s->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (!s->check_assign (out->glyphId, glyph_map->get (glyphId),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->paint.serialize_subset (c, paint, src_base));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -629,13 +789,47 @@ struct BaseGlyphV1Record
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
typedef SortedArray32Of<BaseGlyphV1Record> BaseGlyphV1List;
|
||||
struct BaseGlyphV1List : SortedArray32Of<BaseGlyphV1Record>
|
||||
{
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
const hb_set_t* glyphset = c->plan->_glyphset;
|
||||
|
||||
for (const auto& _ : as_array ())
|
||||
{
|
||||
unsigned gid = _.glyphId;
|
||||
if (!glyphset->has (gid)) continue;
|
||||
|
||||
if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++;
|
||||
else return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
};
|
||||
|
||||
struct LayerV1List : Array32OfOffset32To<Paint>
|
||||
{
|
||||
const Paint& get_paint (unsigned i) const
|
||||
{ return this+(*this)[i]; }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
for (const auto& offset : as_array ()) {
|
||||
auto *o = out->serialize_append (c->serializer);
|
||||
if (unlikely (!o) || !o->serialize_subset (c, offset, this))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -531,7 +531,7 @@ struct graph_t
|
||||
|
||||
const auto& child = vertices_[link.objidx].obj;
|
||||
int64_t child_weight = child.tail - child.head +
|
||||
(!link.is_wide ? (1 << 16) : ((int64_t) 1 << 32));
|
||||
((int64_t) 1 << (link.width * 8));
|
||||
int64_t child_distance = next_distance + child_weight;
|
||||
|
||||
if (child_distance < vertices_[link.objidx].distance)
|
||||
@ -578,15 +578,17 @@ struct graph_t
|
||||
{
|
||||
if (link.is_signed)
|
||||
{
|
||||
if (link.is_wide)
|
||||
if (link.width == 4)
|
||||
return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
|
||||
else
|
||||
return offset >= -(1 << 15) && offset < (1 << 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (link.is_wide)
|
||||
if (link.width == 4)
|
||||
return offset >= 0 && offset < ((int64_t) 1 << 32);
|
||||
else if (link.width == 3)
|
||||
return offset >= 0 && offset < ((int32_t) 1 << 24);
|
||||
else
|
||||
return offset >= 0 && offset < (1 << 16);
|
||||
}
|
||||
@ -627,7 +629,7 @@ struct graph_t
|
||||
char* head,
|
||||
hb_serialize_context_t* c) const
|
||||
{
|
||||
if (link.is_wide)
|
||||
if (link.width == 4)
|
||||
{
|
||||
if (link.is_signed)
|
||||
{
|
||||
@ -635,7 +637,9 @@ struct graph_t
|
||||
} else {
|
||||
serialize_link_of_type<OT::HBUINT32> (link, head, c);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else if (link.width == 2)
|
||||
{
|
||||
if (link.is_signed)
|
||||
{
|
||||
serialize_link_of_type<OT::HBINT16> (link, head, c);
|
||||
@ -643,6 +647,8 @@ struct graph_t
|
||||
serialize_link_of_type<OT::HBUINT16> (link, head, c);
|
||||
}
|
||||
}
|
||||
else
|
||||
serialize_link_of_type<OT::HBUINT24> (link, head, c);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -82,7 +82,7 @@ struct hb_serialize_context_t
|
||||
|
||||
struct link_t
|
||||
{
|
||||
bool is_wide: 1;
|
||||
unsigned width: 3;
|
||||
bool is_signed: 1;
|
||||
unsigned whence: 2;
|
||||
unsigned position: 28;
|
||||
@ -354,7 +354,6 @@ struct hb_serialize_context_t
|
||||
whence_t whence = Head,
|
||||
unsigned bias = 0)
|
||||
{
|
||||
static_assert (sizeof (T) == 2 || sizeof (T) == 4, "");
|
||||
if (unlikely (in_error ())) return;
|
||||
|
||||
if (!objidx)
|
||||
@ -365,7 +364,7 @@ struct hb_serialize_context_t
|
||||
|
||||
auto& link = *current->links.push ();
|
||||
|
||||
link.is_wide = sizeof (T) == 4;
|
||||
link.width = sizeof (T);
|
||||
link.is_signed = hb_is_signed (hb_unwrap_type (T));
|
||||
link.whence = (unsigned) whence;
|
||||
link.position = (const char *) &ofs - current->head;
|
||||
@ -405,15 +404,19 @@ struct hb_serialize_context_t
|
||||
offset -= link.bias;
|
||||
if (link.is_signed)
|
||||
{
|
||||
if (link.is_wide)
|
||||
assert (link.width == 2 || link.width == 4);
|
||||
if (link.width == 4)
|
||||
assign_offset<int32_t> (parent, link, offset);
|
||||
else
|
||||
assign_offset<int16_t> (parent, link, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (link.is_wide)
|
||||
assert (link.width == 2 || link.width == 3 || link.width == 4);
|
||||
if (link.width == 4)
|
||||
assign_offset<uint32_t> (parent, link, offset);
|
||||
else if (link.width == 3)
|
||||
assign_offset<uint32_t, 3> (parent, link, offset);
|
||||
else
|
||||
assign_offset<uint16_t> (parent, link, offset);
|
||||
}
|
||||
@ -566,10 +569,10 @@ struct hb_serialize_context_t
|
||||
{ return packed; }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
template <typename T, unsigned Size = sizeof (T)>
|
||||
void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
|
||||
{
|
||||
auto &off = * ((BEInt<T> *) (parent->head + link.position));
|
||||
auto &off = * ((BEInt<T, Size> *) (parent->head + link.position));
|
||||
assert (0 == off);
|
||||
check_assign (off, offset, HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user