1/***************************************************************************/
2/* */
3/* ttmtx.c */
4/* */
5/* Load the metrics tables common to TTF and OTF fonts (body). */
6/* */
7/* Copyright 2006-2018 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
18
19#include <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21#include FT_INTERNAL_STREAM_H
22#include FT_TRUETYPE_TAGS_H
23
24#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
25#include FT_SERVICE_METRICS_VARIATIONS_H
26#endif
27
28#include "ttmtx.h"
29
30#include "sferrors.h"
31
32
33 /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */
34 /* be identical except for the names of their fields, */
35 /* which are different. */
36 /* */
37 /* This ensures that `tt_face_load_hmtx' is able to read */
38 /* both the horizontal and vertical headers. */
39
40
41 /*************************************************************************/
42 /* */
43 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
44 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
45 /* messages during execution. */
46 /* */
47#undef FT_COMPONENT
48#define FT_COMPONENT trace_ttmtx
49
50
51 /*************************************************************************/
52 /* */
53 /* <Function> */
54 /* tt_face_load_hmtx */
55 /* */
56 /* <Description> */
57 /* Load the `hmtx' or `vmtx' table into a face object. */
58 /* */
59 /* <Input> */
60 /* face :: A handle to the target face object. */
61 /* */
62 /* stream :: The input stream. */
63 /* */
64 /* vertical :: A boolean flag. If set, load `vmtx'. */
65 /* */
66 /* <Return> */
67 /* FreeType error code. 0 means success. */
68 /* */
69 FT_LOCAL_DEF( FT_Error )
70 tt_face_load_hmtx( TT_Face face,
71 FT_Stream stream,
72 FT_Bool vertical )
73 {
74 FT_Error error;
75 FT_ULong tag, table_size;
76 FT_ULong* ptable_offset;
77 FT_ULong* ptable_size;
78
79
80 if ( vertical )
81 {
82 tag = TTAG_vmtx;
83 ptable_offset = &face->vert_metrics_offset;
84 ptable_size = &face->vert_metrics_size;
85 }
86 else
87 {
88 tag = TTAG_hmtx;
89 ptable_offset = &face->horz_metrics_offset;
90 ptable_size = &face->horz_metrics_size;
91 }
92
93 error = face->goto_table( face, tag, stream, &table_size );
94 if ( error )
95 goto Fail;
96
97 *ptable_size = table_size;
98 *ptable_offset = FT_STREAM_POS();
99
100 Fail:
101 return error;
102 }
103
104
105 /*************************************************************************/
106 /* */
107 /* <Function> */
108 /* tt_face_load_hhea */
109 /* */
110 /* <Description> */
111 /* Load the `hhea' or 'vhea' table into a face object. */
112 /* */
113 /* <Input> */
114 /* face :: A handle to the target face object. */
115 /* */
116 /* stream :: The input stream. */
117 /* */
118 /* vertical :: A boolean flag. If set, load `vhea'. */
119 /* */
120 /* <Return> */
121 /* FreeType error code. 0 means success. */
122 /* */
123 FT_LOCAL_DEF( FT_Error )
124 tt_face_load_hhea( TT_Face face,
125 FT_Stream stream,
126 FT_Bool vertical )
127 {
128 FT_Error error;
129 TT_HoriHeader* header;
130
131 static const FT_Frame_Field metrics_header_fields[] =
132 {
133#undef FT_STRUCTURE
134#define FT_STRUCTURE TT_HoriHeader
135
136 FT_FRAME_START( 36 ),
137 FT_FRAME_ULONG ( Version ),
138 FT_FRAME_SHORT ( Ascender ),
139 FT_FRAME_SHORT ( Descender ),
140 FT_FRAME_SHORT ( Line_Gap ),
141 FT_FRAME_USHORT( advance_Width_Max ),
142 FT_FRAME_SHORT ( min_Left_Side_Bearing ),
143 FT_FRAME_SHORT ( min_Right_Side_Bearing ),
144 FT_FRAME_SHORT ( xMax_Extent ),
145 FT_FRAME_SHORT ( caret_Slope_Rise ),
146 FT_FRAME_SHORT ( caret_Slope_Run ),
147 FT_FRAME_SHORT ( caret_Offset ),
148 FT_FRAME_SHORT ( Reserved[0] ),
149 FT_FRAME_SHORT ( Reserved[1] ),
150 FT_FRAME_SHORT ( Reserved[2] ),
151 FT_FRAME_SHORT ( Reserved[3] ),
152 FT_FRAME_SHORT ( metric_Data_Format ),
153 FT_FRAME_USHORT( number_Of_HMetrics ),
154 FT_FRAME_END
155 };
156
157
158 if ( vertical )
159 {
160 void *v = &face->vertical;
161
162
163 error = face->goto_table( face, TTAG_vhea, stream, 0 );
164 if ( error )
165 goto Fail;
166
167 header = (TT_HoriHeader*)v;
168 }
169 else
170 {
171 error = face->goto_table( face, TTAG_hhea, stream, 0 );
172 if ( error )
173 goto Fail;
174
175 header = &face->horizontal;
176 }
177
178 if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
179 goto Fail;
180
181 FT_TRACE3(( "Ascender: %5d\n", header->Ascender ));
182 FT_TRACE3(( "Descender: %5d\n", header->Descender ));
183 FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
184
185 header->long_metrics = NULL;
186 header->short_metrics = NULL;
187
188 Fail:
189 return error;
190 }
191
192
193 /*************************************************************************/
194 /* */
195 /* <Function> */
196 /* tt_face_get_metrics */
197 /* */
198 /* <Description> */
199 /* Return the horizontal or vertical metrics in font units for a */
200 /* given glyph. The values are the left side bearing (top side */
201 /* bearing for vertical metrics) and advance width (advance height */
202 /* for vertical metrics). */
203 /* */
204 /* <Input> */
205 /* face :: A pointer to the TrueType face structure. */
206 /* */
207 /* vertical :: If set to TRUE, get vertical metrics. */
208 /* */
209 /* gindex :: The glyph index. */
210 /* */
211 /* <Output> */
212 /* abearing :: The bearing, either left side or top side. */
213 /* */
214 /* aadvance :: The advance width or advance height, depending on */
215 /* the `vertical' flag. */
216 /* */
217 FT_LOCAL_DEF( void )
218 tt_face_get_metrics( TT_Face face,
219 FT_Bool vertical,
220 FT_UInt gindex,
221 FT_Short *abearing,
222 FT_UShort *aadvance )
223 {
224 FT_Error error;
225 FT_Stream stream = face->root.stream;
226 TT_HoriHeader* header;
227 FT_ULong table_pos, table_size, table_end;
228 FT_UShort k;
229
230#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
231 FT_Service_MetricsVariations var =
232 (FT_Service_MetricsVariations)face->var;
233#endif
234
235
236 if ( vertical )
237 {
238 void* v = &face->vertical;
239
240
241 header = (TT_HoriHeader*)v;
242 table_pos = face->vert_metrics_offset;
243 table_size = face->vert_metrics_size;
244 }
245 else
246 {
247 header = &face->horizontal;
248 table_pos = face->horz_metrics_offset;
249 table_size = face->horz_metrics_size;
250 }
251
252 table_end = table_pos + table_size;
253
254 k = header->number_Of_HMetrics;
255
256 if ( k > 0 )
257 {
258 if ( gindex < (FT_UInt)k )
259 {
260 table_pos += 4 * gindex;
261 if ( table_pos + 4 > table_end )
262 goto NoData;
263
264 if ( FT_STREAM_SEEK( table_pos ) ||
265 FT_READ_USHORT( *aadvance ) ||
266 FT_READ_SHORT( *abearing ) )
267 goto NoData;
268 }
269 else
270 {
271 table_pos += 4 * ( k - 1 );
272 if ( table_pos + 4 > table_end )
273 goto NoData;
274
275 if ( FT_STREAM_SEEK( table_pos ) ||
276 FT_READ_USHORT( *aadvance ) )
277 goto NoData;
278
279 table_pos += 4 + 2 * ( gindex - k );
280 if ( table_pos + 2 > table_end )
281 *abearing = 0;
282 else
283 {
284 if ( !FT_STREAM_SEEK( table_pos ) )
285 (void)FT_READ_SHORT( *abearing );
286 }
287 }
288 }
289 else
290 {
291 NoData:
292 *abearing = 0;
293 *aadvance = 0;
294 }
295
296#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
297 if ( var )
298 {
299 FT_Face f = FT_FACE( face );
300 FT_Int a = (FT_Int)*aadvance;
301 FT_Int b = (FT_Int)*abearing;
302
303
304 if ( vertical )
305 {
306 if ( var->vadvance_adjust )
307 var->vadvance_adjust( f, gindex, &a );
308 if ( var->tsb_adjust )
309 var->tsb_adjust( f, gindex, &b );
310 }
311 else
312 {
313 if ( var->hadvance_adjust )
314 var->hadvance_adjust( f, gindex, &a );
315 if ( var->lsb_adjust )
316 var->lsb_adjust( f, gindex, &b );
317 }
318
319 *aadvance = (FT_UShort)a;
320 *abearing = (FT_Short)b;
321 }
322#endif
323 }
324
325
326/* END */
327