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
) ||
234 tt_face_load_fpgm( face
, stream
) ||
235 tt_face_load_prep( face
, stream
);
240 error
= tt_face_load_loca( face
, stream
) ||
241 tt_face_load_cvt( face
, stream
) ||
242 tt_face_load_fpgm( face
, stream
) ||
243 tt_face_load_prep( face
, stream
);
249 #if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
250 !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
253 FT_Bool unpatented_hinting
;
257 /* Determine whether unpatented hinting is to be used for this face. */
258 unpatented_hinting
= FT_BOOL
259 ( library
->debug_hooks
[FT_DEBUG_HOOK_UNPATENTED_HINTING
] != NULL
);
261 for ( i
= 0; i
< num_params
&& !face
->unpatented_hinting
; i
++ )
262 if ( params
[i
].tag
== FT_PARAM_TAG_UNPATENTED_HINTING
)
263 unpatented_hinting
= TRUE
;
265 /* Compare the face with a list of well-known `tricky' fonts. */
266 /* This list shall be expanded as we find more of them. */
267 if ( !unpatented_hinting
)
269 static const char* const trick_names
[] =
271 "DFKaiSho-SB", /* dfkaisb.ttf */
272 "DFKai-SB", /* kaiu.ttf */
273 "HuaTianSongTi?", /* htst3.ttf */
274 "MingLiU", /* mingliu.ttf & mingliu.ttc */
275 "PMingLiU", /* mingliu.ttc */
276 "MingLi43", /* mingli.ttf */
282 /* Note that we only check the face name at the moment; it might */
283 /* be worth to do more checks for a few special cases. */
284 for ( nn
= 0; trick_names
[nn
] != NULL
; nn
++ )
286 if ( ttface
->family_name
&&
287 ft_strstr( ttface
->family_name
, trick_names
[nn
] ) )
289 unpatented_hinting
= 1;
295 ttface
->internal
->ignore_unpatented_hinter
=
296 FT_BOOL( !unpatented_hinting
);
299 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING &&
300 !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
302 /* initialize standard glyph loading routines */
303 TT_Init_Glyph_Loading( face
);
309 error
= TT_Err_Unknown_File_Format
;
314 /*************************************************************************/
320 /* Finalize a given face object. */
323 /* face :: A pointer to the face object to destroy. */
326 tt_face_done( FT_Face ttface
) /* TT_Face */
328 TT_Face face
= (TT_Face
)ttface
;
329 FT_Memory memory
= face
->root
.memory
;
330 FT_Stream stream
= face
->root
.stream
;
332 SFNT_Service sfnt
= (SFNT_Service
)face
->sfnt
;
335 /* for `extended TrueType formats' (i.e. compressed versions) */
336 if ( face
->extra
.finalizer
)
337 face
->extra
.finalizer( face
->extra
.data
);
340 sfnt
->done_face( face
);
342 /* freeing the locations table */
343 tt_face_done_loca( face
);
345 tt_face_free_hdmx( face
);
347 /* freeing the CVT */
348 FT_FREE( face
->cvt
);
351 /* freeing the programs */
352 FT_FRAME_RELEASE( face
->font_program
);
353 FT_FRAME_RELEASE( face
->cvt_program
);
354 face
->font_program_size
= 0;
355 face
->cvt_program_size
= 0;
357 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
358 tt_done_blend( memory
, face
->blend
);
364 /*************************************************************************/
368 /*************************************************************************/
370 #ifdef TT_USE_BYTECODE_INTERPRETER
372 /*************************************************************************/
375 /* tt_size_run_fpgm */
378 /* Run the font program. */
381 /* size :: A handle to the size object. */
384 /* FreeType error code. 0 means success. */
386 FT_LOCAL_DEF( FT_Error
)
387 tt_size_run_fpgm( TT_Size size
)
389 TT_Face face
= (TT_Face
)size
->root
.face
;
394 /* debugging instances have their own context */
396 exec
= size
->context
;
398 exec
= ( (TT_Driver
)FT_FACE_DRIVER( face
) )->context
;
401 return TT_Err_Could_Not_Find_Context
;
403 TT_Load_Context( exec
, face
, size
);
412 exec
->instruction_trap
= FALSE
;
413 exec
->F_dot_P
= 0x10000L
;
416 FT_Size_Metrics
* metrics
= &exec
->metrics
;
417 TT_Size_Metrics
* tt_metrics
= &exec
->tt_metrics
;
422 metrics
->x_scale
= 0;
423 metrics
->y_scale
= 0;
425 tt_metrics
->ppem
= 0;
426 tt_metrics
->scale
= 0;
427 tt_metrics
->ratio
= 0x10000L
;
430 /* allow font program execution */
431 TT_Set_CodeRange( exec
,
434 face
->font_program_size
);
436 /* disable CVT and glyph programs coderange */
437 TT_Clear_CodeRange( exec
, tt_coderange_cvt
);
438 TT_Clear_CodeRange( exec
, tt_coderange_glyph
);
440 if ( face
->font_program_size
> 0 )
442 error
= TT_Goto_CodeRange( exec
, tt_coderange_font
, 0 );
445 error
= face
->interpreter( exec
);
451 TT_Save_Context( exec
, size
);
457 /*************************************************************************/
460 /* tt_size_run_prep */
463 /* Run the control value program. */
466 /* size :: A handle to the size object. */
469 /* FreeType error code. 0 means success. */
471 FT_LOCAL_DEF( FT_Error
)
472 tt_size_run_prep( TT_Size size
)
474 TT_Face face
= (TT_Face
)size
->root
.face
;
479 /* debugging instances have their own context */
481 exec
= size
->context
;
483 exec
= ( (TT_Driver
)FT_FACE_DRIVER( face
) )->context
;
486 return TT_Err_Could_Not_Find_Context
;
488 TT_Load_Context( exec
, face
, size
);
493 exec
->instruction_trap
= FALSE
;
495 TT_Set_CodeRange( exec
,
498 face
->cvt_program_size
);
500 TT_Clear_CodeRange( exec
, tt_coderange_glyph
);
502 if ( face
->cvt_program_size
> 0 )
504 error
= TT_Goto_CodeRange( exec
, tt_coderange_cvt
, 0 );
506 if ( !error
&& !size
->debug
)
507 error
= face
->interpreter( exec
);
512 /* save as default graphics state */
515 TT_Save_Context( exec
, size
);
520 #endif /* TT_USE_BYTECODE_INTERPRETER */
523 #ifdef TT_USE_BYTECODE_INTERPRETER
526 tt_size_done_bytecode( FT_Size ftsize
)
528 TT_Size size
= (TT_Size
)ftsize
;
529 TT_Face face
= (TT_Face
)ftsize
->face
;
530 FT_Memory memory
= face
->root
.memory
;
535 /* the debug context must be deleted by the debugger itself */
536 size
->context
= NULL
;
540 FT_FREE( size
->cvt
);
543 /* free storage area */
544 FT_FREE( size
->storage
);
545 size
->storage_size
= 0;
548 tt_glyphzone_done( &size
->twilight
);
550 FT_FREE( size
->function_defs
);
551 FT_FREE( size
->instruction_defs
);
553 size
->num_function_defs
= 0;
554 size
->max_function_defs
= 0;
555 size
->num_instruction_defs
= 0;
556 size
->max_instruction_defs
= 0;
561 size
->bytecode_ready
= 0;
566 /* Initialize bytecode-related fields in the size object. */
567 /* We do this only if bytecode interpretation is really needed. */
569 tt_size_init_bytecode( FT_Size ftsize
)
572 TT_Size size
= (TT_Size
)ftsize
;
573 TT_Face face
= (TT_Face
)ftsize
->face
;
574 FT_Memory memory
= face
->root
.memory
;
577 FT_UShort n_twilight
;
578 TT_MaxProfile
* maxp
= &face
->max_profile
;
581 size
->bytecode_ready
= 1;
584 size
->max_function_defs
= maxp
->maxFunctionDefs
;
585 size
->max_instruction_defs
= maxp
->maxInstructionDefs
;
587 size
->num_function_defs
= 0;
588 size
->num_instruction_defs
= 0;
593 size
->cvt_size
= face
->cvt_size
;
594 size
->storage_size
= maxp
->maxStorage
;
596 /* Set default metrics */
598 FT_Size_Metrics
* metrics
= &size
->metrics
;
599 TT_Size_Metrics
* metrics2
= &size
->ttmetrics
;
604 metrics2
->rotated
= FALSE
;
605 metrics2
->stretched
= FALSE
;
607 /* set default compensation (all 0) */
608 for ( i
= 0; i
< 4; i
++ )
609 metrics2
->compensations
[i
] = 0;
612 /* allocate function defs, instruction defs, cvt, and storage area */
613 if ( FT_NEW_ARRAY( size
->function_defs
, size
->max_function_defs
) ||
614 FT_NEW_ARRAY( size
->instruction_defs
, size
->max_instruction_defs
) ||
615 FT_NEW_ARRAY( size
->cvt
, size
->cvt_size
) ||
616 FT_NEW_ARRAY( size
->storage
, size
->storage_size
) )
619 /* reserve twilight zone */
620 n_twilight
= maxp
->maxTwilightPoints
;
622 /* there are 4 phantom points (do we need this?) */
625 error
= tt_glyphzone_new( memory
, n_twilight
, 0, &size
->twilight
);
629 size
->twilight
.n_points
= n_twilight
;
631 size
->GS
= tt_default_graphics_state
;
633 /* set `face->interpreter' according to the debug hook present */
635 FT_Library library
= face
->root
.driver
->root
.library
;
638 face
->interpreter
= (TT_Interpreter
)
639 library
->debug_hooks
[FT_DEBUG_HOOK_TRUETYPE
];
640 if ( !face
->interpreter
)
641 face
->interpreter
= (TT_Interpreter
)TT_RunIns
;
644 /* Fine, now run the font program! */
645 error
= tt_size_run_fpgm( size
);
649 tt_size_done_bytecode( ftsize
);
655 FT_LOCAL_DEF( FT_Error
)
656 tt_size_ready_bytecode( TT_Size size
)
658 FT_Error error
= TT_Err_Ok
;
661 if ( !size
->bytecode_ready
)
663 error
= tt_size_init_bytecode( (FT_Size
)size
);
668 /* rescale CVT when needed */
669 if ( !size
->cvt_ready
)
672 TT_Face face
= (TT_Face
) size
->root
.face
;
675 /* Scale the cvt values to the new ppem. */
676 /* We use by default the y ppem to scale the CVT. */
677 for ( i
= 0; i
< size
->cvt_size
; i
++ )
678 size
->cvt
[i
] = FT_MulFix( face
->cvt
[i
], size
->ttmetrics
.scale
);
680 /* all twilight points are originally zero */
681 for ( i
= 0; i
< (FT_UInt
)size
->twilight
.n_points
; i
++ )
683 size
->twilight
.org
[i
].x
= 0;
684 size
->twilight
.org
[i
].y
= 0;
685 size
->twilight
.cur
[i
].x
= 0;
686 size
->twilight
.cur
[i
].y
= 0;
689 /* clear storage area */
690 for ( i
= 0; i
< (FT_UInt
)size
->storage_size
; i
++ )
691 size
->storage
[i
] = 0;
693 size
->GS
= tt_default_graphics_state
;
695 error
= tt_size_run_prep( size
);
703 #endif /* TT_USE_BYTECODE_INTERPRETER */
706 /*************************************************************************/
712 /* Initialize a new TrueType size object. */
715 /* size :: A handle to the size object. */
718 /* FreeType error code. 0 means success. */
720 FT_LOCAL_DEF( FT_Error
)
721 tt_size_init( FT_Size ttsize
) /* TT_Size */
723 TT_Size size
= (TT_Size
)ttsize
;
724 FT_Error error
= TT_Err_Ok
;
726 #ifdef TT_USE_BYTECODE_INTERPRETER
727 size
->bytecode_ready
= 0;
731 size
->ttmetrics
.valid
= FALSE
;
732 size
->strike_index
= 0xFFFFFFFFUL
;
738 /*************************************************************************/
744 /* The TrueType size object finalizer. */
747 /* size :: A handle to the target size object. */
750 tt_size_done( FT_Size ttsize
) /* TT_Size */
752 TT_Size size
= (TT_Size
)ttsize
;
755 #ifdef TT_USE_BYTECODE_INTERPRETER
756 if ( size
->bytecode_ready
)
757 tt_size_done_bytecode( ttsize
);
760 size
->ttmetrics
.valid
= FALSE
;
764 /*************************************************************************/
770 /* Reset a TrueType size when resolutions and character dimensions */
771 /* have been changed. */
774 /* size :: A handle to the target size object. */
776 FT_LOCAL_DEF( FT_Error
)
777 tt_size_reset( TT_Size size
)
780 FT_Error error
= TT_Err_Ok
;
781 FT_Size_Metrics
* metrics
;
784 size
->ttmetrics
.valid
= FALSE
;
786 face
= (TT_Face
)size
->root
.face
;
788 metrics
= &size
->metrics
;
790 /* copy the result from base layer */
791 *metrics
= size
->root
.metrics
;
793 if ( metrics
->x_ppem
< 1 || metrics
->y_ppem
< 1 )
794 return TT_Err_Invalid_PPem
;
796 /* This bit flag, if set, indicates that the ppems must be */
797 /* rounded to integers. Nearly all TrueType fonts have this bit */
798 /* set, as hinting won't work really well otherwise. */
800 if ( face
->header
.Flags
& 8 )
802 metrics
->x_scale
= FT_DivFix( metrics
->x_ppem
<< 6,
803 face
->root
.units_per_EM
);
804 metrics
->y_scale
= FT_DivFix( metrics
->y_ppem
<< 6,
805 face
->root
.units_per_EM
);
808 FT_PIX_ROUND( FT_MulFix( face
->root
.ascender
, metrics
->y_scale
) );
810 FT_PIX_ROUND( FT_MulFix( face
->root
.descender
, metrics
->y_scale
) );
812 FT_PIX_ROUND( FT_MulFix( face
->root
.height
, metrics
->y_scale
) );
813 metrics
->max_advance
=
814 FT_PIX_ROUND( FT_MulFix( face
->root
.max_advance_width
,
815 metrics
->x_scale
) );
818 /* compute new transformation */
819 if ( metrics
->x_ppem
>= metrics
->y_ppem
)
821 size
->ttmetrics
.scale
= metrics
->x_scale
;
822 size
->ttmetrics
.ppem
= metrics
->x_ppem
;
823 size
->ttmetrics
.x_ratio
= 0x10000L
;
824 size
->ttmetrics
.y_ratio
= FT_MulDiv( metrics
->y_ppem
,
830 size
->ttmetrics
.scale
= metrics
->y_scale
;
831 size
->ttmetrics
.ppem
= metrics
->y_ppem
;
832 size
->ttmetrics
.x_ratio
= FT_MulDiv( metrics
->x_ppem
,
835 size
->ttmetrics
.y_ratio
= 0x10000L
;
838 #ifdef TT_USE_BYTECODE_INTERPRETER
840 #endif /* TT_USE_BYTECODE_INTERPRETER */
843 size
->ttmetrics
.valid
= TRUE
;
849 /*************************************************************************/
855 /* Initialize a given TrueType driver object. */
858 /* driver :: A handle to the target driver object. */
861 /* FreeType error code. 0 means success. */
863 FT_LOCAL_DEF( FT_Error
)
864 tt_driver_init( FT_Module ttdriver
) /* TT_Driver */
867 #ifdef TT_USE_BYTECODE_INTERPRETER
869 TT_Driver driver
= (TT_Driver
)ttdriver
;
872 if ( !TT_New_Context( driver
) )
873 return TT_Err_Could_Not_Find_Context
;
877 FT_UNUSED( ttdriver
);
885 /*************************************************************************/
891 /* Finalize a given TrueType driver. */
894 /* driver :: A handle to the target TrueType driver. */
897 tt_driver_done( FT_Module ttdriver
) /* TT_Driver */
899 #ifdef TT_USE_BYTECODE_INTERPRETER
900 TT_Driver driver
= (TT_Driver
)ttdriver
;
903 /* destroy the execution context */
904 if ( driver
->context
)
906 TT_Done_Context( driver
->context
);
907 driver
->context
= NULL
;
910 FT_UNUSED( ttdriver
);
916 /*************************************************************************/
922 /* Initialize a new slot object. */
925 /* slot :: A handle to the slot object. */
928 /* FreeType error code. 0 means success. */
930 FT_LOCAL_DEF( FT_Error
)
931 tt_slot_init( FT_GlyphSlot slot
)
933 return FT_GlyphLoader_CreateExtra( slot
->internal
->loader
);