Imported Upstream version 1.8.1
[platform/upstream/harfbuzz.git] / src / hb-ot-color-colr-table.hh
index 2c3b1cc..ce6702d 100644 (file)
 #include "hb-open-type-private.hh"
 
 /*
- * Color Palette
- * http://www.microsoft.com/typography/otspec/colr.htm
+ * COLR -- Color
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/colr
  */
-
 #define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
 
+
 namespace OT {
 
 
@@ -48,8 +48,8 @@ struct LayerRecord
   }
 
   protected:
-  GlyphID gID;                 /* Glyph ID of layer glyph */
-  HBUINT16 paletteIndex;       /* Index value to use with a selected color palette */
+  GlyphID      glyphid;        /* Glyph ID of layer glyph */
+  HBUINT16     colorIdx;       /* Index value to use with a selected color palette */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -61,17 +61,28 @@ struct BaseGlyphRecord
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  inline int cmp (hb_codepoint_t g) const {
+    return g < glyphid ? -1 : g > glyphid ? 1 : 0;
   }
 
   protected:
-  GlyphID gID;                 /* Glyph ID of reference glyph */
-  HBUINT16 firstLayerIndex;    /* Index to the layer record */
-  HBUINT16 numLayers;          /* Number of color layers associated with this glyph */
+  GlyphID      glyphid;        /* Glyph ID of reference glyph */
+  HBUINT16     firstLayerIdx;  /* Index to the layer record */
+  HBUINT16     numLayers;      /* Number of color layers associated with this glyph */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
+static int compare_bgr (const void *pa, const void *pb)
+{
+  const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
+  const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
+  return b->cmp (*a);
+}
+
 struct COLR
 {
   static const hb_tag_t tableTag = HB_OT_TAG_COLR;
@@ -79,59 +90,50 @@ struct COLR
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!(c->check_struct (this) &&
-        c->check_array ((const void*) &layerRecordsOffsetZ, sizeof (LayerRecord), numLayerRecords) &&
-        c->check_array ((const void*) &baseGlyphRecordsZ, sizeof (BaseGlyphRecord), numBaseGlyphRecords)))
-      return_trace (false);
-
-    const BaseGlyphRecord* base_glyph_records = &baseGlyphRecordsZ (this);
-    for (unsigned int i = 0; i < numBaseGlyphRecords; ++i)
-      if (base_glyph_records[i].firstLayerIndex +
-          base_glyph_records[i].numLayers > numLayerRecords)
-        return_trace (false);
-
-    return_trace (true);
+    return_trace (likely (c->check_struct (this) &&
+                         (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
+                         (this+layersZ).sanitize (c, numLayers)));
   }
 
-  inline bool get_base_glyph_record (
-    hb_codepoint_t glyph_id, unsigned int &first_layer, unsigned int &num_layers) const
+  inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
+                                    unsigned int *first_layer /* OUT */,
+                                    unsigned int *num_layers /* OUT */) const
   {
-    const BaseGlyphRecord* base_glyph_records = &baseGlyphRecordsZ (this);
-    unsigned int min = 0, max = numBaseGlyphRecords - 1;
-    while (min <= max)
-    {
-      unsigned int mid = (min + max) / 2;
-      hb_codepoint_t gID = base_glyph_records[mid].gID;
-      if (gID > glyph_id)
-        max = mid - 1;
-      else if (gID < glyph_id)
-        min = mid + 1;
-      else
-      {
-        first_layer = base_glyph_records[mid].firstLayerIndex;
-        num_layers = base_glyph_records[mid].numLayers;
-        return true;
-      }
-    }
-    return false;
+    const BaseGlyphRecord* record;
+    record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
+                                         sizeof (BaseGlyphRecord), compare_bgr);
+    if (unlikely (!record))
+      return false;
+
+    *first_layer = record->firstLayerIdx;
+    *num_layers = record->numLayers;
+    return true;
   }
 
-  inline void get_layer_record (int layer,
-    hb_codepoint_t &glyph_id, unsigned int &palette_index) const
+  inline bool get_layer_record (unsigned int record,
+                               hb_codepoint_t *glyph_id /* OUT */,
+                               unsigned int *palette_index /* OUT */) const
   {
-    const LayerRecord* records = &layerRecordsOffsetZ (this);
-    glyph_id = records[layer].gID;
-    palette_index = records[layer].paletteIndex;
+    if (unlikely (record >= numLayers))
+    {
+      *glyph_id = 0;
+      *palette_index = 0xFFFF;
+      return false;
+    }
+    const LayerRecord &layer = (this+layersZ)[record];
+    *glyph_id = layer.glyphid;
+    *palette_index = layer.colorIdx;
+    return true;
   }
 
   protected:
-  HBUINT16     version;                /* Table version number */
-  HBUINT16     numBaseGlyphRecords;    /* Number of Base Glyph Records */
-  LOffsetTo<BaseGlyphRecord>
-               baseGlyphRecordsZ;      /* Offset to Base Glyph records. */
-  LOffsetTo<LayerRecord>
-               layerRecordsOffsetZ;    /* Offset to Layer Records */
-  HBUINT16     numLayerRecords;        /* Number of Layer Records */
+  HBUINT16     version;        /* Table version number */
+  HBUINT16     numBaseGlyphs;  /* Number of Base Glyph Records */
+  LOffsetTo<UnsizedArrayOf<BaseGlyphRecord> >
+               baseGlyphsZ;    /* Offset to Base Glyph records. */
+  LOffsetTo<UnsizedArrayOf<LayerRecord> >
+               layersZ;        /* Offset to Layer Records */
+  HBUINT16     numLayers;      /* Number of Layer Records */
   public:
   DEFINE_SIZE_STATIC (14);
 };