QtBase  v6.3.1
hb-ot-hmtx-table.hh
Go to the documentation of this file.
1 /*
2  * Copyright © 2011,2012 Google, Inc.
3  *
4  * This is part of HarfBuzz, a text shaping library.
5  *
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.
11  *
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
16  * DAMAGE.
17  *
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.
23  *
24  * Google Author(s): Behdad Esfahbod, Roderick Sheeter
25  */
26 
27 #ifndef HB_OT_HMTX_TABLE_HH
28 #define HB_OT_HMTX_TABLE_HH
29 
30 #include "hb-open-type.hh"
31 #include "hb-ot-maxp-table.hh"
32 #include "hb-ot-hhea-table.hh"
33 #include "hb-ot-var-hvar-table.hh"
34 #include "hb-ot-metrics.hh"
35 
36 /*
37  * hmtx -- Horizontal Metrics
38  * https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
39  * vmtx -- Vertical Metrics
40  * https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx
41  */
42 #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
43 #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
44 
45 
46 HB_INTERNAL int
47 _glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
48 
49 HB_INTERNAL unsigned
50 _glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
51 
52 
53 namespace OT {
54 
55 
56 struct LongMetric
57 {
58  UFWORD advance; /* Advance width/height. */
59  FWORD sb; /* Leading (left/top) side bearing. */
60  public:
62 };
63 
64 
65 template <typename T, typename H>
66 struct hmtxvmtx
67 {
69  {
70  TRACE_SANITIZE (this);
71  /* We don't check for anything specific here. The users of the
72  * struct do all the hard work... */
73  return_trace (true);
74  }
75 
76 
78  unsigned int num_hmetrics) const
79  {
80  hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
81  hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
82  hb_blob_destroy (src_blob);
83 
84  if (unlikely (!dest_blob)) {
85  return false;
86  }
87 
88  unsigned int length;
89  H *table = (H *) hb_blob_get_data (dest_blob, &length);
90  table->numberOfLongMetrics = num_hmetrics;
91 
92  bool result = plan->add_table (H::tableTag, dest_blob);
93  hb_blob_destroy (dest_blob);
94 
95  return result;
96  }
97 
98  template<typename Iterator,
99  hb_requires (hb_is_iterator (Iterator))>
101  Iterator it,
102  unsigned num_long_metrics)
103  {
104  unsigned idx = 0;
105  for (auto _ : it)
106  {
107  if (idx < num_long_metrics)
108  {
109  LongMetric lm;
110  lm.advance = _.first;
111  lm.sb = _.second;
112  if (unlikely (!c->embed<LongMetric> (&lm))) return;
113  }
114  else
115  {
116  FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
117  if (unlikely (!sb)) return;
118  *sb = _.second;
119  }
120  idx++;
121  }
122  }
123 
125  {
126  TRACE_SUBSET (this);
127 
128  T *table_prime = c->serializer->start_embed <T> ();
129  if (unlikely (!table_prime)) return_trace (false);
130 
131  accelerator_t _mtx (c->plan->source);
132  unsigned num_long_metrics;
133  {
134  /* Determine num_long_metrics to encode. */
135  auto& plan = c->plan;
136  num_long_metrics = plan->num_output_glyphs ();
137  hb_codepoint_t old_gid = 0;
138  unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0;
139  while (num_long_metrics > 1 &&
140  last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0))
141  {
142  num_long_metrics--;
143  }
144  }
145 
146  auto it =
147  + hb_range (c->plan->num_output_glyphs ())
148  | hb_map ([c, &_mtx] (unsigned _)
149  {
150  hb_codepoint_t old_gid;
151  if (!c->plan->old_gid_for_new_gid (_, &old_gid))
152  return hb_pair (0u, 0);
153  return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
154  })
155  ;
156 
157  table_prime->serialize (c->serializer, it, num_long_metrics);
158 
159  if (unlikely (c->serializer->in_error ()))
160  return_trace (false);
161 
162  // Amend header num hmetrics
163  if (unlikely (!subset_update_header (c->plan, num_long_metrics)))
164  return_trace (false);
165 
166  return_trace (true);
167  }
168 
170  {
171  friend struct hmtxvmtx;
172 
174  {
175  table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
176  var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
177 
178  default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face);
179 
180  /* Populate count variables and sort them out as we go */
181 
182  unsigned int len = table.get_length ();
183  if (len & 1)
184  len--;
185 
186  num_long_metrics = T::is_horizontal ?
187  face->table.hhea->numberOfLongMetrics :
188 #ifndef HB_NO_VERTICAL
189  face->table.vhea->numberOfLongMetrics
190 #else
191  0
192 #endif
193  ;
194  if (unlikely (num_long_metrics * 4 > len))
195  num_long_metrics = len / 4;
196  len -= num_long_metrics * 4;
197 
198  num_bearings = face->table.maxp->get_num_glyphs ();
199 
202  if (unlikely ((num_bearings - num_long_metrics) * 2 > len))
204  len -= (num_bearings - num_long_metrics) * 2;
205 
206  /* We MUST set num_bearings to zero if num_long_metrics is zero.
207  * Our get_advance() depends on that. */
208  if (unlikely (!num_long_metrics))
210 
211  num_advances = num_bearings + len / 2;
212  num_glyphs = face->get_num_glyphs ();
213  if (num_glyphs < num_advances)
215  }
217  {
218  table.destroy ();
219  var_table.destroy ();
220  }
221 
222  bool has_data () const { return (bool) num_bearings; }
223 
225  {
226  if (glyph < num_long_metrics)
227  return table->longMetricZ[glyph].sb;
228 
229  if (unlikely (glyph >= num_bearings))
230  return 0;
231 
232  const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
233  return bearings[glyph - num_long_metrics];
234  }
235 
237  {
238  int side_bearing = get_side_bearing (glyph);
239 
240 #ifndef HB_NO_VAR
241  if (unlikely (glyph >= num_bearings) || !font->num_coords)
242  return side_bearing;
243 
244  if (var_table.get_length ())
245  return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
246 
247  return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
248 #else
249  return side_bearing;
250 #endif
251  }
252 
253  unsigned int get_advance (hb_codepoint_t glyph) const
254  {
255  /* OpenType case. */
256  if (glyph < num_bearings)
257  return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance;
258 
259  /* If num_advances is zero, it means we don't have the metrics table
260  * for this direction: return default advance. Otherwise, there's a
261  * well-defined answer. */
262  if (unlikely (!num_advances))
263  return default_advance;
264 
265 #ifdef HB_NO_BORING_EXPANSION
266  return 0;
267 #endif
268 
269  if (unlikely (glyph >= num_glyphs))
270  return 0;
271 
272  /* num_bearings <= glyph < num_glyphs;
273  * num_bearings <= num_advances */
274 
275  /* TODO Optimize */
276 
277  if (num_bearings == num_advances)
278  return get_advance (num_bearings - 1);
279 
280  const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
281  const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics];
282 
283  return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
284  }
285 
286  unsigned int get_advance (hb_codepoint_t glyph,
287  hb_font_t *font) const
288  {
289  unsigned int advance = get_advance (glyph);
290 
291 #ifndef HB_NO_VAR
292  if (unlikely (glyph >= num_bearings) || !font->num_coords)
293  return advance;
294 
295  if (var_table.get_length ())
296  return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?!
297 
298  return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
299 #else
300  return advance;
301 #endif
302  }
303 
304  protected:
305  // 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs
307  unsigned num_bearings;
308  unsigned num_advances;
309  unsigned num_glyphs;
310 
311  unsigned int default_advance;
312 
313  private:
315  hb_blob_ptr_t<HVARVVAR> var_table;
316  };
317 
318  protected:
320  longMetricZ; /* Paired advance width and leading
321  * bearing values for each glyph. The
322  * value numOfHMetrics comes from
323  * the 'hhea' table. If the font is
324  * monospaced, only one entry need
325  * be in the array, but that entry is
326  * required. The last entry applies to
327  * all subsequent glyphs. */
328 /*UnsizedArrayOf<FWORD> leadingBearingX;*/
329  /* Here the advance is assumed
330  * to be the same as the advance
331  * for the last entry above. The
332  * number of entries in this array is
333  * derived from numGlyphs (from 'maxp'
334  * table) minus numberOfLongMetrics.
335  * This generally is used with a run
336  * of monospaced glyphs (e.g., Kanji
337  * fonts or Courier fonts). Only one
338  * run is allowed and it must be at
339  * the end. This allows a monospaced
340  * font to vary the side bearing
341  * values for each glyph. */
342 /*UnsizedArrayOf<UFWORD>advancesX;*/
343  /* TODO Document. */
344  public:
346 };
347 
348 struct hmtx : hmtxvmtx<hmtx, hhea> {
349  static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
351  static constexpr bool is_horizontal = true;
352 };
353 struct vmtx : hmtxvmtx<vmtx, vhea> {
354  static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
356  static constexpr bool is_horizontal = false;
357 };
358 
359 struct hmtx_accelerator_t : hmtx::accelerator_t {
360  hmtx_accelerator_t (hb_face_t *face) : hmtx::accelerator_t (face) {}
361 };
362 struct vmtx_accelerator_t : vmtx::accelerator_t {
363  vmtx_accelerator_t (hb_face_t *face) : vmtx::accelerator_t (face) {}
364 };
365 
366 } /* namespace OT */
367 
368 
369 #endif /* HB_OT_HMTX_TABLE_HH */
small capitals from c petite p scientific f u
Definition: afcover.h:88
FT_UInt idx
Definition: cffcmap.c:135
#define roundf(x)
Definition: hb-algs.hh:165
hb_blob_t * hb_blob_copy_writable_or_fail(hb_blob_t *blob)
Definition: hb-blob.cc:200
const char * hb_blob_get_data(hb_blob_t *blob, unsigned int *length)
Definition: hb-blob.cc:377
void hb_blob_destroy(hb_blob_t *blob)
Definition: hb-blob.cc:262
#define TRACE_SANITIZE(this)
Definition: hb-debug.hh:414
#define return_trace(RET)
Definition: hb-debug.hh:349
#define TRACE_SUBSET(this)
Definition: hb-debug.hh:438
void const void *obj HB_UNUSED
Definition: hb-debug.hh:180
unsigned int hb_face_get_upem(const hb_face_t *face)
Definition: hb-face.cc:496
#define hb_is_iterator(Iter)
Definition: hb-iter.hh:265
auto it hb_map(hb_second)) template< typename Type > inline hb_array_t< Type > operator()(hb_array_t< Type > array
static auto hb_requires(hb_is_iterable(Iterable))> static inline auto end(Iterable &&iterable) HB_AUTO_RETURN(hb_iter(iterable).end()) namespace OT
Definition: hb-iter.hh:331
#define HB_OT_TAG_hmtx
HB_INTERNAL int _glyf_get_side_bearing_var(hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
Definition: hb-ot-font.cc:375
#define HB_OT_TAG_vmtx
HB_INTERNAL unsigned _glyf_get_advance_var(hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
Definition: hb-ot-font.cc:381
#define _(S, M)
#define HB_OT_TAG_VVAR
#define HB_OT_TAG_HVAR
#define unlikely(expr)
Definition: hb.hh:251
#define HB_INTERNAL
Definition: hb.hh:274
#define H(x, y, z)
Definition: md5.c:53
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLenum face
const GLubyte * c
Definition: qopenglext.h:12701
GLenum GLsizei len
Definition: qopenglext.h:3292
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLenum GLenum GLsizei void * table
Definition: qopenglext.h:2745
uint32_t hb_codepoint_t
Definition: hb-common.h:106
uint32_t hb_tag_t
Definition: hb-common.h:157
QStringList::Iterator it
hmtx_accelerator_t(hb_face_t *face)
static constexpr hb_tag_t variationsTag
static constexpr bool is_horizontal
static constexpr hb_tag_t tableTag
int get_side_bearing(hb_codepoint_t glyph) const
unsigned int get_advance(hb_codepoint_t glyph) const
unsigned int get_advance(hb_codepoint_t glyph, hb_font_t *font) const
int get_side_bearing(hb_font_t *font, hb_codepoint_t glyph) const
bool subset_update_header(hb_subset_plan_t *plan, unsigned int num_hmetrics) const
bool subset(hb_subset_context_t *c) const
DEFINE_SIZE_ARRAY(0, longMetricZ)
bool sanitize(hb_sanitize_context_t *c HB_UNUSED) const
void serialize(hb_serialize_context_t *c, Iterator it, unsigned num_long_metrics)
UnsizedArrayOf< LongMetric > longMetricZ
vmtx_accelerator_t(hb_face_t *face)
static constexpr bool is_horizontal
static constexpr hb_tag_t tableTag
static constexpr hb_tag_t variationsTag
Definition: main.cpp:38
bool add_table(hb_tag_t tag, hb_blob_t *contents)
hb_face_t * source