[color] Rewrite colr access
authorBehdad Esfahbod <behdad@behdad.org>
Mon, 22 Oct 2018 19:40:38 +0000 (12:40 -0700)
committerBehdad Esfahbod <behdad@behdad.org>
Mon, 22 Oct 2018 21:21:23 +0000 (14:21 -0700)
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.

src/hb-dsalgs.hh
src/hb-open-type.hh
src/hb-ot-color-colr-table.hh
src/hb-ot-color.cc

index eb15c08..7e1b7eb 100644 (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;
index 08e7206..be0d8b0 100644 (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))
index acad257..7c5c35d 100644 (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;
-
-    if (first_layer) *first_layer = record->firstLayerIdx;
-    if (num_layers) *num_layers = record->numLayers;
-    return true;
-  }
+    const BaseGlyphRecord &record = get_glyph_record (glyph);
 
-  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. */
index 2672d0a..08d98a9 100644 (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);
 }