ce6702d2ad353871bb7f647b35b5d03d723fd039
[platform/upstream/harfbuzz.git] / src / hb-ot-color-colr-table.hh
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-private.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   friend struct COLR;
43
44   inline bool sanitize (hb_sanitize_context_t *c) const
45   {
46     TRACE_SANITIZE (this);
47     return_trace (c->check_struct (this));
48   }
49
50   protected:
51   GlyphID       glyphid;        /* Glyph ID of layer glyph */
52   HBUINT16      colorIdx;       /* Index value to use with a selected color palette */
53   public:
54   DEFINE_SIZE_STATIC (4);
55 };
56
57 struct BaseGlyphRecord
58 {
59   friend struct COLR;
60
61   inline bool sanitize (hb_sanitize_context_t *c) const
62   {
63     TRACE_SANITIZE (this);
64     return_trace (likely (c->check_struct (this)));
65   }
66
67   inline int cmp (hb_codepoint_t g) const {
68     return g < glyphid ? -1 : g > glyphid ? 1 : 0;
69   }
70
71   protected:
72   GlyphID       glyphid;        /* Glyph ID of reference glyph */
73   HBUINT16      firstLayerIdx;  /* Index to the layer record */
74   HBUINT16      numLayers;      /* Number of color layers associated with this glyph */
75   public:
76   DEFINE_SIZE_STATIC (6);
77 };
78
79 static int compare_bgr (const void *pa, const void *pb)
80 {
81   const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
82   const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
83   return b->cmp (*a);
84 }
85
86 struct COLR
87 {
88   static const hb_tag_t tableTag = HB_OT_TAG_COLR;
89
90   inline bool sanitize (hb_sanitize_context_t *c) const
91   {
92     TRACE_SANITIZE (this);
93     return_trace (likely (c->check_struct (this) &&
94                           (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
95                           (this+layersZ).sanitize (c, numLayers)));
96   }
97
98   inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
99                                      unsigned int *first_layer /* OUT */,
100                                      unsigned int *num_layers /* OUT */) const
101   {
102     const BaseGlyphRecord* record;
103     record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
104                                           sizeof (BaseGlyphRecord), compare_bgr);
105     if (unlikely (!record))
106       return false;
107
108     *first_layer = record->firstLayerIdx;
109     *num_layers = record->numLayers;
110     return true;
111   }
112
113   inline bool get_layer_record (unsigned int record,
114                                 hb_codepoint_t *glyph_id /* OUT */,
115                                 unsigned int *palette_index /* OUT */) const
116   {
117     if (unlikely (record >= numLayers))
118     {
119       *glyph_id = 0;
120       *palette_index = 0xFFFF;
121       return false;
122     }
123     const LayerRecord &layer = (this+layersZ)[record];
124     *glyph_id = layer.glyphid;
125     *palette_index = layer.colorIdx;
126     return true;
127   }
128
129   protected:
130   HBUINT16      version;        /* Table version number */
131   HBUINT16      numBaseGlyphs;  /* Number of Base Glyph Records */
132   LOffsetTo<UnsizedArrayOf<BaseGlyphRecord> >
133                 baseGlyphsZ;    /* Offset to Base Glyph records. */
134   LOffsetTo<UnsizedArrayOf<LayerRecord> >
135                 layersZ;        /* Offset to Layer Records */
136   HBUINT16      numLayers;      /* Number of Layer Records */
137   public:
138   DEFINE_SIZE_STATIC (14);
139 };
140
141 } /* namespace OT */
142
143
144 #endif /* HB_OT_COLOR_COLR_TABLE_HH */