[color] Rewrite colr access

COLR table has one function: return layers for a glyph, and we expose exactly
that, so should just wire it through.  Also use sub_array() for verifiable
safety.

Also, BaseGlyphRecord's null object is enough.  We don't need to special-case
the not-found.
This commit is contained in:
Behdad Esfahbod 2018-10-22 12:40:38 -07:00
parent 1de17bdb80
commit 3bf91bd269
4 changed files with 41 additions and 44 deletions

View File

@ -521,6 +521,17 @@ struct hb_array_t
return arrayZ[i];
}
inline hb_array_t<T> sub_array (unsigned int start_offset, unsigned int seg_count) const
{
unsigned int count = len;
if (unlikely (start_offset > count))
count = 0;
else
count -= start_offset;
count = MIN (count, seg_count);
return hb_array_t<T> (arrayZ + start_offset, count);
}
inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
const T *arrayZ;

View File

@ -417,7 +417,7 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
template <typename Type, typename LenType=HBUINT16>
struct ArrayOf
{
const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
inline const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
{
unsigned int count = len;
if (unlikely (start_offset > count))

View File

@ -98,35 +98,27 @@ struct COLR
inline bool has_data (void) const { return numBaseGlyphs; }
inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
unsigned int *first_layer /* OUT */,
unsigned int *num_layers /* OUT */) const
inline unsigned int get_glyph_layers (hb_codepoint_t glyph,
unsigned int start_offset,
unsigned int *count, /* IN/OUT. May be NULL. */
hb_ot_color_layer_t *layers /* OUT. May be NULL. */) const
{
const BaseGlyphRecord* record;
record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
sizeof (BaseGlyphRecord), BaseGlyphRecord::cmp);
if (unlikely (!record))
return false;
const BaseGlyphRecord &record = get_glyph_record (glyph);
if (first_layer) *first_layer = record->firstLayerIdx;
if (num_layers) *num_layers = record->numLayers;
return true;
}
inline bool get_layer_record (unsigned int record,
hb_codepoint_t *glyph_id /* OUT */,
unsigned int *color_index /* OUT */) const
{
if (unlikely (record >= numLayers))
hb_array_t<const LayerRecord> all_layers ((this+layersZ).arrayZ, numLayers);
hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
record.numLayers);
if (count)
{
*glyph_id = 0;
*color_index = 0xFFFF;
return false;
hb_array_t<const LayerRecord> segment_layers = glyph_layers.sub_array (start_offset, *count);
*count = segment_layers.len;
for (unsigned int i = 0; i < segment_layers.len; i++)
{
layers[i].glyph = segment_layers.arrayZ[i].glyphId;
layers[i].color_index = segment_layers.arrayZ[i].colorIdx;
}
}
const LayerRecord &layer = (this+layersZ)[record];
if (glyph_id) *glyph_id = layer.glyphId;
if (color_index) *color_index = layer.colorIdx;
return true;
return glyph_layers.len;
}
inline bool sanitize (hb_sanitize_context_t *c) const
@ -137,6 +129,17 @@ struct COLR
(this+layersZ).sanitize (c, numLayers)));
}
private:
inline const BaseGlyphRecord &get_glyph_record (hb_codepoint_t glyph_id) const
{
const BaseGlyphRecord *rec = (BaseGlyphRecord *) bsearch (&glyph_id,
&(this+baseGlyphsZ),
numBaseGlyphs,
sizeof (BaseGlyphRecord),
BaseGlyphRecord::cmp);
return rec ? *rec : Null(BaseGlyphRecord);
}
protected:
HBUINT16 version; /* Table version number (starts at 0). */
HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */

View File

@ -263,22 +263,5 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
hb_ot_color_layer_t *layers /* OUT. May be NULL. */)
{
const OT::COLR& colr = _get_colr (face);
unsigned int num_results = 0;
unsigned int start_layer_index, num_layers = 0;
if (colr.get_base_glyph_record (glyph, &start_layer_index, &num_layers))
{
if (count)
{
unsigned int layer_count = MIN<unsigned int>(*count, num_layers - start_offset);
for (unsigned int i = 0; i < layer_count; i++)
{
if (colr.get_layer_record (start_layer_index + start_offset + i,
&layers[num_results].glyph, &layers[num_results].color_index))
++num_results;
}
}
}
if (likely (count)) *count = num_results;
return num_layers;
return colr.get_glyph_layers (glyph, start_offset, count, layers);
}