Disabling auto-refresh of game list by default, as it is causing bugs sometimes
[open-ps2-loader.git] / thirdparty / freetype-2.3.12 / src / sfnt / ttmtx.c
blob53e6ac7881f36b5cc9a8e5ecf88aaedc723c7e8e
1 /***************************************************************************/
2 /* */
3 /* ttmtx.c */
4 /* */
5 /* Load the metrics tables common to TTF and OTF fonts (body). */
6 /* */
7 /* Copyright 2006, 2007, 2008, 2009 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 /***************************************************************************/
19 #include <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_STREAM_H
22 #include FT_TRUETYPE_TAGS_H
23 #include "ttmtx.h"
25 #include "sferrors.h"
28 /*************************************************************************/
29 /* */
30 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
31 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
32 /* messages during execution. */
33 /* */
34 #undef FT_COMPONENT
35 #define FT_COMPONENT trace_ttmtx
39 * Unfortunately, we can't enable our memory optimizations if
40 * FT_CONFIG_OPTION_OLD_INTERNALS is defined. This is because at least
41 * one rogue client (libXfont in the X.Org XServer) is directly accessing
42 * the metrics.
45 /*************************************************************************/
46 /* */
47 /* <Function> */
48 /* tt_face_load_hmtx */
49 /* */
50 /* <Description> */
51 /* Load the `hmtx' or `vmtx' table into a face object. */
52 /* */
53 /* <Input> */
54 /* face :: A handle to the target face object. */
55 /* */
56 /* stream :: The input stream. */
57 /* */
58 /* vertical :: A boolean flag. If set, load `vmtx'. */
59 /* */
60 /* <Return> */
61 /* FreeType error code. 0 means success. */
62 /* */
63 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
65 FT_LOCAL_DEF( FT_Error )
66 tt_face_load_hmtx( TT_Face face,
67 FT_Stream stream,
68 FT_Bool vertical )
70 FT_Error error;
71 FT_ULong tag, table_size;
72 FT_ULong* ptable_offset;
73 FT_ULong* ptable_size;
76 if ( vertical )
78 tag = TTAG_vmtx;
79 ptable_offset = &face->vert_metrics_offset;
80 ptable_size = &face->vert_metrics_size;
82 else
84 tag = TTAG_hmtx;
85 ptable_offset = &face->horz_metrics_offset;
86 ptable_size = &face->horz_metrics_size;
89 error = face->goto_table( face, tag, stream, &table_size );
90 if ( error )
91 goto Fail;
93 *ptable_size = table_size;
94 *ptable_offset = FT_STREAM_POS();
96 Fail:
97 return error;
100 #else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
102 FT_LOCAL_DEF( FT_Error )
103 tt_face_load_hmtx( TT_Face face,
104 FT_Stream stream,
105 FT_Bool vertical )
107 FT_Error error;
108 FT_Memory memory = stream->memory;
110 FT_ULong table_len;
111 FT_Long num_shorts, num_longs, num_shorts_checked;
113 TT_LongMetrics* longs;
114 TT_ShortMetrics** shorts;
115 FT_Byte* p;
118 if ( vertical )
120 void* lm = &face->vertical.long_metrics;
121 void** sm = &face->vertical.short_metrics;
124 error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
125 if ( error )
126 goto Fail;
128 num_longs = face->vertical.number_Of_VMetrics;
129 if ( (FT_ULong)num_longs > table_len / 4 )
130 num_longs = (FT_Long)( table_len / 4 );
132 face->vertical.number_Of_VMetrics = 0;
134 longs = (TT_LongMetrics*)lm;
135 shorts = (TT_ShortMetrics**)sm;
137 else
139 void* lm = &face->horizontal.long_metrics;
140 void** sm = &face->horizontal.short_metrics;
143 error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
144 if ( error )
145 goto Fail;
147 num_longs = face->horizontal.number_Of_HMetrics;
148 if ( (FT_ULong)num_longs > table_len / 4 )
149 num_longs = (FT_Long)( table_len / 4 );
151 face->horizontal.number_Of_HMetrics = 0;
153 longs = (TT_LongMetrics*)lm;
154 shorts = (TT_ShortMetrics**)sm;
157 /* never trust derived values */
159 num_shorts = face->max_profile.numGlyphs - num_longs;
160 num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
162 if ( num_shorts < 0 )
164 FT_TRACE0(( "tt_face_load_hmtx:"
165 " %cmtx has more metrics than glyphs.\n",
166 vertical ? "v" : "h" ));
168 /* Adobe simply ignores this problem. So we shall do the same. */
169 #if 0
170 error = vertical ? SFNT_Err_Invalid_Vert_Metrics
171 : SFNT_Err_Invalid_Horiz_Metrics;
172 goto Exit;
173 #else
174 num_shorts = 0;
175 #endif
178 if ( FT_QNEW_ARRAY( *longs, num_longs ) ||
179 FT_QNEW_ARRAY( *shorts, num_shorts ) )
180 goto Fail;
182 if ( FT_FRAME_ENTER( table_len ) )
183 goto Fail;
185 p = stream->cursor;
188 TT_LongMetrics cur = *longs;
189 TT_LongMetrics limit = cur + num_longs;
192 for ( ; cur < limit; cur++ )
194 cur->advance = FT_NEXT_USHORT( p );
195 cur->bearing = FT_NEXT_SHORT( p );
199 /* do we have an inconsistent number of metric values? */
201 TT_ShortMetrics* cur = *shorts;
202 TT_ShortMetrics* limit = cur +
203 FT_MIN( num_shorts, num_shorts_checked );
206 for ( ; cur < limit; cur++ )
207 *cur = FT_NEXT_SHORT( p );
209 /* We fill up the missing left side bearings with the */
210 /* last valid value. Since this will occur for buggy CJK */
211 /* fonts usually only, nothing serious will happen. */
212 if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
214 FT_Short val = (*shorts)[num_shorts_checked - 1];
217 limit = *shorts + num_shorts;
218 for ( ; cur < limit; cur++ )
219 *cur = val;
223 FT_FRAME_EXIT();
225 if ( vertical )
226 face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
227 else
228 face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
230 Fail:
231 return error;
234 #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
237 /*************************************************************************/
238 /* */
239 /* <Function> */
240 /* tt_face_load_hhea */
241 /* */
242 /* <Description> */
243 /* Load the `hhea' or 'vhea' table into a face object. */
244 /* */
245 /* <Input> */
246 /* face :: A handle to the target face object. */
247 /* */
248 /* stream :: The input stream. */
249 /* */
250 /* vertical :: A boolean flag. If set, load `vhea'. */
251 /* */
252 /* <Return> */
253 /* FreeType error code. 0 means success. */
254 /* */
255 FT_LOCAL_DEF( FT_Error )
256 tt_face_load_hhea( TT_Face face,
257 FT_Stream stream,
258 FT_Bool vertical )
260 FT_Error error;
261 TT_HoriHeader* header;
263 const FT_Frame_Field metrics_header_fields[] =
265 #undef FT_STRUCTURE
266 #define FT_STRUCTURE TT_HoriHeader
268 FT_FRAME_START( 36 ),
269 FT_FRAME_ULONG ( Version ),
270 FT_FRAME_SHORT ( Ascender ),
271 FT_FRAME_SHORT ( Descender ),
272 FT_FRAME_SHORT ( Line_Gap ),
273 FT_FRAME_USHORT( advance_Width_Max ),
274 FT_FRAME_SHORT ( min_Left_Side_Bearing ),
275 FT_FRAME_SHORT ( min_Right_Side_Bearing ),
276 FT_FRAME_SHORT ( xMax_Extent ),
277 FT_FRAME_SHORT ( caret_Slope_Rise ),
278 FT_FRAME_SHORT ( caret_Slope_Run ),
279 FT_FRAME_SHORT ( caret_Offset ),
280 FT_FRAME_SHORT ( Reserved[0] ),
281 FT_FRAME_SHORT ( Reserved[1] ),
282 FT_FRAME_SHORT ( Reserved[2] ),
283 FT_FRAME_SHORT ( Reserved[3] ),
284 FT_FRAME_SHORT ( metric_Data_Format ),
285 FT_FRAME_USHORT( number_Of_HMetrics ),
286 FT_FRAME_END
290 if ( vertical )
292 void *v = &face->vertical;
295 error = face->goto_table( face, TTAG_vhea, stream, 0 );
296 if ( error )
297 goto Fail;
299 header = (TT_HoriHeader*)v;
301 else
303 error = face->goto_table( face, TTAG_hhea, stream, 0 );
304 if ( error )
305 goto Fail;
307 header = &face->horizontal;
310 if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
311 goto Fail;
313 FT_TRACE3(( "Ascender: %5d\n", header->Ascender ));
314 FT_TRACE3(( "Descender: %5d\n", header->Descender ));
315 FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
317 header->long_metrics = NULL;
318 header->short_metrics = NULL;
320 Fail:
321 return error;
325 /*************************************************************************/
326 /* */
327 /* <Function> */
328 /* tt_face_get_metrics */
329 /* */
330 /* <Description> */
331 /* Returns the horizontal or vertical metrics in font units for a */
332 /* given glyph. The metrics are the left side bearing (resp. top */
333 /* side bearing) and advance width (resp. advance height). */
334 /* */
335 /* <Input> */
336 /* header :: A pointer to either the horizontal or vertical metrics */
337 /* structure. */
338 /* */
339 /* idx :: The glyph index. */
340 /* */
341 /* <Output> */
342 /* bearing :: The bearing, either left side or top side. */
343 /* */
344 /* advance :: The advance width resp. advance height. */
345 /* */
346 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
348 FT_LOCAL_DEF( FT_Error )
349 tt_face_get_metrics( TT_Face face,
350 FT_Bool vertical,
351 FT_UInt gindex,
352 FT_Short *abearing,
353 FT_UShort *aadvance )
355 FT_Error error;
356 FT_Stream stream = face->root.stream;
357 TT_HoriHeader* header;
358 FT_ULong table_pos, table_size, table_end;
359 FT_UShort k;
362 if ( vertical )
364 void* v = &face->vertical;
367 header = (TT_HoriHeader*)v;
368 table_pos = face->vert_metrics_offset;
369 table_size = face->vert_metrics_size;
371 else
373 header = &face->horizontal;
374 table_pos = face->horz_metrics_offset;
375 table_size = face->horz_metrics_size;
378 table_end = table_pos + table_size;
380 k = header->number_Of_HMetrics;
382 if ( k > 0 )
384 if ( gindex < (FT_UInt)k )
386 table_pos += 4 * gindex;
387 if ( table_pos + 4 > table_end )
388 goto NoData;
390 if ( FT_STREAM_SEEK( table_pos ) ||
391 FT_READ_USHORT( *aadvance ) ||
392 FT_READ_SHORT( *abearing ) )
393 goto NoData;
395 else
397 table_pos += 4 * ( k - 1 );
398 if ( table_pos + 4 > table_end )
399 goto NoData;
401 if ( FT_STREAM_SEEK( table_pos ) ||
402 FT_READ_USHORT( *aadvance ) )
403 goto NoData;
405 table_pos += 4 + 2 * ( gindex - k );
406 if ( table_pos + 2 > table_end )
407 *abearing = 0;
408 else
410 if ( !FT_STREAM_SEEK( table_pos ) )
411 (void)FT_READ_SHORT( *abearing );
415 else
417 NoData:
418 *abearing = 0;
419 *aadvance = 0;
422 return SFNT_Err_Ok;
425 #else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
427 FT_LOCAL_DEF( FT_Error )
428 tt_face_get_metrics( TT_Face face,
429 FT_Bool vertical,
430 FT_UInt gindex,
431 FT_Short* abearing,
432 FT_UShort* aadvance )
434 void* v = &face->vertical;
435 void* h = &face->horizontal;
436 TT_HoriHeader* header = vertical ? (TT_HoriHeader*)v
437 : (TT_HoriHeader*)h;
438 TT_LongMetrics longs_m;
439 FT_UShort k = header->number_Of_HMetrics;
442 if ( k == 0 ||
443 !header->long_metrics ||
444 gindex >= (FT_UInt)face->max_profile.numGlyphs )
446 *abearing = *aadvance = 0;
447 return SFNT_Err_Ok;
450 if ( gindex < (FT_UInt)k )
452 longs_m = (TT_LongMetrics)header->long_metrics + gindex;
453 *abearing = longs_m->bearing;
454 *aadvance = longs_m->advance;
456 else
458 *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
459 *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
462 return SFNT_Err_Ok;
465 #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
468 /* END */