hb-ot-color-cpal-table.hh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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. #ifndef HB_OT_COLOR_CPAL_TABLE_HH
  28. #define HB_OT_COLOR_CPAL_TABLE_HH
  29. #include "hb-open-type.hh"
  30. #include "hb-ot-color.h"
  31. #include "hb-ot-name.h"
  32. /*
  33. * CPAL -- Color Palette
  34. * https://docs.microsoft.com/en-us/typography/opentype/spec/cpal
  35. */
  36. #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
  37. namespace OT {
  38. struct CPALV1Tail
  39. {
  40. friend struct CPAL;
  41. private:
  42. hb_ot_color_palette_flags_t get_palette_flags (const void *base,
  43. unsigned int palette_index,
  44. unsigned int palette_count) const
  45. {
  46. if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
  47. return (hb_ot_color_palette_flags_t) (uint32_t)
  48. (base+paletteFlagsZ).as_array (palette_count)[palette_index];
  49. }
  50. hb_ot_name_id_t get_palette_name_id (const void *base,
  51. unsigned int palette_index,
  52. unsigned int palette_count) const
  53. {
  54. if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID;
  55. return (base+paletteLabelsZ).as_array (palette_count)[palette_index];
  56. }
  57. hb_ot_name_id_t get_color_name_id (const void *base,
  58. unsigned int color_index,
  59. unsigned int color_count) const
  60. {
  61. if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID;
  62. return (base+colorLabelsZ).as_array (color_count)[color_index];
  63. }
  64. public:
  65. bool serialize (hb_serialize_context_t *c,
  66. unsigned palette_count,
  67. unsigned color_count,
  68. const void *base,
  69. const hb_map_t *color_index_map) const
  70. {
  71. TRACE_SERIALIZE (this);
  72. auto *out = c->allocate_size<CPALV1Tail> (static_size);
  73. if (unlikely (!out)) return_trace (false);
  74. out->paletteFlagsZ = 0;
  75. if (paletteFlagsZ)
  76. out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
  77. out->paletteLabelsZ = 0;
  78. if (paletteLabelsZ)
  79. out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
  80. const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
  81. if (colorLabelsZ)
  82. {
  83. c->push ();
  84. for (const auto _ : colorLabels)
  85. {
  86. const hb_codepoint_t *v;
  87. if (!color_index_map->has (_, &v)) continue;
  88. NameID new_color_idx;
  89. new_color_idx = *v;
  90. if (!c->copy<NameID> (new_color_idx))
  91. {
  92. c->pop_discard ();
  93. return_trace (false);
  94. }
  95. }
  96. c->add_link (out->colorLabelsZ, c->pop_pack ());
  97. }
  98. return_trace (true);
  99. }
  100. bool sanitize (hb_sanitize_context_t *c,
  101. const void *base,
  102. unsigned int palette_count,
  103. unsigned int color_count) const
  104. {
  105. TRACE_SANITIZE (this);
  106. return_trace (c->check_struct (this) &&
  107. (!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) &&
  108. (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) &&
  109. (!colorLabelsZ || (base+colorLabelsZ).sanitize (c, color_count)));
  110. }
  111. protected:
  112. // TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets
  113. // here. Currently they are needed since UnsizedArrayOf doesn't define null_size
  114. NNOffset32To<UnsizedArrayOf<HBUINT32>>
  115. paletteFlagsZ; /* Offset from the beginning of CPAL table to
  116. * the Palette Type Array. Set to 0 if no array
  117. * is provided. */
  118. NNOffset32To<UnsizedArrayOf<NameID>>
  119. paletteLabelsZ; /* Offset from the beginning of CPAL table to
  120. * the palette labels array. Set to 0 if no
  121. * array is provided. */
  122. NNOffset32To<UnsizedArrayOf<NameID>>
  123. colorLabelsZ; /* Offset from the beginning of CPAL table to
  124. * the color labels array. Set to 0
  125. * if no array is provided. */
  126. public:
  127. DEFINE_SIZE_STATIC (12);
  128. };
  129. typedef HBUINT32 BGRAColor;
  130. struct CPAL
  131. {
  132. static constexpr hb_tag_t tableTag = HB_OT_TAG_CPAL;
  133. bool has_data () const { return numPalettes; }
  134. unsigned int get_size () const
  135. { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
  136. unsigned int get_palette_count () const { return numPalettes; }
  137. unsigned int get_color_count () const { return numColors; }
  138. hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const
  139. { return v1 ().get_palette_flags (this, palette_index, numPalettes); }
  140. hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const
  141. { return v1 ().get_palette_name_id (this, palette_index, numPalettes); }
  142. hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
  143. { return v1 ().get_color_name_id (this, color_index, numColors); }
  144. unsigned int get_palette_colors (unsigned int palette_index,
  145. unsigned int start_offset,
  146. unsigned int *color_count, /* IN/OUT. May be NULL. */
  147. hb_color_t *colors /* OUT. May be NULL. */) const
  148. {
  149. if (unlikely (palette_index >= numPalettes))
  150. {
  151. if (color_count) *color_count = 0;
  152. return 0;
  153. }
  154. unsigned int start_index = colorRecordIndicesZ[palette_index];
  155. hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
  156. hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index,
  157. numColors);
  158. if (color_count)
  159. {
  160. + palette_colors.sub_array (start_offset, color_count)
  161. | hb_sink (hb_array (colors, *color_count))
  162. ;
  163. }
  164. return numColors;
  165. }
  166. private:
  167. const CPALV1Tail& v1 () const
  168. {
  169. if (version == 0) return Null (CPALV1Tail);
  170. return StructAfter<CPALV1Tail> (*this);
  171. }
  172. public:
  173. bool serialize (hb_serialize_context_t *c,
  174. const hb_array_t<const HBUINT16> &color_record_indices,
  175. const hb_array_t<const BGRAColor> &color_records,
  176. const hb_vector_t<unsigned>& first_color_index_for_layer,
  177. const hb_map_t& first_color_to_layer_index,
  178. const hb_set_t &retained_color_indices) const
  179. {
  180. TRACE_SERIALIZE (this);
  181. // TODO(grieger): limit total final size.
  182. for (const auto idx : color_record_indices)
  183. {
  184. hb_codepoint_t layer_index = first_color_to_layer_index[idx];
  185. HBUINT16 new_idx;
  186. new_idx = layer_index * retained_color_indices.get_population ();
  187. if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
  188. }
  189. c->push ();
  190. for (unsigned first_color_index : first_color_index_for_layer)
  191. {
  192. for (hb_codepoint_t color_index : retained_color_indices)
  193. {
  194. if (!c->copy<BGRAColor> (color_records[first_color_index + color_index]))
  195. {
  196. c->pop_discard ();
  197. return_trace (false);
  198. }
  199. }
  200. }
  201. c->add_link (colorRecordsZ, c->pop_pack ());
  202. return_trace (true);
  203. }
  204. bool subset (hb_subset_context_t *c) const
  205. {
  206. TRACE_SUBSET (this);
  207. if (!numPalettes) return_trace (false);
  208. const hb_map_t *color_index_map = c->plan->colr_palettes;
  209. if (color_index_map->is_empty ()) return_trace (false);
  210. hb_set_t retained_color_indices;
  211. for (const auto _ : color_index_map->keys ())
  212. {
  213. if (_ == 0xFFFF) continue;
  214. retained_color_indices.add (_);
  215. }
  216. if (retained_color_indices.is_empty ()) return_trace (false);
  217. auto *out = c->serializer->start_embed (*this);
  218. if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
  219. out->version = version;
  220. out->numColors = retained_color_indices.get_population ();
  221. out->numPalettes = numPalettes;
  222. hb_vector_t<unsigned> first_color_index_for_layer;
  223. hb_map_t first_color_to_layer_index;
  224. const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
  225. for (const auto first_color_record_idx : colorRecordIndices)
  226. {
  227. if (first_color_to_layer_index.has (first_color_record_idx)) continue;
  228. first_color_index_for_layer.push (first_color_record_idx);
  229. first_color_to_layer_index.set (first_color_record_idx,
  230. first_color_index_for_layer.length - 1);
  231. }
  232. out->numColorRecords = first_color_index_for_layer.length
  233. * retained_color_indices.get_population ();
  234. const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
  235. if (!out->serialize (c->serializer,
  236. colorRecordIndices,
  237. color_records,
  238. first_color_index_for_layer,
  239. first_color_to_layer_index,
  240. retained_color_indices))
  241. return_trace (false);
  242. if (version == 1)
  243. return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map));
  244. return_trace (true);
  245. }
  246. bool sanitize (hb_sanitize_context_t *c) const
  247. {
  248. TRACE_SANITIZE (this);
  249. return_trace (c->check_struct (this) &&
  250. (this+colorRecordsZ).sanitize (c, numColorRecords) &&
  251. colorRecordIndicesZ.sanitize (c, numPalettes) &&
  252. (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
  253. }
  254. protected:
  255. HBUINT16 version; /* Table version number */
  256. /* Version 0 */
  257. HBUINT16 numColors; /* Number of colors in each palette. */
  258. HBUINT16 numPalettes; /* Number of palettes in the table. */
  259. HBUINT16 numColorRecords; /* Total number of color records, combined for
  260. * all palettes. */
  261. NNOffset32To<UnsizedArrayOf<BGRAColor>>
  262. colorRecordsZ; /* Offset from the beginning of CPAL table to
  263. * the first ColorRecord. */
  264. UnsizedArrayOf<HBUINT16>
  265. colorRecordIndicesZ; /* Index of each palette’s first color record in
  266. * the combined color record array. */
  267. /*CPALV1Tail v1;*/
  268. public:
  269. DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ);
  270. };
  271. } /* namespace OT */
  272. #endif /* HB_OT_COLOR_CPAL_TABLE_HH */