1 /***************************************************************************/
5 /* Objects manager (body). */
7 /* Copyright 1996-2001, 2002, 2003, 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_CALC_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_TRUETYPE_IDS_H
24 #include FT_TRUETYPE_TAGS_H
25 #include FT_INTERNAL_SFNT_H
32 #ifdef TT_USE_BYTECODE_INTERPRETER
36 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
37 #include FT_TRUETYPE_UNPATENTED_H
40 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
44 /*************************************************************************/
46 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
47 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
48 /* messages during execution. */
51 #define FT_COMPONENT trace_ttobjs
54 #ifdef TT_USE_BYTECODE_INTERPRETER
56 /*************************************************************************/
58 /* GLYPH ZONE FUNCTIONS */
60 /*************************************************************************/
63 /*************************************************************************/
66 /* tt_glyphzone_done */
69 /* Deallocate a glyph zone. */
72 /* zone :: A pointer to the target glyph zone. */
75 tt_glyphzone_done( TT_GlyphZone zone
)
77 FT_Memory memory
= zone
->memory
;
82 FT_FREE( zone
->contours
);
83 FT_FREE( zone
->tags
);
86 FT_FREE( zone
->orus
);
88 zone
->max_points
= zone
->n_points
= 0;
89 zone
->max_contours
= zone
->n_contours
= 0;
95 /*************************************************************************/
98 /* tt_glyphzone_new */
101 /* Allocate a new glyph zone. */
104 /* memory :: A handle to the current memory object. */
106 /* maxPoints :: The capacity of glyph zone in points. */
108 /* maxContours :: The capacity of glyph zone in contours. */
111 /* zone :: A pointer to the target glyph zone record. */
114 /* FreeType error code. 0 means success. */
116 FT_LOCAL_DEF( FT_Error
)
117 tt_glyphzone_new( FT_Memory memory
,
119 FT_Short maxContours
,
125 FT_MEM_ZERO( zone
, sizeof ( *zone
) );
126 zone
->memory
= memory
;
128 if ( FT_NEW_ARRAY( zone
->org
, maxPoints
) ||
129 FT_NEW_ARRAY( zone
->cur
, maxPoints
) ||
130 FT_NEW_ARRAY( zone
->orus
, maxPoints
) ||
131 FT_NEW_ARRAY( zone
->tags
, maxPoints
) ||
132 FT_NEW_ARRAY( zone
->contours
, maxContours
) )
134 tt_glyphzone_done( zone
);
138 zone
->max_points
= maxPoints
;
139 zone
->max_contours
= maxContours
;
144 #endif /* TT_USE_BYTECODE_INTERPRETER */
147 /*************************************************************************/
153 /* Initialize a given TrueType face object. */
156 /* stream :: The source font stream. */
158 /* face_index :: The index of the font face in the resource. */
160 /* num_params :: Number of additional generic parameters. Ignored. */
162 /* params :: Additional generic parameters. Ignored. */
165 /* face :: The newly built face object. */
168 /* FreeType error code. 0 means success. */
170 FT_LOCAL_DEF( FT_Error
)
171 tt_face_init( FT_Stream stream
,
172 FT_Face ttface
, /* TT_Face */
175 FT_Parameter
* params
)
180 TT_Face face
= (TT_Face
)ttface
;
183 library
= face
->root
.driver
->root
.library
;
184 sfnt
= (SFNT_Service
)FT_Get_Module_Interface( library
, "sfnt" );
188 /* create input stream from resource */
189 if ( FT_STREAM_SEEK( 0 ) )
192 /* check that we have a valid TrueType file */
193 error
= sfnt
->init_face( stream
, face
, face_index
, num_params
, params
);
197 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
198 /* The 0x00020000 tag is completely undocumented; some fonts from */
199 /* Arphic made for Chinese Windows 3.1 have this. */
200 if ( face
->format_tag
!= 0x00010000L
&& /* MS fonts */
201 face
->format_tag
!= 0x00020000L
&& /* CJK fonts for Win 3.1 */
202 face
->format_tag
!= TTAG_true
) /* Mac fonts */
204 FT_TRACE2(( "[not a valid TTF font]\n" ));
208 #ifdef TT_USE_BYTECODE_INTERPRETER
209 face
->root
.face_flags
|= FT_FACE_FLAG_HINTER
;
212 /* If we are performing a simple font format check, exit immediately. */
213 if ( face_index
< 0 )
216 /* Load font directory */
217 error
= sfnt
->load_face( stream
, face
, face_index
, num_params
, params
);
221 error
= tt_face_load_hdmx( face
, stream
);
225 if ( face
->root
.face_flags
& FT_FACE_FLAG_SCALABLE
)
228 #ifdef FT_CONFIG_OPTION_INCREMENTAL
230 if ( !face
->root
.internal
->incremental_interface
)
231 error
= tt_face_load_loca( face
, stream
);
233 error
= tt_face_load_cvt( face
, stream
);
235 error
= tt_face_load_fpgm( face
, stream
);
237 error
= tt_face_load_prep( face
, stream
);
242 error
= tt_face_load_loca( face
, stream
);
244 error
= tt_face_load_cvt( face
, stream
);
246 error
= tt_face_load_fpgm( face
, stream
);
248 error
= tt_face_load_prep( face
, stream
);
254 #if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
255 !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
258 FT_Bool unpatented_hinting
;
262 /* Determine whether unpatented hinting is to be used for this face. */
263 unpatented_hinting
= FT_BOOL
264 ( library
->debug_hooks
[FT_DEBUG_HOOK_UNPATENTED_HINTING
] != NULL
);
266 for ( i
= 0; i
< num_params
&& !face
->unpatented_hinting
; i
++ )
267 if ( params
[i
].tag
== FT_PARAM_TAG_UNPATENTED_HINTING
)
268 unpatented_hinting
= TRUE
;
270 /* Compare the face with a list of well-known `tricky' fonts. */
271 /* This list shall be expanded as we find more of them. */
272 if ( !unpatented_hinting
)
274 static const char* const trick_names
[] =
276 "DFKaiSho-SB", /* dfkaisb.ttf */
277 "DFKai-SB", /* kaiu.ttf */
278 "HuaTianSongTi?", /* htst3.ttf */
279 "MingLiU", /* mingliu.ttf & mingliu.ttc */
280 "PMingLiU", /* mingliu.ttc */
281 "MingLi43", /* mingli.ttf */
287 /* Note that we only check the face name at the moment; it might */
288 /* be worth to do more checks for a few special cases. */
289 for ( nn
= 0; trick_names
[nn
] != NULL
; nn
++ )
291 if ( ttface
->family_name
&&
292 ft_strstr( ttface
->family_name
, trick_names
[nn
] ) )
294 unpatented_hinting
= 1;
300 ttface
->internal
->ignore_unpatented_hinter
=
301 FT_BOOL( !unpatented_hinting
);
304 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING &&
305 !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
307 /* initialize standard glyph loading routines */
308 TT_Init_Glyph_Loading( face
);
314 error
= TT_Err_Unknown_File_Format
;
319 /*************************************************************************/
325 /* Finalize a given face object. */
328 /* face :: A pointer to the face object to destroy. */
331 tt_face_done( FT_Face ttface
) /* TT_Face */
333 TT_Face face
= (TT_Face
)ttface
;
334 FT_Memory memory
= face
->root
.memory
;
335 FT_Stream stream
= face
->root
.stream
;
337 SFNT_Service sfnt
= (SFNT_Service
)face
->sfnt
;
340 /* for `extended TrueType formats' (i.e. compressed versions) */
341 if ( face
->extra
.finalizer
)
342 face
->extra
.finalizer( face
->extra
.data
);
345 sfnt
->done_face( face
);
347 /* freeing the locations table */
348 tt_face_done_loca( face
);
350 tt_face_free_hdmx( face
);
352 /* freeing the CVT */
353 FT_FREE( face
->cvt
);
356 /* freeing the programs */
357 FT_FRAME_RELEASE( face
->font_program
);
358 FT_FRAME_RELEASE( face
->cvt_program
);
359 face
->font_program_size
= 0;
360 face
->cvt_program_size
= 0;
362 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
363 tt_done_blend( memory
, face
->blend
);
369 /*************************************************************************/
373 /*************************************************************************/
375 #ifdef TT_USE_BYTECODE_INTERPRETER
377 /*************************************************************************/
380 /* tt_size_run_fpgm */
383 /* Run the font program. */
386 /* size :: A handle to the size object. */
389 /* FreeType error code. 0 means success. */
391 FT_LOCAL_DEF( FT_Error
)
392 tt_size_run_fpgm( TT_Size size
)
394 TT_Face face
= (TT_Face
)size
->root
.face
;
399 /* debugging instances have their own context */
401 exec
= size
->context
;
403 exec
= ( (TT_Driver
)FT_FACE_DRIVER( face
) )->context
;
406 return TT_Err_Could_Not_Find_Context
;
408 TT_Load_Context( exec
, face
, size
);
417 exec
->instruction_trap
= FALSE
;
418 exec
->F_dot_P
= 0x10000L
;
421 FT_Size_Metrics
* metrics
= &exec
->metrics
;
422 TT_Size_Metrics
* tt_metrics
= &exec
->tt_metrics
;
427 metrics
->x_scale
= 0;
428 metrics
->y_scale
= 0;
430 tt_metrics
->ppem
= 0;
431 tt_metrics
->scale
= 0;
432 tt_metrics
->ratio
= 0x10000L
;
435 /* allow font program execution */
436 TT_Set_CodeRange( exec
,
439 face
->font_program_size
);
441 /* disable CVT and glyph programs coderange */
442 TT_Clear_CodeRange( exec
, tt_coderange_cvt
);
443 TT_Clear_CodeRange( exec
, tt_coderange_glyph
);
445 if ( face
->font_program_size
> 0 )
447 error
= TT_Goto_CodeRange( exec
, tt_coderange_font
, 0 );
450 error
= face
->interpreter( exec
);
456 TT_Save_Context( exec
, size
);
462 /*************************************************************************/
465 /* tt_size_run_prep */
468 /* Run the control value program. */
471 /* size :: A handle to the size object. */
474 /* FreeType error code. 0 means success. */
476 FT_LOCAL_DEF( FT_Error
)
477 tt_size_run_prep( TT_Size size
)
479 TT_Face face
= (TT_Face
)size
->root
.face
;
484 /* debugging instances have their own context */
486 exec
= size
->context
;
488 exec
= ( (TT_Driver
)FT_FACE_DRIVER( face
) )->context
;
491 return TT_Err_Could_Not_Find_Context
;
493 TT_Load_Context( exec
, face
, size
);
498 exec
->instruction_trap
= FALSE
;
500 TT_Set_CodeRange( exec
,
503 face
->cvt_program_size
);
505 TT_Clear_CodeRange( exec
, tt_coderange_glyph
);
507 if ( face
->cvt_program_size
> 0 )
509 error
= TT_Goto_CodeRange( exec
, tt_coderange_cvt
, 0 );
511 if ( !error
&& !size
->debug
)
512 error
= face
->interpreter( exec
);
517 /* save as default graphics state */
520 TT_Save_Context( exec
, size
);
525 #endif /* TT_USE_BYTECODE_INTERPRETER */
528 #ifdef TT_USE_BYTECODE_INTERPRETER
531 tt_size_done_bytecode( FT_Size ftsize
)
533 TT_Size size
= (TT_Size
)ftsize
;
534 TT_Face face
= (TT_Face
)ftsize
->face
;
535 FT_Memory memory
= face
->root
.memory
;
540 /* the debug context must be deleted by the debugger itself */
541 size
->context
= NULL
;
545 FT_FREE( size
->cvt
);
548 /* free storage area */
549 FT_FREE( size
->storage
);
550 size
->storage_size
= 0;
553 tt_glyphzone_done( &size
->twilight
);
555 FT_FREE( size
->function_defs
);
556 FT_FREE( size
->instruction_defs
);
558 size
->num_function_defs
= 0;
559 size
->max_function_defs
= 0;
560 size
->num_instruction_defs
= 0;
561 size
->max_instruction_defs
= 0;
566 size
->bytecode_ready
= 0;
571 /* Initialize bytecode-related fields in the size object. */
572 /* We do this only if bytecode interpretation is really needed. */
574 tt_size_init_bytecode( FT_Size ftsize
)
577 TT_Size size
= (TT_Size
)ftsize
;
578 TT_Face face
= (TT_Face
)ftsize
->face
;
579 FT_Memory memory
= face
->root
.memory
;
582 FT_UShort n_twilight
;
583 TT_MaxProfile
* maxp
= &face
->max_profile
;
586 size
->bytecode_ready
= 1;
589 size
->max_function_defs
= maxp
->maxFunctionDefs
;
590 size
->max_instruction_defs
= maxp
->maxInstructionDefs
;
592 size
->num_function_defs
= 0;
593 size
->num_instruction_defs
= 0;
598 size
->cvt_size
= face
->cvt_size
;
599 size
->storage_size
= maxp
->maxStorage
;
601 /* Set default metrics */
603 FT_Size_Metrics
* metrics
= &size
->metrics
;
604 TT_Size_Metrics
* metrics2
= &size
->ttmetrics
;
609 metrics2
->rotated
= FALSE
;
610 metrics2
->stretched
= FALSE
;
612 /* set default compensation (all 0) */
613 for ( i
= 0; i
< 4; i
++ )
614 metrics2
->compensations
[i
] = 0;
617 /* allocate function defs, instruction defs, cvt, and storage area */
618 if ( FT_NEW_ARRAY( size
->function_defs
, size
->max_function_defs
) ||
619 FT_NEW_ARRAY( size
->instruction_defs
, size
->max_instruction_defs
) ||
620 FT_NEW_ARRAY( size
->cvt
, size
->cvt_size
) ||
621 FT_NEW_ARRAY( size
->storage
, size
->storage_size
) )
624 /* reserve twilight zone */
625 n_twilight
= maxp
->maxTwilightPoints
;
627 /* there are 4 phantom points (do we need this?) */
630 error
= tt_glyphzone_new( memory
, n_twilight
, 0, &size
->twilight
);
634 size
->twilight
.n_points
= n_twilight
;
636 size
->GS
= tt_default_graphics_state
;
638 /* set `face->interpreter' according to the debug hook present */
640 FT_Library library
= face
->root
.driver
->root
.library
;
643 face
->interpreter
= (TT_Interpreter
)
644 library
->debug_hooks
[FT_DEBUG_HOOK_TRUETYPE
];
645 if ( !face
->interpreter
)
646 face
->interpreter
= (TT_Interpreter
)TT_RunIns
;
649 /* Fine, now run the font program! */
650 error
= tt_size_run_fpgm( size
);
654 tt_size_done_bytecode( ftsize
);
660 FT_LOCAL_DEF( FT_Error
)
661 tt_size_ready_bytecode( TT_Size size
)
663 FT_Error error
= TT_Err_Ok
;
666 if ( !size
->bytecode_ready
)
668 error
= tt_size_init_bytecode( (FT_Size
)size
);
673 /* rescale CVT when needed */
674 if ( !size
->cvt_ready
)
677 TT_Face face
= (TT_Face
) size
->root
.face
;
680 /* Scale the cvt values to the new ppem. */
681 /* We use by default the y ppem to scale the CVT. */
682 for ( i
= 0; i
< size
->cvt_size
; i
++ )
683 size
->cvt
[i
] = FT_MulFix( face
->cvt
[i
], size
->ttmetrics
.scale
);
685 /* all twilight points are originally zero */
686 for ( i
= 0; i
< (FT_UInt
)size
->twilight
.n_points
; i
++ )
688 size
->twilight
.org
[i
].x
= 0;
689 size
->twilight
.org
[i
].y
= 0;
690 size
->twilight
.cur
[i
].x
= 0;
691 size
->twilight
.cur
[i
].y
= 0;
694 /* clear storage area */
695 for ( i
= 0; i
< (FT_UInt
)size
->storage_size
; i
++ )
696 size
->storage
[i
] = 0;
698 size
->GS
= tt_default_graphics_state
;
700 error
= tt_size_run_prep( size
);
709 #endif /* TT_USE_BYTECODE_INTERPRETER */
712 /*************************************************************************/
718 /* Initialize a new TrueType size object. */
721 /* size :: A handle to the size object. */
724 /* FreeType error code. 0 means success. */
726 FT_LOCAL_DEF( FT_Error
)
727 tt_size_init( FT_Size ttsize
) /* TT_Size */
729 TT_Size size
= (TT_Size
)ttsize
;
730 FT_Error error
= TT_Err_Ok
;
732 #ifdef TT_USE_BYTECODE_INTERPRETER
733 size
->bytecode_ready
= 0;
737 size
->ttmetrics
.valid
= FALSE
;
738 size
->strike_index
= 0xFFFFFFFFUL
;
744 /*************************************************************************/
750 /* The TrueType size object finalizer. */
753 /* size :: A handle to the target size object. */
756 tt_size_done( FT_Size ttsize
) /* TT_Size */
758 TT_Size size
= (TT_Size
)ttsize
;
761 #ifdef TT_USE_BYTECODE_INTERPRETER
762 if ( size
->bytecode_ready
)
763 tt_size_done_bytecode( ttsize
);
766 size
->ttmetrics
.valid
= FALSE
;
770 /*************************************************************************/
776 /* Reset a TrueType size when resolutions and character dimensions */
777 /* have been changed. */
780 /* size :: A handle to the target size object. */
782 FT_LOCAL_DEF( FT_Error
)
783 tt_size_reset( TT_Size size
)
786 FT_Error error
= TT_Err_Ok
;
787 FT_Size_Metrics
* metrics
;
790 size
->ttmetrics
.valid
= FALSE
;
792 face
= (TT_Face
)size
->root
.face
;
794 metrics
= &size
->metrics
;
796 /* copy the result from base layer */
797 *metrics
= size
->root
.metrics
;
799 if ( metrics
->x_ppem
< 1 || metrics
->y_ppem
< 1 )
800 return TT_Err_Invalid_PPem
;
802 /* This bit flag, if set, indicates that the ppems must be */
803 /* rounded to integers. Nearly all TrueType fonts have this bit */
804 /* set, as hinting won't work really well otherwise. */
806 if ( face
->header
.Flags
& 8 )
808 metrics
->x_scale
= FT_DivFix( metrics
->x_ppem
<< 6,
809 face
->root
.units_per_EM
);
810 metrics
->y_scale
= FT_DivFix( metrics
->y_ppem
<< 6,
811 face
->root
.units_per_EM
);
814 FT_PIX_ROUND( FT_MulFix( face
->root
.ascender
, metrics
->y_scale
) );
816 FT_PIX_ROUND( FT_MulFix( face
->root
.descender
, metrics
->y_scale
) );
818 FT_PIX_ROUND( FT_MulFix( face
->root
.height
, metrics
->y_scale
) );
819 metrics
->max_advance
=
820 FT_PIX_ROUND( FT_MulFix( face
->root
.max_advance_width
,
821 metrics
->x_scale
) );
824 /* compute new transformation */
825 if ( metrics
->x_ppem
>= metrics
->y_ppem
)
827 size
->ttmetrics
.scale
= metrics
->x_scale
;
828 size
->ttmetrics
.ppem
= metrics
->x_ppem
;
829 size
->ttmetrics
.x_ratio
= 0x10000L
;
830 size
->ttmetrics
.y_ratio
= FT_MulDiv( metrics
->y_ppem
,
836 size
->ttmetrics
.scale
= metrics
->y_scale
;
837 size
->ttmetrics
.ppem
= metrics
->y_ppem
;
838 size
->ttmetrics
.x_ratio
= FT_MulDiv( metrics
->x_ppem
,
841 size
->ttmetrics
.y_ratio
= 0x10000L
;
844 #ifdef TT_USE_BYTECODE_INTERPRETER
846 #endif /* TT_USE_BYTECODE_INTERPRETER */
849 size
->ttmetrics
.valid
= TRUE
;
855 /*************************************************************************/
861 /* Initialize a given TrueType driver object. */
864 /* driver :: A handle to the target driver object. */
867 /* FreeType error code. 0 means success. */
869 FT_LOCAL_DEF( FT_Error
)
870 tt_driver_init( FT_Module ttdriver
) /* TT_Driver */
873 #ifdef TT_USE_BYTECODE_INTERPRETER
875 TT_Driver driver
= (TT_Driver
)ttdriver
;
878 if ( !TT_New_Context( driver
) )
879 return TT_Err_Could_Not_Find_Context
;
883 FT_UNUSED( ttdriver
);
891 /*************************************************************************/
897 /* Finalize a given TrueType driver. */
900 /* driver :: A handle to the target TrueType driver. */
903 tt_driver_done( FT_Module ttdriver
) /* TT_Driver */
905 #ifdef TT_USE_BYTECODE_INTERPRETER
906 TT_Driver driver
= (TT_Driver
)ttdriver
;
909 /* destroy the execution context */
910 if ( driver
->context
)
912 TT_Done_Context( driver
->context
);
913 driver
->context
= NULL
;
916 FT_UNUSED( ttdriver
);
922 /*************************************************************************/
928 /* Initialize a new slot object. */
931 /* slot :: A handle to the slot object. */
934 /* FreeType error code. 0 means success. */
936 FT_LOCAL_DEF( FT_Error
)
937 tt_slot_init( FT_GlyphSlot slot
)
939 return FT_GlyphLoader_CreateExtra( slot
->internal
->loader
);