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
25 */
26
27#ifndef HB_OT_HMTX_TABLE_HH
28#define HB_OT_HMTX_TABLE_HH
29
30#include "hb-open-type-private.hh"
31#include "hb-ot-hhea-table.hh"
32#include "hb-ot-os2-table.hh"
33#include "hb-ot-var-hvar-table.hh"
34
35
36namespace OT {
37
38
39/*
40 * hmtx -- The Horizontal Metrics Table
41 * vmtx -- The Vertical Metrics Table
42 */
43
44#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
45#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
46
47
48struct LongMetric
49{
50 UFWORD advance; /* Advance width/height. */
51 FWORD lsb; /* Leading (left/top) side bearing. */
52 public:
53 DEFINE_SIZE_STATIC (4);
54};
55
56template <typename T>
57struct hmtxvmtx
58{
59 inline bool sanitize (hb_sanitize_context_t *c) const
60 {
61 TRACE_SANITIZE (this);
62 /* We don't check for anything specific here. The users of the
63 * struct do all the hard work... */
64 return_trace (true);
65 }
66
67 struct accelerator_t
68 {
69 inline void init (hb_face_t *face,
70 unsigned int default_advance_ = 0)
71 {
72 default_advance = default_advance_ ? default_advance_ : face->get_upem ();
73
74 bool got_font_extents = false;
75 if (T::os2Tag)
76 {
77 hb_blob_t *os2_blob = Sanitizer<os2>::sanitize (blob: face->reference_table (tag: T::os2Tag));
78 const os2 *os2_table = Sanitizer<os2>::lock_instance (blob: os2_blob);
79#define USE_TYPO_METRICS (1u<<7)
80 if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
81 {
82 ascender = os2_table->sTypoAscender;
83 descender = os2_table->sTypoDescender;
84 line_gap = os2_table->sTypoLineGap;
85 got_font_extents = (ascender | descender) != 0;
86 }
87 hb_blob_destroy (blob: os2_blob);
88 }
89
90 hb_blob_t *_hea_blob = Sanitizer<_hea>::sanitize (blob: face->reference_table (tag: T::headerTag));
91 const _hea *_hea_table = Sanitizer<_hea>::lock_instance (blob: _hea_blob);
92 num_advances = _hea_table->numberOfLongMetrics;
93 if (!got_font_extents)
94 {
95 ascender = _hea_table->ascender;
96 descender = _hea_table->descender;
97 line_gap = _hea_table->lineGap;
98 got_font_extents = (ascender | descender) != 0;
99 }
100 hb_blob_destroy (blob: _hea_blob);
101
102 has_font_extents = got_font_extents;
103
104 blob = Sanitizer<hmtxvmtx>::sanitize (face->reference_table (tag: T::tableTag));
105
106 /* Cap num_metrics() and num_advances() based on table length. */
107 unsigned int len = hb_blob_get_length (blob);
108 if (unlikely (num_advances * 4 > len))
109 num_advances = len / 4;
110 num_metrics = num_advances + (len - 4 * num_advances) / 2;
111
112 /* We MUST set num_metrics to zero if num_advances is zero.
113 * Our get_advance() depends on that. */
114 if (unlikely (!num_advances))
115 {
116 num_metrics = num_advances = 0;
117 hb_blob_destroy (blob);
118 blob = hb_blob_get_empty ();
119 }
120 table = Sanitizer<hmtxvmtx>::lock_instance (blob);
121
122 var_blob = Sanitizer<HVARVVAR>::sanitize (blob: face->reference_table (tag: T::variationsTag));
123 var_table = Sanitizer<HVARVVAR>::lock_instance (blob: var_blob);
124 }
125
126 inline void fini (void)
127 {
128 hb_blob_destroy (blob);
129 hb_blob_destroy (blob: var_blob);
130 }
131
132 inline unsigned int get_advance (hb_codepoint_t glyph,
133 hb_font_t *font) const
134 {
135 if (unlikely (glyph >= num_metrics))
136 {
137 /* If num_metrics is zero, it means we don't have the metrics table
138 * for this direction: return default advance. Otherwise, it means that the
139 * glyph index is out of bound: return zero. */
140 if (num_metrics)
141 return 0;
142 else
143 return default_advance;
144 }
145
146 return table->longMetric[MIN (a: glyph, b: (uint32_t) num_advances - 1)].advance
147 + var_table->get_advance_var (glyph, coords: font->coords, coord_count: font->num_coords); // TODO Optimize?!
148 }
149
150 public:
151 bool has_font_extents;
152 unsigned short ascender;
153 unsigned short descender;
154 unsigned short line_gap;
155
156 private:
157 unsigned int num_metrics;
158 unsigned int num_advances;
159 unsigned int default_advance;
160
161 const hmtxvmtx *table;
162 hb_blob_t *blob;
163 const HVARVVAR *var_table;
164 hb_blob_t *var_blob;
165 };
166
167 protected:
168 LongMetric longMetric[VAR]; /* Paired advance width and leading
169 * bearing values for each glyph. The
170 * value numOfHMetrics comes from
171 * the 'hhea' table. If the font is
172 * monospaced, only one entry need
173 * be in the array, but that entry is
174 * required. The last entry applies to
175 * all subsequent glyphs. */
176 FWORD leadingBearingX[VAR]; /* Here the advance is assumed
177 * to be the same as the advance
178 * for the last entry above. The
179 * number of entries in this array is
180 * derived from numGlyphs (from 'maxp'
181 * table) minus numberOfLongMetrics.
182 * This generally is used with a run
183 * of monospaced glyphs (e.g., Kanji
184 * fonts or Courier fonts). Only one
185 * run is allowed and it must be at
186 * the end. This allows a monospaced
187 * font to vary the side bearing
188 * values for each glyph. */
189 public:
190 DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX);
191};
192
193struct hmtx : hmtxvmtx<hmtx> {
194 static const hb_tag_t tableTag = HB_OT_TAG_hmtx;
195 static const hb_tag_t headerTag = HB_OT_TAG_hhea;
196 static const hb_tag_t variationsTag = HB_OT_TAG_HVAR;
197 static const hb_tag_t os2Tag = HB_OT_TAG_os2;
198};
199struct vmtx : hmtxvmtx<vmtx> {
200 static const hb_tag_t tableTag = HB_OT_TAG_vmtx;
201 static const hb_tag_t headerTag = HB_OT_TAG_vhea;
202 static const hb_tag_t variationsTag = HB_OT_TAG_VVAR;
203 static const hb_tag_t os2Tag = HB_TAG_NONE;
204};
205
206} /* namespace OT */
207
208
209#endif /* HB_OT_HMTX_TABLE_HH */
210

source code of qtbase/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh