| /* | 
 |  * Copyright © 2016  Google, Inc. | 
 |  * Copyright © 2018  Ebrahim Byagowi | 
 |  * | 
 |  *  This is part of HarfBuzz, a text shaping library. | 
 |  * | 
 |  * Permission is hereby granted, without written agreement and without | 
 |  * license or royalty fees, to use, copy, modify, and distribute this | 
 |  * software and its documentation for any purpose, provided that the | 
 |  * above copyright notice and the following two paragraphs appear in | 
 |  * all copies of this software. | 
 |  * | 
 |  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 
 |  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 
 |  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | 
 |  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 
 |  * DAMAGE. | 
 |  * | 
 |  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 
 |  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 
 |  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS | 
 |  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | 
 |  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 
 |  * | 
 |  * Google Author(s): Sascha Brawer | 
 |  */ | 
 |  | 
 | #ifndef HB_OT_COLOR_CPAL_TABLE_HH | 
 | #define HB_OT_COLOR_CPAL_TABLE_HH | 
 |  | 
 | #include "hb-open-type.hh" | 
 | #include "hb-ot-color.h" | 
 | #include "hb-ot-name.h" | 
 |  | 
 |  | 
 | /* | 
 |  * CPAL -- Color Palette | 
 |  * https://docs.microsoft.com/en-us/typography/opentype/spec/cpal | 
 |  */ | 
 | #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L') | 
 |  | 
 |  | 
 | namespace OT { | 
 |  | 
 |  | 
 | struct CPALV1Tail | 
 | { | 
 |   friend struct CPAL; | 
 |  | 
 |   private: | 
 |   inline hb_ot_color_palette_flags_t | 
 |   get_palette_flags (const void *base, | 
 | 		     unsigned int palette_index, | 
 | 		     unsigned int palette_count) const | 
 |   { | 
 |     if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; | 
 |     return (hb_ot_color_palette_flags_t) (uint32_t) | 
 | 	   (base+paletteFlagsZ).as_array (palette_count)[palette_index]; | 
 |   } | 
 |  | 
 |   inline hb_ot_name_id_t | 
 |   get_palette_name_id (const void *base, | 
 | 		       unsigned int palette_index, | 
 | 		       unsigned int palette_count) const | 
 |   { | 
 |     if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID; | 
 |     return (base+paletteLabelsZ).as_array (palette_count)[palette_index]; | 
 |   } | 
 |  | 
 |   inline hb_ot_name_id_t | 
 |   get_color_name_id (const void *base, | 
 | 		     unsigned int color_index, | 
 | 		     unsigned int color_count) const | 
 |   { | 
 |     if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID; | 
 |     return (base+colorLabelsZ).as_array (color_count)[color_index]; | 
 |   } | 
 |  | 
 |   public: | 
 |   inline bool sanitize (hb_sanitize_context_t *c, | 
 | 			const void *base, | 
 | 			unsigned int palette_count, | 
 | 			unsigned int color_count) const | 
 |   { | 
 |     TRACE_SANITIZE (this); | 
 |     return_trace (c->check_struct (this) && | 
 | 		  (!paletteFlagsZ  || (base+paletteFlagsZ).sanitize (c, palette_count)) && | 
 | 		  (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) && | 
 | 		  (!colorLabelsZ   || (base+colorLabelsZ).sanitize (c, color_count))); | 
 |   } | 
 |  | 
 |   protected: | 
 |   LOffsetTo<UnsizedArrayOf<HBUINT32>, false> | 
 | 		paletteFlagsZ;		/* Offset from the beginning of CPAL table to | 
 | 					 * the Palette Type Array. Set to 0 if no array | 
 | 					 * is provided. */ | 
 |   LOffsetTo<UnsizedArrayOf<NameID>, false> | 
 | 		paletteLabelsZ;		/* Offset from the beginning of CPAL table to | 
 | 					 * the palette labels array. Set to 0 if no | 
 | 					 * array is provided. */ | 
 |   LOffsetTo<UnsizedArrayOf<NameID>, false> | 
 | 		colorLabelsZ;		/* Offset from the beginning of CPAL table to | 
 | 					 * the color labels array. Set to 0 | 
 | 					 * if no array is provided. */ | 
 |   public: | 
 |   DEFINE_SIZE_STATIC (12); | 
 | }; | 
 |  | 
 | typedef HBUINT32 BGRAColor; | 
 |  | 
 | struct CPAL | 
 | { | 
 |   enum { tableTag = HB_OT_TAG_CPAL }; | 
 |  | 
 |   inline bool has_data (void) const { return numPalettes; } | 
 |  | 
 |   inline unsigned int get_size (void) const | 
 |   { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); } | 
 |  | 
 |   inline unsigned int get_palette_count () const { return numPalettes; } | 
 |   inline unsigned int get_color_count () const { return numColors; } | 
 |  | 
 |   inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const | 
 |   { return v1 ().get_palette_flags (this, palette_index, numPalettes); } | 
 |  | 
 |   inline hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const | 
 |   { return v1 ().get_palette_name_id (this, palette_index, numPalettes); } | 
 |  | 
 |   inline hb_ot_name_id_t get_color_name_id (unsigned int color_index) const | 
 |   { return v1 ().get_color_name_id (this, color_index, numColors); } | 
 |  | 
 |   inline unsigned int get_palette_colors (unsigned int  palette_index, | 
 | 					  unsigned int  start_offset, | 
 | 					  unsigned int *color_count, /* IN/OUT.  May be NULL. */ | 
 | 					  hb_color_t   *colors       /* OUT.     May be NULL. */) const | 
 |   { | 
 |     if (unlikely (palette_index >= numPalettes)) | 
 |     { | 
 |       if (color_count) *color_count = 0; | 
 |       return 0; | 
 |     } | 
 |     unsigned int start_index = colorRecordIndicesZ[palette_index]; | 
 |     hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords); | 
 |     hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index, | 
 | 								       numColors); | 
 |     if (color_count) | 
 |     { | 
 |       hb_array_t<const BGRAColor> segment_colors = palette_colors.sub_array (start_offset, *color_count); | 
 |       /* Always return numColors colors per palette even if it has out-of-bounds start index. */ | 
 |       unsigned int count = MIN<unsigned int> (MAX<int> (numColors - start_offset, 0), *color_count); | 
 |       *color_count = count; | 
 |       for (unsigned int i = 0; i < count; i++) | 
 |         colors[i] = segment_colors[i]; /* Bound-checked read. */ | 
 |     } | 
 |     return numColors; | 
 |   } | 
 |  | 
 |   private: | 
 |   inline const CPALV1Tail& v1 (void) const | 
 |   { | 
 |     if (version == 0) return Null(CPALV1Tail); | 
 |     return StructAfter<CPALV1Tail> (*this); | 
 |   } | 
 |  | 
 |   public: | 
 |   inline bool sanitize (hb_sanitize_context_t *c) const | 
 |   { | 
 |     TRACE_SANITIZE (this); | 
 |     return_trace (c->check_struct (this) && | 
 | 		  (this+colorRecordsZ).sanitize (c, numColorRecords) && | 
 | 		  colorRecordIndicesZ.sanitize (c, numPalettes) && | 
 | 		  (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors))); | 
 |   } | 
 |  | 
 |   protected: | 
 |   HBUINT16	version;		/* Table version number */ | 
 |   /* Version 0 */ | 
 |   HBUINT16	numColors;		/* Number of colors in each palette. */ | 
 |   HBUINT16	numPalettes;		/* Number of palettes in the table. */ | 
 |   HBUINT16	numColorRecords;	/* Total number of color records, combined for | 
 | 					 * all palettes. */ | 
 |   LOffsetTo<UnsizedArrayOf<BGRAColor>, false> | 
 | 		colorRecordsZ;		/* Offset from the beginning of CPAL table to | 
 | 					 * the first ColorRecord. */ | 
 |   UnsizedArrayOf<HBUINT16> | 
 | 		colorRecordIndicesZ;	/* Index of each palette’s first color record in | 
 | 					 * the combined color record array. */ | 
 | /*CPALV1Tail	v1;*/ | 
 |   public: | 
 |   DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ); | 
 | }; | 
 |  | 
 | } /* namespace OT */ | 
 |  | 
 |  | 
 | #endif /* HB_OT_COLOR_CPAL_TABLE_HH */ |