1 /***************************************************************************/
5 /* TrueType-specific tables loader (body). */
7 /* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_OBJECTS_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_TRUETYPE_TAGS_H
27 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
34 /*************************************************************************/
36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
38 /* messages during execution. */
41 #define FT_COMPONENT trace_ttpload
44 /*************************************************************************/
47 /* tt_face_load_loca */
50 /* Load the locations table. */
53 /* face :: A handle to the target face object. */
56 /* stream :: The input stream. */
59 /* FreeType error code. 0 means success. */
61 FT_LOCAL_DEF( FT_Error
)
62 tt_face_load_loca( TT_Face face
,
70 /* we need the size of the `glyf' table for malformed `loca' tables */
71 error
= face
->goto_table( face
, TTAG_glyf
, stream
, &face
->glyf_len
);
73 /* it is possible that a font doesn't have a glyf table at all */
74 /* or its size is zero */
75 if ( error
== TT_Err_Table_Missing
)
80 FT_TRACE2(( "Locations " ));
81 error
= face
->goto_table( face
, TTAG_loca
, stream
, &table_len
);
84 error
= TT_Err_Locations_Missing
;
88 if ( face
->header
.Index_To_Loc_Format
!= 0 )
92 if ( table_len
>= 0x40000L
)
94 FT_TRACE2(( "table too large\n" ));
95 error
= TT_Err_Invalid_Table
;
98 face
->num_locations
= table_len
>> shift
;
104 if ( table_len
>= 0x20000L
)
106 FT_TRACE2(( "table too large\n" ));
107 error
= TT_Err_Invalid_Table
;
110 face
->num_locations
= table_len
>> shift
;
113 if ( face
->num_locations
!= (FT_ULong
)face
->root
.num_glyphs
)
115 FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
116 face
->num_locations
, face
->root
.num_glyphs
));
118 /* we only handle the case where `maxp' gives a larger value */
119 if ( face
->num_locations
< (FT_ULong
)face
->root
.num_glyphs
)
121 FT_Long new_loca_len
= (FT_Long
)face
->root
.num_glyphs
<< shift
;
123 TT_Table entry
= face
->dir_tables
;
124 TT_Table limit
= entry
+ face
->num_tables
;
126 FT_Long pos
= FT_Stream_Pos( stream
);
127 FT_Long dist
= 0x7FFFFFFFL
;
130 /* compute the distance to next table in font file */
131 for ( ; entry
< limit
; entry
++ )
133 FT_Long diff
= entry
->Offset
- pos
;
136 if ( diff
> 0 && diff
< dist
)
140 if ( entry
== limit
)
142 /* `loca' is the last table */
143 dist
= stream
->size
- pos
;
146 if ( new_loca_len
<= dist
)
148 face
->num_locations
= face
->root
.num_glyphs
;
149 table_len
= new_loca_len
;
151 FT_TRACE2(( "adjusting num_locations to %d\n",
152 face
->num_locations
));
158 * Extract the frame. We don't need to decompress it since
159 * we are able to parse it directly.
161 if ( FT_FRAME_EXTRACT( table_len
, face
->glyph_locations
) )
164 FT_TRACE2(( "loaded\n" ));
171 FT_LOCAL_DEF( FT_ULong
)
172 tt_face_get_location( TT_Face face
,
183 if ( gindex
< face
->num_locations
)
185 if ( face
->header
.Index_To_Loc_Format
!= 0 )
187 p
= face
->glyph_locations
+ gindex
* 4;
188 p_limit
= face
->glyph_locations
+ face
->num_locations
* 4;
190 pos1
= FT_NEXT_ULONG( p
);
193 if ( p
+ 4 <= p_limit
)
194 pos2
= FT_NEXT_ULONG( p
);
198 p
= face
->glyph_locations
+ gindex
* 2;
199 p_limit
= face
->glyph_locations
+ face
->num_locations
* 2;
201 pos1
= FT_NEXT_USHORT( p
);
204 if ( p
+ 2 <= p_limit
)
205 pos2
= FT_NEXT_USHORT( p
);
212 /* Check broken location data */
213 if ( pos1
>= face
->glyf_len
)
215 FT_TRACE1(( "tt_face_get_location:"
216 " too large offset=0x%08lx found for gid=0x%04lx,"
217 " exceeding the end of glyf table (0x%08lx)\n",
218 pos1
, gindex
, face
->glyf_len
));
223 if ( pos2
>= face
->glyf_len
)
225 FT_TRACE1(( "tt_face_get_location:"
226 " too large offset=0x%08lx found for gid=0x%04lx,"
227 " truncate at the end of glyf table (0x%08lx)\n",
228 pos2
, gindex
+ 1, face
->glyf_len
));
229 pos2
= face
->glyf_len
;
232 /* The `loca' table must be ordered; it refers to the length of */
233 /* an entry as the difference between the current and the next */
234 /* position. However, there do exist (malformed) fonts which */
235 /* don't obey this rule, so we are only able to provide an */
236 /* upper bound for the size. */
238 /* We get (intentionally) a wrong, non-zero result in case the */
239 /* `glyf' table is missing. */
241 *asize
= (FT_UInt
)( pos2
- pos1
);
243 *asize
= (FT_UInt
)( face
->glyf_len
- pos1
);
250 tt_face_done_loca( TT_Face face
)
252 FT_Stream stream
= face
->root
.stream
;
255 FT_FRAME_RELEASE( face
->glyph_locations
);
256 face
->num_locations
= 0;
261 /*************************************************************************/
264 /* tt_face_load_cvt */
267 /* Load the control value table into a face object. */
270 /* face :: A handle to the target face object. */
273 /* stream :: A handle to the input stream. */
276 /* FreeType error code. 0 means success. */
278 FT_LOCAL_DEF( FT_Error
)
279 tt_face_load_cvt( TT_Face face
,
282 #ifdef TT_USE_BYTECODE_INTERPRETER
285 FT_Memory memory
= stream
->memory
;
289 FT_TRACE2(( "CVT " ));
291 error
= face
->goto_table( face
, TTAG_cvt
, stream
, &table_len
);
294 FT_TRACE2(( "is missing\n" ));
303 face
->cvt_size
= table_len
/ 2;
305 if ( FT_NEW_ARRAY( face
->cvt
, face
->cvt_size
) )
308 if ( FT_FRAME_ENTER( face
->cvt_size
* 2L ) )
312 FT_Short
* cur
= face
->cvt
;
313 FT_Short
* limit
= cur
+ face
->cvt_size
;
316 for ( ; cur
< limit
; cur
++ )
317 *cur
= FT_GET_SHORT();
321 FT_TRACE2(( "loaded\n" ));
323 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
325 error
= tt_face_vary_cvt( face
, stream
);
331 #else /* !TT_USE_BYTECODE_INTERPRETER */
342 /*************************************************************************/
345 /* tt_face_load_fpgm */
348 /* Load the font program. */
351 /* face :: A handle to the target face object. */
354 /* stream :: A handle to the input stream. */
357 /* FreeType error code. 0 means success. */
359 FT_LOCAL_DEF( FT_Error
)
360 tt_face_load_fpgm( TT_Face face
,
363 #ifdef TT_USE_BYTECODE_INTERPRETER
369 FT_TRACE2(( "Font program " ));
371 /* The font program is optional */
372 error
= face
->goto_table( face
, TTAG_fpgm
, stream
, &table_len
);
375 face
->font_program
= NULL
;
376 face
->font_program_size
= 0;
379 FT_TRACE2(( "is missing\n" ));
383 face
->font_program_size
= table_len
;
384 if ( FT_FRAME_EXTRACT( table_len
, face
->font_program
) )
387 FT_TRACE2(( "loaded, %12d bytes\n", face
->font_program_size
));
393 #else /* !TT_USE_BYTECODE_INTERPRETER */
404 /*************************************************************************/
407 /* tt_face_load_prep */
410 /* Load the cvt program. */
413 /* face :: A handle to the target face object. */
416 /* stream :: A handle to the input stream. */
419 /* FreeType error code. 0 means success. */
421 FT_LOCAL_DEF( FT_Error
)
422 tt_face_load_prep( TT_Face face
,
425 #ifdef TT_USE_BYTECODE_INTERPRETER
431 FT_TRACE2(( "Prep program " ));
433 error
= face
->goto_table( face
, TTAG_prep
, stream
, &table_len
);
436 face
->cvt_program
= NULL
;
437 face
->cvt_program_size
= 0;
440 FT_TRACE2(( "is missing\n" ));
444 face
->cvt_program_size
= table_len
;
445 if ( FT_FRAME_EXTRACT( table_len
, face
->cvt_program
) )
448 FT_TRACE2(( "loaded, %12d bytes\n", face
->cvt_program_size
));
454 #else /* !TT_USE_BYTECODE_INTERPRETER */
465 /*************************************************************************/
468 /* tt_face_load_hdmx */
471 /* Load the `hdmx' table into the face object. */
474 /* face :: A handle to the target face object. */
476 /* stream :: A handle to the input stream. */
479 /* FreeType error code. 0 means success. */
482 FT_LOCAL_DEF( FT_Error
)
483 tt_face_load_hdmx( TT_Face face
,
487 FT_Memory memory
= stream
->memory
;
488 FT_UInt version
, nn
, num_records
;
489 FT_ULong table_size
, record_size
;
494 /* this table is optional */
495 error
= face
->goto_table( face
, TTAG_hdmx
, stream
, &table_size
);
496 if ( error
|| table_size
< 8 )
499 if ( FT_FRAME_EXTRACT( table_size
, face
->hdmx_table
) )
502 p
= face
->hdmx_table
;
503 limit
= p
+ table_size
;
505 version
= FT_NEXT_USHORT( p
);
506 num_records
= FT_NEXT_USHORT( p
);
507 record_size
= FT_NEXT_ULONG( p
);
509 /* The maximum number of bytes in an hdmx device record is the */
510 /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */
511 /* the reason why `record_size' is a long (which we read as */
512 /* unsigned long for convenience). In practice, two bytes */
513 /* sufficient to hold the size value. */
515 /* There are at least two fonts, HANNOM-A and HANNOM-B version */
516 /* 2.0 (2005), which get this wrong: The upper two bytes of */
517 /* the size value are set to 0xFF instead of 0x00. We catch */
520 if ( record_size
>= 0xFFFF0000UL
)
521 record_size
&= 0xFFFFU
;
523 /* The limit for `num_records' is a heuristic value. */
525 if ( version
!= 0 || num_records
> 255 || record_size
> 0x10001L
)
527 error
= TT_Err_Invalid_File_Format
;
531 if ( FT_NEW_ARRAY( face
->hdmx_record_sizes
, num_records
) )
534 for ( nn
= 0; nn
< num_records
; nn
++ )
536 if ( p
+ record_size
> limit
)
539 face
->hdmx_record_sizes
[nn
] = p
[0];
543 face
->hdmx_record_count
= nn
;
544 face
->hdmx_table_size
= table_size
;
545 face
->hdmx_record_size
= record_size
;
551 FT_FRAME_RELEASE( face
->hdmx_table
);
552 face
->hdmx_table_size
= 0;
558 tt_face_free_hdmx( TT_Face face
)
560 FT_Stream stream
= face
->root
.stream
;
561 FT_Memory memory
= stream
->memory
;
564 FT_FREE( face
->hdmx_record_sizes
);
565 FT_FRAME_RELEASE( face
->hdmx_table
);
569 /*************************************************************************/
571 /* Return the advance width table for a given pixel size if it is found */
572 /* in the font's `hdmx' table (if any). */
574 FT_LOCAL_DEF( FT_Byte
* )
575 tt_face_get_device_metrics( TT_Face face
,
580 FT_Byte
* result
= NULL
;
581 FT_ULong record_size
= face
->hdmx_record_size
;
582 FT_Byte
* record
= face
->hdmx_table
+ 8;
585 for ( nn
= 0; nn
< face
->hdmx_record_count
; nn
++ )
586 if ( face
->hdmx_record_sizes
[nn
] == ppem
)
589 if ( gindex
< record_size
)
590 result
= record
+ nn
* record_size
+ gindex
;