77 |
77 |
78 |
78 |
79 |
79 |
80 |
80 |
81 /* |
81 /* |
82 * Color Palette |
82 * CPAL -- Color Palette |
83 * http://www.microsoft.com/typography/otspec/cpal.htm |
83 * https://docs.microsoft.com/en-us/typography/opentype/spec/cpal |
84 */ |
84 */ |
85 |
|
86 #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L') |
85 #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L') |
|
86 |
87 |
87 |
88 namespace OT { |
88 namespace OT { |
89 |
89 |
90 |
90 |
91 struct CPALV1Tail |
91 struct CPALV1Tail |
92 { |
92 { |
93 friend struct CPAL; |
93 friend struct CPAL; |
94 |
94 |
95 inline bool sanitize (hb_sanitize_context_t *c, unsigned int palettes) const |
95 inline bool |
|
96 sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palettes) const |
96 { |
97 { |
97 TRACE_SANITIZE (this); |
98 TRACE_SANITIZE (this); |
98 return_trace ( |
99 return_trace (c->check_struct (this) && |
99 c->check_struct (this) && |
100 (base+paletteFlagsZ).sanitize (c, palettes) && |
100 c->check_array ((const void*) &paletteFlags, sizeof (HBUINT32), palettes) && |
101 (base+paletteLabelZ).sanitize (c, palettes) && |
101 c->check_array ((const void*) &paletteLabel, sizeof (HBUINT16), palettes) && |
102 (base+paletteEntryLabelZ).sanitize (c, palettes)); |
102 c->check_array ((const void*) &paletteEntryLabel, sizeof (HBUINT16), palettes)); |
|
103 } |
103 } |
104 |
104 |
105 private: |
105 private: |
106 inline hb_ot_color_palette_flags_t |
106 inline hb_ot_color_palette_flags_t |
107 get_palette_flags (const void *base, unsigned int palette) const |
107 get_palette_flags (const void *base, unsigned int palette) const |
108 { |
108 { |
109 const HBUINT32* flags = &paletteFlags (base); |
109 // range checked at the CPAL caller |
110 return (hb_ot_color_palette_flags_t) (uint32_t) flags[palette]; |
110 return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette]; |
111 } |
111 } |
112 |
112 |
113 inline unsigned int |
113 inline unsigned int |
114 get_palette_name_id (const void *base, unsigned int palette) const |
114 get_palette_name_id (const void *base, unsigned int palette) const |
115 { |
115 { |
116 const HBUINT16* name_ids = &paletteLabel (base); |
116 // range checked at the CPAL caller |
117 return name_ids[palette]; |
117 return (base+paletteLabelZ)[palette]; |
118 } |
118 } |
119 |
119 |
120 protected: |
120 protected: |
121 LOffsetTo<HBUINT32> paletteFlags; |
121 LOffsetTo<UnsizedArrayOf<HBUINT32> > |
122 LOffsetTo<HBUINT16> paletteLabel; |
122 paletteFlagsZ; /* Offset from the beginning of CPAL table to |
123 LOffsetTo<HBUINT16> paletteEntryLabel; |
123 * the Palette Type Array. Set to 0 if no array |
|
124 * is provided. */ |
|
125 LOffsetTo<UnsizedArrayOf<HBUINT16> > |
|
126 paletteLabelZ; /* Offset from the beginning of CPAL table to |
|
127 * the Palette Labels Array. Set to 0 if no |
|
128 * array is provided. */ |
|
129 LOffsetTo<UnsizedArrayOf<HBUINT16> > |
|
130 paletteEntryLabelZ; /* Offset from the beginning of CPAL table to |
|
131 * the Palette Entry Label Array. Set to 0 |
|
132 * if no array is provided. */ |
124 public: |
133 public: |
125 DEFINE_SIZE_STATIC (12); |
134 DEFINE_SIZE_STATIC (12); |
126 }; |
135 }; |
127 |
136 |
128 typedef HBUINT32 BGRAColor; |
137 typedef HBUINT32 BGRAColor; |
132 static const hb_tag_t tableTag = HB_OT_TAG_CPAL; |
141 static const hb_tag_t tableTag = HB_OT_TAG_CPAL; |
133 |
142 |
134 inline bool sanitize (hb_sanitize_context_t *c) const |
143 inline bool sanitize (hb_sanitize_context_t *c) const |
135 { |
144 { |
136 TRACE_SANITIZE (this); |
145 TRACE_SANITIZE (this); |
137 if (!(c->check_struct (this) && // This checks colorRecordIndicesX sanity also, see #get_size |
146 if (unlikely (!(c->check_struct (this) && // it checks colorRecordIndices also |
138 c->check_array ((const void*) &colorRecordsZ, sizeof (BGRAColor), numColorRecords))) |
147 // see #get_size |
|
148 (this+colorRecordsZ).sanitize (c, numColorRecords)))) |
139 return_trace (false); |
149 return_trace (false); |
140 |
150 |
141 // Check for indices sanity so no need for doing it runtime |
151 // Check for indices sanity so no need for doing it runtime |
142 for (unsigned int i = 0; i < numPalettes; ++i) |
152 for (unsigned int i = 0; i < numPalettes; ++i) |
143 if (colorRecordIndicesX[i] + numPaletteEntries > numColorRecords) |
153 if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords)) |
144 return_trace (false); |
154 return_trace (false); |
145 |
155 |
146 // If version is zero, we are done here; otherwise we need to check tail also |
156 // If version is zero, we are done here; otherwise we need to check tail also |
147 if (version == 0) |
157 if (version == 0) |
148 return_trace (true); |
158 return_trace (true); |
149 |
159 |
150 const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this); |
160 const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this); |
151 return_trace (v1.sanitize (c, numPalettes)); |
161 return_trace (likely (v1.sanitize (c, this, numPalettes))); |
152 } |
162 } |
153 |
163 |
154 inline unsigned int get_size (void) const |
164 inline unsigned int get_size (void) const |
155 { |
165 { |
156 return min_size + numPalettes * sizeof (HBUINT16); |
166 return min_size + numPalettes * sizeof (HBUINT16); |
157 } |
167 } |
158 |
168 |
159 inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const |
169 inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const |
160 { |
170 { |
161 if (version == 0 || palette >= numPalettes) |
171 if (unlikely (version == 0 || palette >= numPalettes)) |
162 return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; |
172 return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; |
163 |
173 |
164 const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this); |
174 const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this); |
165 return cpal1.get_palette_flags (this, palette); |
175 return cpal1.get_palette_flags (this, palette); |
166 } |
176 } |
167 |
177 |
168 inline unsigned int get_palette_name_id (unsigned int palette) const |
178 inline unsigned int get_palette_name_id (unsigned int palette) const |
169 { |
179 { |
170 if (version == 0 || palette >= numPalettes) |
180 if (unlikely (version == 0 || palette >= numPalettes)) |
171 return 0xFFFF; |
181 return 0xFFFF; |
172 |
182 |
173 const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this); |
183 const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this); |
174 return cpal1.get_palette_name_id (this, palette); |
184 return cpal1.get_palette_name_id (this, palette); |
175 } |
185 } |
177 inline unsigned int get_palette_count () const |
187 inline unsigned int get_palette_count () const |
178 { |
188 { |
179 return numPalettes; |
189 return numPalettes; |
180 } |
190 } |
181 |
191 |
182 inline hb_ot_color_t get_color_record_argb (unsigned int color_index, unsigned int palette) const |
192 inline hb_ot_color_t |
183 { |
193 get_color_record_argb (unsigned int color_index, unsigned int palette) const |
184 if (color_index >= numPaletteEntries || palette >= numPalettes) |
194 { |
|
195 if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes)) |
185 return 0; |
196 return 0; |
186 |
197 |
187 const BGRAColor* records = &colorRecordsZ(this); |
|
188 // No need for more range check as it is already done on #sanitize |
198 // No need for more range check as it is already done on #sanitize |
189 return records[colorRecordIndicesX[palette] + color_index]; |
199 const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ; |
|
200 return color_records[colorRecordIndicesZ[palette] + color_index]; |
190 } |
201 } |
191 |
202 |
192 protected: |
203 protected: |
193 HBUINT16 version; |
204 HBUINT16 version; /* Table version number */ |
194 /* Version 0 */ |
205 /* Version 0 */ |
195 HBUINT16 numPaletteEntries; |
206 HBUINT16 numPaletteEntries; /* Number of palette entries in each palette. */ |
196 HBUINT16 numPalettes; |
207 HBUINT16 numPalettes; /* Number of palettes in the table. */ |
197 HBUINT16 numColorRecords; |
208 HBUINT16 numColorRecords; /* Total number of color records, combined for |
198 LOffsetTo<HBUINT32> colorRecordsZ; |
209 * all palettes. */ |
199 HBUINT16 colorRecordIndicesX[VAR]; // VAR=numPalettes |
210 LOffsetTo<UnsizedArrayOf<BGRAColor> > |
200 /*CPALV1Tail v1[VAR];*/ |
211 colorRecordsZ; /* Offset from the beginning of CPAL table to |
|
212 * the first ColorRecord. */ |
|
213 UnsizedArrayOf<HBUINT16> |
|
214 colorRecordIndicesZ; /* Index of each paletteās first color record in |
|
215 * the combined color record array. */ |
|
216 /*CPALV1Tail v1;*/ |
201 public: |
217 public: |
202 DEFINE_SIZE_ARRAY (12, colorRecordIndicesX); |
218 DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ); |
203 }; |
219 }; |
204 |
220 |
205 } /* namespace OT */ |
221 } /* namespace OT */ |
206 |
222 |
207 |
223 |