Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2018  Ebrahim Byagowi
      3  *
      4  *  This is part of HarfBuzz, a text shaping library.
      5  *
      6  * Permission is hereby granted, without written agreement and without
      7  * license or royalty fees, to use, copy, modify, and distribute this
      8  * software and its documentation for any purpose, provided that the
      9  * above copyright notice and the following two paragraphs appear in
     10  * all copies of this software.
     11  *
     12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     16  * DAMAGE.
     17  *
     18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     23  */
     24 
     25 #ifndef HB_OT_COLOR_COLR_TABLE_HH
     26 #define HB_OT_COLOR_COLR_TABLE_HH
     27 
     28 #include "hb-open-type.hh"
     29 
     30 /*
     31  * COLR -- Color
     32  * https://docs.microsoft.com/en-us/typography/opentype/spec/colr
     33  */
     34 #define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
     35 
     36 
     37 namespace OT {
     38 
     39 
     40 struct LayerRecord
     41 {
     42   bool sanitize (hb_sanitize_context_t *c) const
     43   {
     44     TRACE_SANITIZE (this);
     45     return_trace (c->check_struct (this));
     46   }
     47 
     48   public:
     49   GlyphID	glyphId;	/* Glyph ID of layer glyph */
     50   Index		colorIdx;	/* Index value to use with a
     51 				 * selected color palette.
     52 				 * An index value of 0xFFFF
     53 				 * is a special case indicating
     54 				 * that the text foreground
     55 				 * color (defined by a
     56 				 * higher-level client) should
     57 				 * be used and shall not be
     58 				 * treated as actual index
     59 				 * into CPAL ColorRecord array. */
     60   public:
     61   DEFINE_SIZE_STATIC (4);
     62 };
     63 
     64 struct BaseGlyphRecord
     65 {
     66   int cmp (hb_codepoint_t g) const
     67   { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
     68 
     69   bool sanitize (hb_sanitize_context_t *c) const
     70   {
     71     TRACE_SANITIZE (this);
     72     return_trace (likely (c->check_struct (this)));
     73   }
     74 
     75   public:
     76   GlyphID	glyphId;	/* Glyph ID of reference glyph */
     77   HBUINT16	firstLayerIdx;	/* Index (from beginning of
     78 				 * the Layer Records) to the
     79 				 * layer record. There will be
     80 				 * numLayers consecutive entries
     81 				 * for this base glyph. */
     82   HBUINT16	numLayers;	/* Number of color layers
     83 				 * associated with this glyph */
     84   public:
     85   DEFINE_SIZE_STATIC (6);
     86 };
     87 
     88 struct COLR
     89 {
     90   enum { tableTag = HB_OT_TAG_COLR };
     91 
     92   bool has_data () const { return numBaseGlyphs; }
     93 
     94   unsigned int get_glyph_layers (hb_codepoint_t       glyph,
     95 				 unsigned int         start_offset,
     96 				 unsigned int        *count, /* IN/OUT.  May be NULL. */
     97 				 hb_ot_color_layer_t *layers /* OUT.     May be NULL. */) const
     98   {
     99     const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph);
    100 
    101     hb_array_t<const LayerRecord> all_layers ((this+layersZ).arrayZ, numLayers);
    102     hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
    103 								       record.numLayers);
    104     if (count)
    105     {
    106       hb_array_t<const LayerRecord> segment_layers = glyph_layers.sub_array (start_offset, *count);
    107       *count = segment_layers.len;
    108       for (unsigned int i = 0; i < segment_layers.len; i++)
    109       {
    110         layers[i].glyph = segment_layers.arrayZ[i].glyphId;
    111         layers[i].color_index = segment_layers.arrayZ[i].colorIdx;
    112       }
    113     }
    114     return glyph_layers.len;
    115   }
    116 
    117   bool sanitize (hb_sanitize_context_t *c) const
    118   {
    119     TRACE_SANITIZE (this);
    120     return_trace (likely (c->check_struct (this) &&
    121 			  (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
    122 			  (this+layersZ).sanitize (c, numLayers)));
    123   }
    124 
    125   protected:
    126   HBUINT16	version;	/* Table version number (starts at 0). */
    127   HBUINT16	numBaseGlyphs;	/* Number of Base Glyph Records. */
    128   LOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord>, false>
    129 		baseGlyphsZ;	/* Offset to Base Glyph records. */
    130   LOffsetTo<UnsizedArrayOf<LayerRecord>, false>
    131 		layersZ;	/* Offset to Layer Records. */
    132   HBUINT16	numLayers;	/* Number of Layer Records. */
    133   public:
    134   DEFINE_SIZE_STATIC (14);
    135 };
    136 
    137 } /* namespace OT */
    138 
    139 
    140 #endif /* HB_OT_COLOR_COLR_TABLE_HH */
    141