1 /* 2 * Copyright © 2016 Google, Inc. 3 * Copyright © 2018 Ebrahim Byagowi 4 * 5 * This is part of HarfBuzz, a text shaping library. 6 * 7 * Permission is hereby granted, without written agreement and without 8 * license or royalty fees, to use, copy, modify, and distribute this 9 * software and its documentation for any purpose, provided that the 10 * above copyright notice and the following two paragraphs appear in 11 * all copies of this software. 12 * 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * DAMAGE. 18 * 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 * 25 * Google Author(s): Sascha Brawer 26 */ 27 28 #ifndef HB_OT_COLOR_CPAL_TABLE_HH 29 #define HB_OT_COLOR_CPAL_TABLE_HH 30 31 #include "hb-open-type.hh" 32 #include "hb-ot-color.h" 33 #include "hb-ot-name.h" 34 35 36 /* 37 * CPAL -- Color Palette 38 * https://docs.microsoft.com/en-us/typography/opentype/spec/cpal 39 */ 40 #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L') 41 42 43 namespace OT { 44 45 46 struct CPALV1Tail 47 { 48 friend struct CPAL; 49 50 private: get_palette_flagsOT::CPALV1Tail51 hb_ot_color_palette_flags_t get_palette_flags (const void *base, 52 unsigned int palette_index, 53 unsigned int palette_count) const 54 { 55 if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; 56 return (hb_ot_color_palette_flags_t) (uint32_t) 57 (base+paletteFlagsZ).as_array (palette_count)[palette_index]; 58 } 59 get_palette_name_idOT::CPALV1Tail60 hb_ot_name_id_t get_palette_name_id (const void *base, 61 unsigned int palette_index, 62 unsigned int palette_count) const 63 { 64 if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID; 65 return (base+paletteLabelsZ).as_array (palette_count)[palette_index]; 66 } 67 get_color_name_idOT::CPALV1Tail68 hb_ot_name_id_t get_color_name_id (const void *base, 69 unsigned int color_index, 70 unsigned int color_count) const 71 { 72 if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID; 73 return (base+colorLabelsZ).as_array (color_count)[color_index]; 74 } 75 76 public: sanitizeOT::CPALV1Tail77 bool sanitize (hb_sanitize_context_t *c, 78 const void *base, 79 unsigned int palette_count, 80 unsigned int color_count) const 81 { 82 TRACE_SANITIZE (this); 83 return_trace (c->check_struct (this) && 84 (!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) && 85 (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) && 86 (!colorLabelsZ || (base+colorLabelsZ).sanitize (c, color_count))); 87 } 88 89 protected: 90 LOffsetTo<UnsizedArrayOf<HBUINT32>, false> 91 paletteFlagsZ; /* Offset from the beginning of CPAL table to 92 * the Palette Type Array. Set to 0 if no array 93 * is provided. */ 94 LOffsetTo<UnsizedArrayOf<NameID>, false> 95 paletteLabelsZ; /* Offset from the beginning of CPAL table to 96 * the palette labels array. Set to 0 if no 97 * array is provided. */ 98 LOffsetTo<UnsizedArrayOf<NameID>, false> 99 colorLabelsZ; /* Offset from the beginning of CPAL table to 100 * the color labels array. Set to 0 101 * if no array is provided. */ 102 public: 103 DEFINE_SIZE_STATIC (12); 104 }; 105 106 typedef HBUINT32 BGRAColor; 107 108 struct CPAL 109 { 110 enum { tableTag = HB_OT_TAG_CPAL }; 111 has_dataOT::CPAL112 bool has_data () const { return numPalettes; } 113 get_sizeOT::CPAL114 unsigned int get_size () const 115 { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); } 116 get_palette_countOT::CPAL117 unsigned int get_palette_count () const { return numPalettes; } get_color_countOT::CPAL118 unsigned int get_color_count () const { return numColors; } 119 get_palette_flagsOT::CPAL120 hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const 121 { return v1 ().get_palette_flags (this, palette_index, numPalettes); } 122 get_palette_name_idOT::CPAL123 hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const 124 { return v1 ().get_palette_name_id (this, palette_index, numPalettes); } 125 get_color_name_idOT::CPAL126 hb_ot_name_id_t get_color_name_id (unsigned int color_index) const 127 { return v1 ().get_color_name_id (this, color_index, numColors); } 128 get_palette_colorsOT::CPAL129 unsigned int get_palette_colors (unsigned int palette_index, 130 unsigned int start_offset, 131 unsigned int *color_count, /* IN/OUT. May be NULL. */ 132 hb_color_t *colors /* OUT. May be NULL. */) const 133 { 134 if (unlikely (palette_index >= numPalettes)) 135 { 136 if (color_count) *color_count = 0; 137 return 0; 138 } 139 unsigned int start_index = colorRecordIndicesZ[palette_index]; 140 hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords); 141 hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index, 142 numColors); 143 if (color_count) 144 { 145 hb_array_t<const BGRAColor> segment_colors = palette_colors.sub_array (start_offset, *color_count); 146 /* Always return numColors colors per palette even if it has out-of-bounds start index. */ 147 unsigned int count = MIN<unsigned int> (MAX<int> (numColors - start_offset, 0), *color_count); 148 *color_count = count; 149 for (unsigned int i = 0; i < count; i++) 150 colors[i] = segment_colors[i]; /* Bound-checked read. */ 151 } 152 return numColors; 153 } 154 155 private: v1OT::CPAL156 const CPALV1Tail& v1 () const 157 { 158 if (version == 0) return Null(CPALV1Tail); 159 return StructAfter<CPALV1Tail> (*this); 160 } 161 162 public: sanitizeOT::CPAL163 bool sanitize (hb_sanitize_context_t *c) const 164 { 165 TRACE_SANITIZE (this); 166 return_trace (c->check_struct (this) && 167 (this+colorRecordsZ).sanitize (c, numColorRecords) && 168 colorRecordIndicesZ.sanitize (c, numPalettes) && 169 (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors))); 170 } 171 172 protected: 173 HBUINT16 version; /* Table version number */ 174 /* Version 0 */ 175 HBUINT16 numColors; /* Number of colors in each palette. */ 176 HBUINT16 numPalettes; /* Number of palettes in the table. */ 177 HBUINT16 numColorRecords; /* Total number of color records, combined for 178 * all palettes. */ 179 LOffsetTo<UnsizedArrayOf<BGRAColor>, false> 180 colorRecordsZ; /* Offset from the beginning of CPAL table to 181 * the first ColorRecord. */ 182 UnsizedArrayOf<HBUINT16> 183 colorRecordIndicesZ; /* Index of each palette’s first color record in 184 * the combined color record array. */ 185 /*CPALV1Tail v1;*/ 186 public: 187 DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ); 188 }; 189 190 } /* namespace OT */ 191 192 193 #endif /* HB_OT_COLOR_CPAL_TABLE_HH */ 194