1 /***************************************************************************/
5 /* TrueType-specific tables loader (body). */
7 /* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007 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. */
62 FT_LOCAL_DEF( FT_Error
)
63 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
);
75 FT_TRACE2(( "Locations " ));
76 error
= face
->goto_table( face
, TTAG_loca
, stream
, &table_len
);
79 error
= TT_Err_Locations_Missing
;
83 if ( face
->header
.Index_To_Loc_Format
!= 0 )
85 if ( table_len
>= 0x40000L
)
87 FT_TRACE2(( "table too large!\n" ));
88 error
= TT_Err_Invalid_Table
;
91 face
->num_locations
= (FT_UInt
)( table_len
>> 2 );
95 if ( table_len
>= 0x20000L
)
97 FT_TRACE2(( "table too large!\n" ));
98 error
= TT_Err_Invalid_Table
;
101 face
->num_locations
= (FT_UInt
)( table_len
>> 1 );
105 * Extract the frame. We don't need to decompress it since
106 * we are able to parse it directly.
108 if ( FT_FRAME_EXTRACT( table_len
, face
->glyph_locations
) )
111 FT_TRACE2(( "loaded\n" ));
118 FT_LOCAL_DEF( FT_ULong
)
119 tt_face_get_location( TT_Face face
,
130 if ( gindex
< face
->num_locations
)
132 if ( face
->header
.Index_To_Loc_Format
!= 0 )
134 p
= face
->glyph_locations
+ gindex
* 4;
135 p_limit
= face
->glyph_locations
+ face
->num_locations
* 4;
137 pos1
= FT_NEXT_ULONG( p
);
140 if ( p
+ 4 <= p_limit
)
141 pos2
= FT_NEXT_ULONG( p
);
145 p
= face
->glyph_locations
+ gindex
* 2;
146 p_limit
= face
->glyph_locations
+ face
->num_locations
* 2;
148 pos1
= FT_NEXT_USHORT( p
);
151 if ( p
+ 2 <= p_limit
)
152 pos2
= FT_NEXT_USHORT( p
);
159 /* It isn't mentioned explicitly that the `loca' table must be */
160 /* ordered, but implicitly it refers to the length of an entry */
161 /* as the difference between the current and the next position. */
162 /* Anyway, there do exist (malformed) fonts which don't obey */
163 /* this rule, so we are only able to provide an upper bound for */
166 *asize
= (FT_UInt
)( pos2
- pos1
);
168 *asize
= (FT_UInt
)( face
->glyf_len
- pos1
);
175 tt_face_done_loca( TT_Face face
)
177 FT_Stream stream
= face
->root
.stream
;
180 FT_FRAME_RELEASE( face
->glyph_locations
);
181 face
->num_locations
= 0;
186 /*************************************************************************/
189 /* tt_face_load_cvt */
192 /* Load the control value table into a face object. */
195 /* face :: A handle to the target face object. */
198 /* stream :: A handle to the input stream. */
201 /* FreeType error code. 0 means success. */
203 FT_LOCAL_DEF( FT_Error
)
204 tt_face_load_cvt( TT_Face face
,
207 #ifdef TT_USE_BYTECODE_INTERPRETER
210 FT_Memory memory
= stream
->memory
;
214 FT_TRACE2(( "CVT " ));
216 error
= face
->goto_table( face
, TTAG_cvt
, stream
, &table_len
);
219 FT_TRACE2(( "is missing!\n" ));
228 face
->cvt_size
= table_len
/ 2;
230 if ( FT_NEW_ARRAY( face
->cvt
, face
->cvt_size
) )
233 if ( FT_FRAME_ENTER( face
->cvt_size
* 2L ) )
237 FT_Short
* cur
= face
->cvt
;
238 FT_Short
* limit
= cur
+ face
->cvt_size
;
241 for ( ; cur
< limit
; cur
++ )
242 *cur
= FT_GET_SHORT();
246 FT_TRACE2(( "loaded\n" ));
248 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
250 error
= tt_face_vary_cvt( face
, stream
);
256 #else /* !TT_USE_BYTECODE_INTERPRETER */
267 /*************************************************************************/
270 /* tt_face_load_fpgm */
273 /* Load the font program. */
276 /* face :: A handle to the target face object. */
279 /* stream :: A handle to the input stream. */
282 /* FreeType error code. 0 means success. */
284 FT_LOCAL_DEF( FT_Error
)
285 tt_face_load_fpgm( TT_Face face
,
288 #ifdef TT_USE_BYTECODE_INTERPRETER
294 FT_TRACE2(( "Font program " ));
296 /* The font program is optional */
297 error
= face
->goto_table( face
, TTAG_fpgm
, stream
, &table_len
);
300 face
->font_program
= NULL
;
301 face
->font_program_size
= 0;
304 FT_TRACE2(( "is missing!\n" ));
308 face
->font_program_size
= table_len
;
309 if ( FT_FRAME_EXTRACT( table_len
, face
->font_program
) )
312 FT_TRACE2(( "loaded, %12d bytes\n", face
->font_program_size
));
318 #else /* !TT_USE_BYTECODE_INTERPRETER */
329 /*************************************************************************/
332 /* tt_face_load_prep */
335 /* Load the cvt program. */
338 /* face :: A handle to the target face object. */
341 /* stream :: A handle to the input stream. */
344 /* FreeType error code. 0 means success. */
346 FT_LOCAL_DEF( FT_Error
)
347 tt_face_load_prep( TT_Face face
,
350 #ifdef TT_USE_BYTECODE_INTERPRETER
356 FT_TRACE2(( "Prep program " ));
358 error
= face
->goto_table( face
, TTAG_prep
, stream
, &table_len
);
361 face
->cvt_program
= NULL
;
362 face
->cvt_program_size
= 0;
365 FT_TRACE2(( "is missing!\n" ));
369 face
->cvt_program_size
= table_len
;
370 if ( FT_FRAME_EXTRACT( table_len
, face
->cvt_program
) )
373 FT_TRACE2(( "loaded, %12d bytes\n", face
->cvt_program_size
));
379 #else /* !TT_USE_BYTECODE_INTERPRETER */
390 /*************************************************************************/
393 /* tt_face_load_hdmx */
396 /* Load the `hdmx' table into the face object. */
399 /* face :: A handle to the target face object. */
401 /* stream :: A handle to the input stream. */
404 /* FreeType error code. 0 means success. */
407 FT_LOCAL_DEF( FT_Error
)
408 tt_face_load_hdmx( TT_Face face
,
412 FT_Memory memory
= stream
->memory
;
413 FT_UInt version
, nn
, num_records
;
414 FT_ULong table_size
, record_size
;
419 /* this table is optional */
420 error
= face
->goto_table( face
, TTAG_hdmx
, stream
, &table_size
);
421 if ( error
|| table_size
< 8 )
424 if ( FT_FRAME_EXTRACT( table_size
, face
->hdmx_table
) )
427 p
= face
->hdmx_table
;
428 limit
= p
+ table_size
;
430 version
= FT_NEXT_USHORT( p
);
431 num_records
= FT_NEXT_USHORT( p
);
432 record_size
= FT_NEXT_ULONG( p
);
434 /* The maximum number of bytes in an hdmx device record is the */
435 /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */
436 /* the reason why `record_size' is a long (which we read as */
437 /* unsigned long for convenience). In practice, two bytes */
438 /* sufficient to hold the size value. */
440 /* There are at least two fonts, HANNOM-A and HANNOM-B version */
441 /* 2.0 (2005), which get this wrong: The upper two bytes of */
442 /* the size value are set to 0xFF instead of 0x00. We catch */
445 if ( record_size
>= 0xFFFF0000UL
)
446 record_size
&= 0xFFFFU
;
448 /* The limit for `num_records' is a heuristic value. */
450 if ( version
!= 0 || num_records
> 255 || record_size
> 0x10001L
)
452 error
= TT_Err_Invalid_File_Format
;
456 if ( FT_NEW_ARRAY( face
->hdmx_record_sizes
, num_records
) )
459 for ( nn
= 0; nn
< num_records
; nn
++ )
461 if ( p
+ record_size
> limit
)
464 face
->hdmx_record_sizes
[nn
] = p
[0];
468 face
->hdmx_record_count
= nn
;
469 face
->hdmx_table_size
= table_size
;
470 face
->hdmx_record_size
= record_size
;
476 FT_FRAME_RELEASE( face
->hdmx_table
);
477 face
->hdmx_table_size
= 0;
483 tt_face_free_hdmx( TT_Face face
)
485 FT_Stream stream
= face
->root
.stream
;
486 FT_Memory memory
= stream
->memory
;
489 FT_FREE( face
->hdmx_record_sizes
);
490 FT_FRAME_RELEASE( face
->hdmx_table
);
494 /*************************************************************************/
496 /* Return the advance width table for a given pixel size if it is found */
497 /* in the font's `hdmx' table (if any). */
499 FT_LOCAL_DEF( FT_Byte
* )
500 tt_face_get_device_metrics( TT_Face face
,
505 FT_Byte
* result
= NULL
;
506 FT_ULong record_size
= face
->hdmx_record_size
;
507 FT_Byte
* record
= face
->hdmx_table
+ 8;
510 for ( nn
= 0; nn
< face
->hdmx_record_count
; nn
++ )
511 if ( face
->hdmx_record_sizes
[nn
] == ppem
)
514 if ( gindex
< record_size
)
515 result
= record
+ nn
* record_size
+ gindex
;