2 * Copyright © 2018 Google, Inc.
4 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
24 * Google Author(s): Garret Rieger
27 #ifndef HB_OT_HDMX_TABLE_HH
28 #define HB_OT_HDMX_TABLE_HH
30 #include "hb-open-type.hh"
33 * hdmx -- Horizontal Device Metrics
34 * https://docs.microsoft.com/en-us/typography/opentype/spec/hdmx
36 #define HB_OT_TAG_hdmx HB_TAG('h','d','m','x')
44 static unsigned int get_size (unsigned count
)
45 { return hb_ceil_to_4 (min_size
+ count
* HBUINT8::static_size
); }
47 template<typename Iterator
,
48 hb_requires (hb_is_iterator (Iterator
))>
49 bool serialize (hb_serialize_context_t
*c
,
52 const hb_vector_t
<hb_codepoint_pair_t
> new_to_old_gid_list
,
55 TRACE_SERIALIZE (this);
57 if (unlikely (!c
->extend (this, num_glyphs
))) return_trace (false);
59 this->pixelSize
= pixelSize
;
62 | hb_reduce (hb_max
, 0u);
64 for (auto &_
: new_to_old_gid_list
)
65 widthsZ
[_
.first
] = *it
++;
70 bool sanitize (hb_sanitize_context_t
*c
, unsigned sizeDeviceRecord
) const
72 TRACE_SANITIZE (this);
73 return_trace (likely (c
->check_struct (this) &&
75 c
->check_range (this, sizeDeviceRecord
)));
78 HBUINT8 pixelSize
; /* Pixel size for following widths (as ppem). */
79 HBUINT8 maxWidth
; /* Maximum width. */
80 UnsizedArrayOf
<HBUINT8
> widthsZ
; /* Array of widths (numGlyphs is from the 'maxp' table). */
82 DEFINE_SIZE_UNBOUNDED (2);
88 static constexpr hb_tag_t tableTag
= HB_OT_TAG_hdmx
;
90 unsigned int get_size () const
91 { return min_size
+ numRecords
* sizeDeviceRecord
; }
93 template<typename Iterator
,
94 hb_requires (hb_is_iterator (Iterator
))>
95 bool serialize (hb_serialize_context_t
*c
,
98 const hb_vector_t
<hb_codepoint_pair_t
> &new_to_old_gid_list
,
101 TRACE_SERIALIZE (this);
103 if (unlikely (!c
->extend_min ((*this)))) return_trace (false);
105 this->version
= version
;
106 this->numRecords
= it
.len ();
107 this->sizeDeviceRecord
= DeviceRecord::get_size (num_glyphs
);
109 for (const hb_item_type
<Iterator
>& _
: +it
)
110 c
->start_embed
<DeviceRecord
> ()->serialize (c
, _
.first
, _
.second
, new_to_old_gid_list
, num_glyphs
);
112 return_trace (c
->successful ());
116 bool subset (hb_subset_context_t
*c
) const
120 auto *hdmx_prime
= c
->serializer
->start_embed
<hdmx
> ();
122 unsigned num_input_glyphs
= get_num_glyphs ();
124 + hb_range ((unsigned) numRecords
)
125 | hb_map ([c
, num_input_glyphs
, this] (unsigned _
)
127 const DeviceRecord
*device_record
=
128 &StructAtOffset
<DeviceRecord
> (&firstDeviceRecord
,
129 _
* sizeDeviceRecord
);
131 + hb_iter (c
->plan
->new_to_old_gid_list
)
132 | hb_map ([num_input_glyphs
, device_record
] (hb_codepoint_pair_t _
)
134 return device_record
->widthsZ
.as_array (num_input_glyphs
) [_
.second
];
137 return hb_pair ((unsigned) device_record
->pixelSize
, +row
);
141 hdmx_prime
->serialize (c
->serializer
, version
, it
,
142 c
->plan
->new_to_old_gid_list
,
143 c
->plan
->num_output_glyphs ());
147 unsigned get_num_glyphs () const
149 return sizeDeviceRecord
- DeviceRecord::min_size
;
152 bool sanitize (hb_sanitize_context_t
*c
) const
154 TRACE_SANITIZE (this);
155 return_trace (c
->check_struct (this) &&
157 !hb_unsigned_mul_overflows (numRecords
, sizeDeviceRecord
) &&
158 min_size
+ numRecords
* sizeDeviceRecord
> numRecords
* sizeDeviceRecord
&&
159 sizeDeviceRecord
>= DeviceRecord::min_size
&&
160 c
->check_range (this, get_size ()));
164 HBUINT16 version
; /* Table version number (0) */
165 HBUINT16 numRecords
; /* Number of device records. */
166 HBUINT32 sizeDeviceRecord
;
167 /* Size of a device record, 32-bit aligned. */
168 DeviceRecord firstDeviceRecord
;
169 /* Array of device records. */
177 #endif /* HB_OT_HDMX_TABLE_HH */