1 /***************************************************************************/
5 /* Objects manager (body). */
7 /* Copyright 1996-2018 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_STREAM_H
22 #include FT_TRUETYPE_TAGS_H
23 #include FT_INTERNAL_SFNT_H
31 #ifdef TT_USE_BYTECODE_INTERPRETER
35 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
39 /*************************************************************************/
41 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
42 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
43 /* messages during execution. */
46 #define FT_COMPONENT trace_ttobjs
49 #ifdef TT_USE_BYTECODE_INTERPRETER
51 /*************************************************************************/
53 /* GLYPH ZONE FUNCTIONS */
55 /*************************************************************************/
58 /*************************************************************************/
61 /* tt_glyphzone_done */
64 /* Deallocate a glyph zone. */
67 /* zone :: A pointer to the target glyph zone. */
70 tt_glyphzone_done( TT_GlyphZone zone
)
72 FT_Memory memory
= zone
->memory
;
77 FT_FREE( zone
->contours
);
78 FT_FREE( zone
->tags
);
81 FT_FREE( zone
->orus
);
83 zone
->max_points
= zone
->n_points
= 0;
84 zone
->max_contours
= zone
->n_contours
= 0;
90 /*************************************************************************/
93 /* tt_glyphzone_new */
96 /* Allocate a new glyph zone. */
99 /* memory :: A handle to the current memory object. */
101 /* maxPoints :: The capacity of glyph zone in points. */
103 /* maxContours :: The capacity of glyph zone in contours. */
106 /* zone :: A pointer to the target glyph zone record. */
109 /* FreeType error code. 0 means success. */
111 FT_LOCAL_DEF( FT_Error
)
112 tt_glyphzone_new( FT_Memory memory
,
114 FT_Short maxContours
,
121 zone
->memory
= memory
;
123 if ( FT_NEW_ARRAY( zone
->org
, maxPoints
) ||
124 FT_NEW_ARRAY( zone
->cur
, maxPoints
) ||
125 FT_NEW_ARRAY( zone
->orus
, maxPoints
) ||
126 FT_NEW_ARRAY( zone
->tags
, maxPoints
) ||
127 FT_NEW_ARRAY( zone
->contours
, maxContours
) )
129 tt_glyphzone_done( zone
);
133 zone
->max_points
= maxPoints
;
134 zone
->max_contours
= maxContours
;
139 #endif /* TT_USE_BYTECODE_INTERPRETER */
142 /* Compare the face with a list of well-known `tricky' fonts. */
143 /* This list shall be expanded as we find more of them. */
146 tt_check_trickyness_family( FT_String
* name
)
149 #define TRICK_NAMES_MAX_CHARACTERS 19
150 #define TRICK_NAMES_COUNT 23
152 static const char trick_names
[TRICK_NAMES_COUNT
]
153 [TRICK_NAMES_MAX_CHARACTERS
+ 1] =
156 PostScript names are given in brackets if they differ from the
157 family name. The version numbers, together with the copyright or
158 release year data, are taken from fonts available to the
161 Note that later versions of the fonts might be no longer tricky;
162 for example, `MingLiU' version 7.00 (file `mingliu.ttc' from
163 Windows 7) is an ordinary TTC with non-tricky subfonts.
166 "cpop", /* dftt-p7.ttf; version 1.00, 1992 [DLJGyShoMedium] */
167 "DFGirl-W6-WIN-BF", /* dftt-h6.ttf; version 1.00, 1993 */
168 "DFGothic-EB", /* DynaLab Inc. 1992-1995 */
169 "DFGyoSho-Lt", /* DynaLab Inc. 1992-1995 */
170 "DFHSGothic-W5", /* DynaLab Inc. 1992-1995 */
171 "DFHSMincho-W3", /* DynaLab Inc. 1992-1995 */
172 "DFHSMincho-W7", /* DynaLab Inc. 1992-1995 */
173 "DFKaiSho-SB", /* dfkaisb.ttf */
175 "DFKai-SB", /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */
176 "DLC", /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */
177 /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */
178 "DLCHayMedium", /* dftt-b5.ttf; version 1.00, 1993 */
179 "DLCHayBold", /* dftt-b7.ttf; version 1.00, 1993 */
180 "DLCKaiMedium", /* dftt-k5.ttf; version 1.00, 1992 */
181 "DLCLiShu", /* dftt-l5.ttf; version 1.00, 1992 */
182 "DLCRoundBold", /* dftt-r7.ttf; version 1.00, 1993 */
183 "HuaTianKaiTi?", /* htkt2.ttf */
184 "HuaTianSongTi?", /* htst3.ttf */
185 "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */
186 /* iicore.ttf; version 0.07, 2007 [Ming] */
187 "MingLiU", /* mingliu.ttf */
188 /* mingliu.ttc; version 3.21, 2001 */
189 "MingMedium", /* dftt-m5.ttf; version 1.00, 1993 [DLCMingMedium] */
190 "PMingLiU", /* mingliu.ttc; version 3.21, 2001 */
191 "MingLi43", /* mingli.ttf; version 1.00, 1992 */
197 for ( nn
= 0; nn
< TRICK_NAMES_COUNT
; nn
++ )
198 if ( ft_strstr( name
, trick_names
[nn
] ) )
205 /* XXX: This function should be in the `sfnt' module. */
207 /* Some PDF generators clear the checksums in the TrueType header table. */
208 /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */
209 /* Printer clears the entries for subsetted subtables. We thus have to */
210 /* recalculate the checksums where necessary. */
213 tt_synth_sfnt_checksum( FT_Stream stream
,
217 FT_UInt32 checksum
= 0;
221 if ( FT_FRAME_ENTER( length
) )
224 for ( ; length
> 3; length
-= 4 )
225 checksum
+= (FT_UInt32
)FT_GET_ULONG();
227 for ( i
= 3; length
> 0; length
--, i
-- )
228 checksum
+= (FT_UInt32
)FT_GET_BYTE() << ( i
* 8 );
236 /* XXX: This function should be in the `sfnt' module. */
239 tt_get_sfnt_checksum( TT_Face face
,
242 #if 0 /* if we believe the written value, use following part. */
243 if ( face
->dir_tables
[i
].CheckSum
)
244 return face
->dir_tables
[i
].CheckSum
;
247 if ( !face
->goto_table
)
250 if ( face
->goto_table( face
,
251 face
->dir_tables
[i
].Tag
,
256 return (FT_ULong
)tt_synth_sfnt_checksum( face
->root
.stream
,
257 face
->dir_tables
[i
].Length
);
261 typedef struct tt_sfnt_id_rec_
270 tt_check_trickyness_sfnt_ids( TT_Face face
)
272 #define TRICK_SFNT_IDS_PER_FACE 3
273 #define TRICK_SFNT_IDS_NUM_FACES 26
275 static const tt_sfnt_id_rec sfnt_id
[TRICK_SFNT_IDS_NUM_FACES
]
276 [TRICK_SFNT_IDS_PER_FACE
] = {
278 #define TRICK_SFNT_ID_cvt 0
279 #define TRICK_SFNT_ID_fpgm 1
280 #define TRICK_SFNT_ID_prep 2
283 { 0x05BCF058UL
, 0x000002E4UL
}, /* cvt */
284 { 0x28233BF1UL
, 0x000087C4UL
}, /* fpgm */
285 { 0xA344A1EAUL
, 0x000001E1UL
} /* prep */
287 { /* MingLiU 1996- */
288 { 0x05BCF058UL
, 0x000002E4UL
}, /* cvt */
289 { 0x28233BF1UL
, 0x000087C4UL
}, /* fpgm */
290 { 0xA344A1EBUL
, 0x000001E1UL
} /* prep */
293 { 0x12C3EBB2UL
, 0x00000350UL
}, /* cvt */
294 { 0xB680EE64UL
, 0x000087A7UL
}, /* fpgm */
295 { 0xCE939563UL
, 0x00000758UL
} /* prep */
298 { 0x11E5EAD4UL
, 0x00000350UL
}, /* cvt */
299 { 0xCE5956E9UL
, 0x0000BC85UL
}, /* fpgm */
300 { 0x8272F416UL
, 0x00000045UL
} /* prep */
302 { /* DFHSGothic-W5 */
303 { 0x1262EB4EUL
, 0x00000350UL
}, /* cvt */
304 { 0xE86A5D64UL
, 0x00007940UL
}, /* fpgm */
305 { 0x7850F729UL
, 0x000005FFUL
} /* prep */
307 { /* DFHSMincho-W3 */
308 { 0x122DEB0AUL
, 0x00000350UL
}, /* cvt */
309 { 0x3D16328AUL
, 0x0000859BUL
}, /* fpgm */
310 { 0xA93FC33BUL
, 0x000002CBUL
} /* prep */
312 { /* DFHSMincho-W7 */
313 { 0x125FEB26UL
, 0x00000350UL
}, /* cvt */
314 { 0xA5ACC982UL
, 0x00007EE1UL
}, /* fpgm */
315 { 0x90999196UL
, 0x0000041FUL
} /* prep */
318 { 0x11E5EAD4UL
, 0x00000350UL
}, /* cvt */
319 { 0x5A30CA3BUL
, 0x00009063UL
}, /* fpgm */
320 { 0x13A42602UL
, 0x0000007EUL
} /* prep */
322 { /* DFKaiShu, variant */
323 { 0x11E5EAD4UL
, 0x00000350UL
}, /* cvt */
324 { 0xA6E78C01UL
, 0x00008998UL
}, /* fpgm */
325 { 0x13A42602UL
, 0x0000007EUL
} /* prep */
328 { 0x07DCF546UL
, 0x00000308UL
}, /* cvt */
329 { 0x40FE7C90UL
, 0x00008E2AUL
}, /* fpgm */
330 { 0x608174B5UL
, 0x0000007AUL
} /* prep */
333 { 0xEB891238UL
, 0x00000308UL
}, /* cvt */
334 { 0xD2E4DCD4UL
, 0x0000676FUL
}, /* fpgm */
335 { 0x8EA5F293UL
, 0x000003B8UL
} /* prep */
338 { 0xFFFBFFFCUL
, 0x00000008UL
}, /* cvt */
339 { 0x9C9E48B8UL
, 0x0000BEA2UL
}, /* fpgm */
340 { 0x70020112UL
, 0x00000008UL
} /* prep */
342 { /* HuaTianSongTi */
343 { 0xFFFBFFFCUL
, 0x00000008UL
}, /* cvt */
344 { 0x0A5A0483UL
, 0x00017C39UL
}, /* fpgm */
345 { 0x70020112UL
, 0x00000008UL
} /* prep */
347 { /* NEC fadpop7.ttf */
348 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
349 { 0x40C92555UL
, 0x000000E5UL
}, /* fpgm */
350 { 0xA39B58E3UL
, 0x0000117CUL
} /* prep */
352 { /* NEC fadrei5.ttf */
353 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
354 { 0x33C41652UL
, 0x000000E5UL
}, /* fpgm */
355 { 0x26D6C52AUL
, 0x00000F6AUL
} /* prep */
357 { /* NEC fangot7.ttf */
358 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
359 { 0x6DB1651DUL
, 0x0000019DUL
}, /* fpgm */
360 { 0x6C6E4B03UL
, 0x00002492UL
} /* prep */
362 { /* NEC fangyo5.ttf */
363 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
364 { 0x40C92555UL
, 0x000000E5UL
}, /* fpgm */
365 { 0xDE51FAD0UL
, 0x0000117CUL
} /* prep */
367 { /* NEC fankyo5.ttf */
368 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
369 { 0x85E47664UL
, 0x000000E5UL
}, /* fpgm */
370 { 0xA6C62831UL
, 0x00001CAAUL
} /* prep */
372 { /* NEC fanrgo5.ttf */
373 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
374 { 0x2D891CFDUL
, 0x0000019DUL
}, /* fpgm */
375 { 0xA0604633UL
, 0x00001DE8UL
} /* prep */
377 { /* NEC fangot5.ttc */
378 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
379 { 0x40AA774CUL
, 0x000001CBUL
}, /* fpgm */
380 { 0x9B5CAA96UL
, 0x00001F9AUL
} /* prep */
382 { /* NEC fanmin3.ttc */
383 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
384 { 0x0D3DE9CBUL
, 0x00000141UL
}, /* fpgm */
385 { 0xD4127766UL
, 0x00002280UL
} /* prep */
387 { /* NEC FA-Gothic, 1996 */
388 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
389 { 0x4A692698UL
, 0x000001F0UL
}, /* fpgm */
390 { 0x340D4346UL
, 0x00001FCAUL
} /* prep */
392 { /* NEC FA-Minchou, 1996 */
393 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
394 { 0xCD34C604UL
, 0x00000166UL
}, /* fpgm */
395 { 0x6CF31046UL
, 0x000022B0UL
} /* prep */
397 { /* NEC FA-RoundGothicB, 1996 */
398 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
399 { 0x5DA75315UL
, 0x0000019DUL
}, /* fpgm */
400 { 0x40745A5FUL
, 0x000022E0UL
} /* prep */
402 { /* NEC FA-RoundGothicM, 1996 */
403 { 0x00000000UL
, 0x00000000UL
}, /* cvt */
404 { 0xF055FC48UL
, 0x000001C2UL
}, /* fpgm */
405 { 0x3900DED3UL
, 0x00001E18UL
} /* prep */
407 { /* MINGLI.TTF, 1992 */
408 { 0x00170003UL
, 0x00000060UL
}, /* cvt */
409 { 0xDBB4306EUL
, 0x000058AAUL
}, /* fpgm */
410 { 0xD643482AUL
, 0x00000035UL
} /* prep */
415 int num_matched_ids
[TRICK_SFNT_IDS_NUM_FACES
];
416 FT_Bool has_cvt
, has_fpgm
, has_prep
;
421 FT_MEM_SET( num_matched_ids
, 0,
422 sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES
);
427 for ( i
= 0; i
< face
->num_tables
; i
++ )
431 switch( face
->dir_tables
[i
].Tag
)
434 k
= TRICK_SFNT_ID_cvt
;
439 k
= TRICK_SFNT_ID_fpgm
;
444 k
= TRICK_SFNT_ID_prep
;
452 for ( j
= 0; j
< TRICK_SFNT_IDS_NUM_FACES
; j
++ )
453 if ( face
->dir_tables
[i
].Length
== sfnt_id
[j
][k
].Length
)
456 checksum
= tt_get_sfnt_checksum( face
, i
);
458 if ( sfnt_id
[j
][k
].CheckSum
== checksum
)
459 num_matched_ids
[j
]++;
461 if ( num_matched_ids
[j
] == TRICK_SFNT_IDS_PER_FACE
)
466 for ( j
= 0; j
< TRICK_SFNT_IDS_NUM_FACES
; j
++ )
468 if ( !has_cvt
&& !sfnt_id
[j
][TRICK_SFNT_ID_cvt
].Length
)
469 num_matched_ids
[j
]++;
470 if ( !has_fpgm
&& !sfnt_id
[j
][TRICK_SFNT_ID_fpgm
].Length
)
471 num_matched_ids
[j
]++;
472 if ( !has_prep
&& !sfnt_id
[j
][TRICK_SFNT_ID_prep
].Length
)
473 num_matched_ids
[j
]++;
474 if ( num_matched_ids
[j
] == TRICK_SFNT_IDS_PER_FACE
)
483 tt_check_trickyness( FT_Face face
)
488 /* For first, check the face name for quick check. */
489 if ( face
->family_name
&&
490 tt_check_trickyness_family( face
->family_name
) )
493 /* Type42 fonts may lack `name' tables, we thus try to identify */
494 /* tricky fonts by checking the checksums of Type42-persistent */
495 /* sfnt tables (`cvt', `fpgm', and `prep'). */
496 if ( tt_check_trickyness_sfnt_ids( (TT_Face
)face
) )
503 /* Check whether `.notdef' is the only glyph in the `loca' table. */
505 tt_check_single_notdef( FT_Face ttface
)
507 FT_Bool result
= FALSE
;
509 TT_Face face
= (TT_Face
)ttface
;
512 FT_ULong glyph_index
= 0;
516 for( i
= 0; i
< face
->num_locations
; i
++ )
518 tt_face_get_location( face
, i
, &asize
);
528 /* Only have a single outline. */
531 if ( glyph_index
== 0 )
535 /* FIXME: Need to test glyphname == .notdef ? */
540 error
= FT_Get_Glyph_Name( ttface
, glyph_index
, buf
, 8 );
542 buf
[0] == '.' && !ft_strncmp( buf
, ".notdef", 8 ) )
551 /*************************************************************************/
557 /* Initialize a given TrueType face object. */
560 /* stream :: The source font stream. */
562 /* face_index :: The index of the TrueType font, if we are opening a */
563 /* collection, in bits 0-15. The numbered instance */
564 /* index~+~1 of a GX (sub)font, if applicable, in bits */
567 /* num_params :: Number of additional generic parameters. Ignored. */
569 /* params :: Additional generic parameters. Ignored. */
572 /* face :: The newly built face object. */
575 /* FreeType error code. 0 means success. */
577 FT_LOCAL_DEF( FT_Error
)
578 tt_face_init( FT_Stream stream
,
579 FT_Face ttface
, /* TT_Face */
582 FT_Parameter
* params
)
587 TT_Face face
= (TT_Face
)ttface
;
590 FT_TRACE2(( "TTF driver\n" ));
592 library
= ttface
->driver
->root
.library
;
594 sfnt
= (SFNT_Service
)FT_Get_Module_Interface( library
, "sfnt" );
597 FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
598 error
= FT_THROW( Missing_Module
);
602 /* create input stream from resource */
603 if ( FT_STREAM_SEEK( 0 ) )
606 /* check that we have a valid TrueType file */
608 error
= sfnt
->init_face( stream
, face
, face_index
, num_params
, params
);
610 /* Stream may have changed. */
611 stream
= face
->root
.stream
;
616 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
617 /* The 0x00020000 tag is completely undocumented; some fonts from */
618 /* Arphic made for Chinese Windows 3.1 have this. */
619 if ( face
->format_tag
!= 0x00010000L
&& /* MS fonts */
620 face
->format_tag
!= 0x00020000L
&& /* CJK fonts for Win 3.1 */
621 face
->format_tag
!= TTAG_true
&& /* Mac fonts */
622 face
->format_tag
!= TTAG_0xA5kbd
&& /* `Keyboard.dfont' (legacy Mac OS X) */
623 face
->format_tag
!= TTAG_0xA5lst
) /* `LastResort.dfont' (legacy Mac OS X) */
625 FT_TRACE2(( " not a TTF font\n" ));
629 #ifdef TT_USE_BYTECODE_INTERPRETER
630 ttface
->face_flags
|= FT_FACE_FLAG_HINTER
;
633 /* If we are performing a simple font format check, exit immediately. */
634 if ( face_index
< 0 )
637 /* Load font directory */
638 error
= sfnt
->load_face( stream
, face
, face_index
, num_params
, params
);
642 if ( tt_check_trickyness( ttface
) )
643 ttface
->face_flags
|= FT_FACE_FLAG_TRICKY
;
645 error
= tt_face_load_hdmx( face
, stream
);
649 if ( FT_IS_SCALABLE( ttface
) )
651 #ifdef FT_CONFIG_OPTION_INCREMENTAL
652 if ( !ttface
->internal
->incremental_interface
)
655 error
= tt_face_load_loca( face
, stream
);
657 /* having a (non-zero) `glyf' table without */
658 /* a `loca' table is not valid */
659 if ( face
->glyf_len
&& FT_ERR_EQ( error
, Table_Missing
) )
665 /* `fpgm', `cvt', and `prep' are optional */
666 error
= tt_face_load_cvt( face
, stream
);
667 if ( error
&& FT_ERR_NEQ( error
, Table_Missing
) )
670 error
= tt_face_load_fpgm( face
, stream
);
671 if ( error
&& FT_ERR_NEQ( error
, Table_Missing
) )
674 error
= tt_face_load_prep( face
, stream
);
675 if ( error
&& FT_ERR_NEQ( error
, Table_Missing
) )
678 /* Check the scalable flag based on `loca'. */
679 #ifdef FT_CONFIG_OPTION_INCREMENTAL
680 if ( !ttface
->internal
->incremental_interface
)
683 if ( ttface
->num_fixed_sizes
&&
684 face
->glyph_locations
&&
685 tt_check_single_notdef( ttface
) )
687 FT_TRACE5(( "tt_face_init:"
688 " Only the `.notdef' glyph has an outline.\n"
690 " Resetting scalable flag to FALSE.\n" ));
692 ttface
->face_flags
&= ~FT_FACE_FLAG_SCALABLE
;
697 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
700 FT_UInt instance_index
= (FT_UInt
)face_index
>> 16;
703 if ( FT_HAS_MULTIPLE_MASTERS( ttface
) &&
706 error
= TT_Set_Named_Instance( face
, instance_index
);
710 tt_apply_mvar( face
);
714 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
716 /* initialize standard glyph loading routines */
717 TT_Init_Glyph_Loading( face
);
723 error
= FT_THROW( Unknown_File_Format
);
728 /*************************************************************************/
734 /* Finalize a given face object. */
737 /* face :: A pointer to the face object to destroy. */
740 tt_face_done( FT_Face ttface
) /* TT_Face */
742 TT_Face face
= (TT_Face
)ttface
;
751 memory
= ttface
->memory
;
752 stream
= ttface
->stream
;
753 sfnt
= (SFNT_Service
)face
->sfnt
;
755 /* for `extended TrueType formats' (i.e. compressed versions) */
756 if ( face
->extra
.finalizer
)
757 face
->extra
.finalizer( face
->extra
.data
);
760 sfnt
->done_face( face
);
762 /* freeing the locations table */
763 tt_face_done_loca( face
);
765 tt_face_free_hdmx( face
);
767 /* freeing the CVT */
768 FT_FREE( face
->cvt
);
771 /* freeing the programs */
772 FT_FRAME_RELEASE( face
->font_program
);
773 FT_FRAME_RELEASE( face
->cvt_program
);
774 face
->font_program_size
= 0;
775 face
->cvt_program_size
= 0;
777 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
778 tt_done_blend( face
);
784 /*************************************************************************/
788 /*************************************************************************/
790 #ifdef TT_USE_BYTECODE_INTERPRETER
792 /*************************************************************************/
795 /* tt_size_run_fpgm */
798 /* Run the font program. */
801 /* size :: A handle to the size object. */
803 /* pedantic :: Set if bytecode execution should be pedantic. */
806 /* FreeType error code. 0 means success. */
808 FT_LOCAL_DEF( FT_Error
)
809 tt_size_run_fpgm( TT_Size size
,
812 TT_Face face
= (TT_Face
)size
->root
.face
;
817 exec
= size
->context
;
819 error
= TT_Load_Context( exec
, face
, size
);
830 exec
->instruction_trap
= FALSE
;
831 exec
->F_dot_P
= 0x4000L
;
833 exec
->pedantic_hinting
= pedantic
;
836 FT_Size_Metrics
* size_metrics
= &exec
->metrics
;
837 TT_Size_Metrics
* tt_metrics
= &exec
->tt_metrics
;
840 size_metrics
->x_ppem
= 0;
841 size_metrics
->y_ppem
= 0;
842 size_metrics
->x_scale
= 0;
843 size_metrics
->y_scale
= 0;
845 tt_metrics
->ppem
= 0;
846 tt_metrics
->scale
= 0;
847 tt_metrics
->ratio
= 0x10000L
;
850 /* allow font program execution */
851 TT_Set_CodeRange( exec
,
854 (FT_Long
)face
->font_program_size
);
856 /* disable CVT and glyph programs coderange */
857 TT_Clear_CodeRange( exec
, tt_coderange_cvt
);
858 TT_Clear_CodeRange( exec
, tt_coderange_glyph
);
860 if ( face
->font_program_size
> 0 )
862 TT_Goto_CodeRange( exec
, tt_coderange_font
, 0 );
864 FT_TRACE4(( "Executing `fpgm' table.\n" ));
865 error
= face
->interpreter( exec
);
866 #ifdef FT_DEBUG_LEVEL_TRACE
868 FT_TRACE4(( " interpretation failed with error code 0x%x\n",
875 size
->bytecode_ready
= error
;
878 TT_Save_Context( exec
, size
);
884 /*************************************************************************/
887 /* tt_size_run_prep */
890 /* Run the control value program. */
893 /* size :: A handle to the size object. */
895 /* pedantic :: Set if bytecode execution should be pedantic. */
898 /* FreeType error code. 0 means success. */
900 FT_LOCAL_DEF( FT_Error
)
901 tt_size_run_prep( TT_Size size
,
904 TT_Face face
= (TT_Face
)size
->root
.face
;
909 exec
= size
->context
;
911 error
= TT_Load_Context( exec
, face
, size
);
918 exec
->instruction_trap
= FALSE
;
920 exec
->pedantic_hinting
= pedantic
;
922 TT_Set_CodeRange( exec
,
925 (FT_Long
)face
->cvt_program_size
);
927 TT_Clear_CodeRange( exec
, tt_coderange_glyph
);
929 if ( face
->cvt_program_size
> 0 )
931 TT_Goto_CodeRange( exec
, tt_coderange_cvt
, 0 );
933 FT_TRACE4(( "Executing `prep' table.\n" ));
934 error
= face
->interpreter( exec
);
935 #ifdef FT_DEBUG_LEVEL_TRACE
937 FT_TRACE4(( " interpretation failed with error code 0x%x\n",
944 size
->cvt_ready
= error
;
946 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */
947 /* graphics state variables to be modified by the CVT program. */
949 exec
->GS
.dualVector
.x
= 0x4000;
950 exec
->GS
.dualVector
.y
= 0;
951 exec
->GS
.projVector
.x
= 0x4000;
952 exec
->GS
.projVector
.y
= 0x0;
953 exec
->GS
.freeVector
.x
= 0x4000;
954 exec
->GS
.freeVector
.y
= 0x0;
966 /* save as default graphics state */
969 TT_Save_Context( exec
, size
);
976 tt_size_done_bytecode( FT_Size ftsize
)
978 TT_Size size
= (TT_Size
)ftsize
;
979 TT_Face face
= (TT_Face
)ftsize
->face
;
980 FT_Memory memory
= face
->root
.memory
;
984 TT_Done_Context( size
->context
);
985 size
->context
= NULL
;
988 FT_FREE( size
->cvt
);
991 /* free storage area */
992 FT_FREE( size
->storage
);
993 size
->storage_size
= 0;
996 tt_glyphzone_done( &size
->twilight
);
998 FT_FREE( size
->function_defs
);
999 FT_FREE( size
->instruction_defs
);
1001 size
->num_function_defs
= 0;
1002 size
->max_function_defs
= 0;
1003 size
->num_instruction_defs
= 0;
1004 size
->max_instruction_defs
= 0;
1009 size
->bytecode_ready
= -1;
1010 size
->cvt_ready
= -1;
1014 /* Initialize bytecode-related fields in the size object. */
1015 /* We do this only if bytecode interpretation is really needed. */
1017 tt_size_init_bytecode( FT_Size ftsize
,
1021 TT_Size size
= (TT_Size
)ftsize
;
1022 TT_Face face
= (TT_Face
)ftsize
->face
;
1023 FT_Memory memory
= face
->root
.memory
;
1025 FT_UShort n_twilight
;
1026 TT_MaxProfile
* maxp
= &face
->max_profile
;
1029 /* clean up bytecode related data */
1030 FT_FREE( size
->function_defs
);
1031 FT_FREE( size
->instruction_defs
);
1032 FT_FREE( size
->cvt
);
1033 FT_FREE( size
->storage
);
1035 if ( size
->context
)
1036 TT_Done_Context( size
->context
);
1037 tt_glyphzone_done( &size
->twilight
);
1039 size
->bytecode_ready
= -1;
1040 size
->cvt_ready
= -1;
1042 size
->context
= TT_New_Context( (TT_Driver
)face
->root
.driver
);
1044 size
->max_function_defs
= maxp
->maxFunctionDefs
;
1045 size
->max_instruction_defs
= maxp
->maxInstructionDefs
;
1047 size
->num_function_defs
= 0;
1048 size
->num_instruction_defs
= 0;
1053 size
->cvt_size
= face
->cvt_size
;
1054 size
->storage_size
= maxp
->maxStorage
;
1056 /* Set default metrics */
1058 TT_Size_Metrics
* tt_metrics
= &size
->ttmetrics
;
1061 tt_metrics
->rotated
= FALSE
;
1062 tt_metrics
->stretched
= FALSE
;
1064 /* set default engine compensation */
1065 tt_metrics
->compensations
[0] = 0; /* gray */
1066 tt_metrics
->compensations
[1] = 0; /* black */
1067 tt_metrics
->compensations
[2] = 0; /* white */
1068 tt_metrics
->compensations
[3] = 0; /* reserved */
1071 /* allocate function defs, instruction defs, cvt, and storage area */
1072 if ( FT_NEW_ARRAY( size
->function_defs
, size
->max_function_defs
) ||
1073 FT_NEW_ARRAY( size
->instruction_defs
, size
->max_instruction_defs
) ||
1074 FT_NEW_ARRAY( size
->cvt
, size
->cvt_size
) ||
1075 FT_NEW_ARRAY( size
->storage
, size
->storage_size
) )
1078 /* reserve twilight zone */
1079 n_twilight
= maxp
->maxTwilightPoints
;
1081 /* there are 4 phantom points (do we need this?) */
1084 error
= tt_glyphzone_new( memory
, n_twilight
, 0, &size
->twilight
);
1088 size
->twilight
.n_points
= n_twilight
;
1090 size
->GS
= tt_default_graphics_state
;
1092 /* set `face->interpreter' according to the debug hook present */
1094 FT_Library library
= face
->root
.driver
->root
.library
;
1097 face
->interpreter
= (TT_Interpreter
)
1098 library
->debug_hooks
[FT_DEBUG_HOOK_TRUETYPE
];
1099 if ( !face
->interpreter
)
1100 face
->interpreter
= (TT_Interpreter
)TT_RunIns
;
1103 /* Fine, now run the font program! */
1105 /* In case of an error while executing `fpgm', we intentionally don't */
1106 /* clean up immediately – bugs in the `fpgm' are so fundamental that */
1107 /* all following hinting calls should fail. Additionally, `fpgm' is */
1108 /* to be executed just once; calling it again is completely useless */
1109 /* and might even lead to extremely slow behaviour if it is malformed */
1110 /* (containing an infinite loop, for example). */
1111 error
= tt_size_run_fpgm( size
, pedantic
);
1116 tt_size_done_bytecode( ftsize
);
1122 FT_LOCAL_DEF( FT_Error
)
1123 tt_size_ready_bytecode( TT_Size size
,
1126 FT_Error error
= FT_Err_Ok
;
1129 if ( size
->bytecode_ready
< 0 )
1130 error
= tt_size_init_bytecode( (FT_Size
)size
, pedantic
);
1132 error
= size
->bytecode_ready
;
1137 /* rescale CVT when needed */
1138 if ( size
->cvt_ready
< 0 )
1141 TT_Face face
= (TT_Face
)size
->root
.face
;
1144 /* Scale the cvt values to the new ppem. */
1145 /* We use by default the y ppem to scale the CVT. */
1146 for ( i
= 0; i
< size
->cvt_size
; i
++ )
1147 size
->cvt
[i
] = FT_MulFix( face
->cvt
[i
], size
->ttmetrics
.scale
);
1149 /* all twilight points are originally zero */
1150 for ( i
= 0; i
< (FT_UInt
)size
->twilight
.n_points
; i
++ )
1152 size
->twilight
.org
[i
].x
= 0;
1153 size
->twilight
.org
[i
].y
= 0;
1154 size
->twilight
.cur
[i
].x
= 0;
1155 size
->twilight
.cur
[i
].y
= 0;
1158 /* clear storage area */
1159 for ( i
= 0; i
< (FT_UInt
)size
->storage_size
; i
++ )
1160 size
->storage
[i
] = 0;
1162 size
->GS
= tt_default_graphics_state
;
1164 error
= tt_size_run_prep( size
, pedantic
);
1167 error
= size
->cvt_ready
;
1173 #endif /* TT_USE_BYTECODE_INTERPRETER */
1176 /*************************************************************************/
1182 /* Initialize a new TrueType size object. */
1185 /* size :: A handle to the size object. */
1188 /* FreeType error code. 0 means success. */
1190 FT_LOCAL_DEF( FT_Error
)
1191 tt_size_init( FT_Size ttsize
) /* TT_Size */
1193 TT_Size size
= (TT_Size
)ttsize
;
1194 FT_Error error
= FT_Err_Ok
;
1197 #ifdef TT_USE_BYTECODE_INTERPRETER
1198 size
->bytecode_ready
= -1;
1199 size
->cvt_ready
= -1;
1202 size
->ttmetrics
.valid
= FALSE
;
1203 size
->strike_index
= 0xFFFFFFFFUL
;
1209 /*************************************************************************/
1215 /* The TrueType size object finalizer. */
1218 /* size :: A handle to the target size object. */
1220 FT_LOCAL_DEF( void )
1221 tt_size_done( FT_Size ttsize
) /* TT_Size */
1223 TT_Size size
= (TT_Size
)ttsize
;
1226 #ifdef TT_USE_BYTECODE_INTERPRETER
1227 tt_size_done_bytecode( ttsize
);
1230 size
->ttmetrics
.valid
= FALSE
;
1234 /*************************************************************************/
1240 /* Reset a TrueType size when resolutions and character dimensions */
1241 /* have been changed. */
1244 /* size :: A handle to the target size object. */
1246 /* only_height :: Only recompute ascender, descender, and height; */
1247 /* this flag is used for variation fonts where */
1248 /* `tt_size_reset' is used as an iterator function. */
1250 FT_LOCAL_DEF( FT_Error
)
1251 tt_size_reset( TT_Size size
,
1252 FT_Bool only_height
)
1255 FT_Size_Metrics
* size_metrics
;
1258 face
= (TT_Face
)size
->root
.face
;
1260 /* nothing to do for CFF2 */
1261 if ( face
->is_cff2
)
1264 size
->ttmetrics
.valid
= FALSE
;
1266 size_metrics
= &size
->hinted_metrics
;
1268 /* copy the result from base layer */
1269 *size_metrics
= size
->root
.metrics
;
1271 if ( size_metrics
->x_ppem
< 1 || size_metrics
->y_ppem
< 1 )
1272 return FT_THROW( Invalid_PPem
);
1274 /* This bit flag, if set, indicates that the ppems must be */
1275 /* rounded to integers. Nearly all TrueType fonts have this bit */
1276 /* set, as hinting won't work really well otherwise. */
1278 if ( face
->header
.Flags
& 8 )
1280 /* the TT spec always asks for ROUND, not FLOOR or CEIL */
1281 size_metrics
->ascender
= FT_PIX_ROUND(
1282 FT_MulFix( face
->root
.ascender
,
1283 size_metrics
->y_scale
) );
1284 size_metrics
->descender
= FT_PIX_ROUND(
1285 FT_MulFix( face
->root
.descender
,
1286 size_metrics
->y_scale
) );
1287 size_metrics
->height
= FT_PIX_ROUND(
1288 FT_MulFix( face
->root
.height
,
1289 size_metrics
->y_scale
) );
1292 size
->ttmetrics
.valid
= TRUE
;
1296 /* we must not recompute the scaling values here since */
1297 /* `tt_size_reset' was already called (with only_height = 0) */
1301 if ( face
->header
.Flags
& 8 )
1303 /* base scaling values on integer ppem values, */
1304 /* as mandated by the TrueType specification */
1305 size_metrics
->x_scale
= FT_DivFix( size_metrics
->x_ppem
<< 6,
1306 face
->root
.units_per_EM
);
1307 size_metrics
->y_scale
= FT_DivFix( size_metrics
->y_ppem
<< 6,
1308 face
->root
.units_per_EM
);
1310 size_metrics
->max_advance
= FT_PIX_ROUND(
1311 FT_MulFix( face
->root
.max_advance_width
,
1312 size_metrics
->x_scale
) );
1315 /* compute new transformation */
1316 if ( size_metrics
->x_ppem
>= size_metrics
->y_ppem
)
1318 size
->ttmetrics
.scale
= size_metrics
->x_scale
;
1319 size
->ttmetrics
.ppem
= size_metrics
->x_ppem
;
1320 size
->ttmetrics
.x_ratio
= 0x10000L
;
1321 size
->ttmetrics
.y_ratio
= FT_DivFix( size_metrics
->y_ppem
,
1322 size_metrics
->x_ppem
);
1326 size
->ttmetrics
.scale
= size_metrics
->y_scale
;
1327 size
->ttmetrics
.ppem
= size_metrics
->y_ppem
;
1328 size
->ttmetrics
.x_ratio
= FT_DivFix( size_metrics
->x_ppem
,
1329 size_metrics
->y_ppem
);
1330 size
->ttmetrics
.y_ratio
= 0x10000L
;
1333 size
->metrics
= size_metrics
;
1335 #ifdef TT_USE_BYTECODE_INTERPRETER
1336 size
->cvt_ready
= -1;
1337 #endif /* TT_USE_BYTECODE_INTERPRETER */
1343 /*************************************************************************/
1346 /* tt_driver_init */
1349 /* Initialize a given TrueType driver object. */
1352 /* driver :: A handle to the target driver object. */
1355 /* FreeType error code. 0 means success. */
1357 FT_LOCAL_DEF( FT_Error
)
1358 tt_driver_init( FT_Module ttdriver
) /* TT_Driver */
1361 #ifdef TT_USE_BYTECODE_INTERPRETER
1363 TT_Driver driver
= (TT_Driver
)ttdriver
;
1365 driver
->interpreter_version
= TT_INTERPRETER_VERSION_35
;
1366 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1367 driver
->interpreter_version
= TT_INTERPRETER_VERSION_38
;
1369 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1370 driver
->interpreter_version
= TT_INTERPRETER_VERSION_40
;
1373 #else /* !TT_USE_BYTECODE_INTERPRETER */
1375 FT_UNUSED( ttdriver
);
1377 #endif /* !TT_USE_BYTECODE_INTERPRETER */
1383 /*************************************************************************/
1386 /* tt_driver_done */
1389 /* Finalize a given TrueType driver. */
1392 /* driver :: A handle to the target TrueType driver. */
1394 FT_LOCAL_DEF( void )
1395 tt_driver_done( FT_Module ttdriver
) /* TT_Driver */
1397 FT_UNUSED( ttdriver
);
1401 /*************************************************************************/
1407 /* Initialize a new slot object. */
1410 /* slot :: A handle to the slot object. */
1413 /* FreeType error code. 0 means success. */
1415 FT_LOCAL_DEF( FT_Error
)
1416 tt_slot_init( FT_GlyphSlot slot
)
1418 return FT_GlyphLoader_CreateExtra( slot
->internal
->loader
);