|
1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* ttobjs.c */ |
|
4 /* */ |
|
5 /* Objects manager (body). */ |
|
6 /* */ |
|
7 /* Copyright 1996-2011 */ |
|
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
|
9 /* */ |
|
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. */ |
|
15 /* */ |
|
16 /***************************************************************************/ |
|
17 |
|
18 |
|
19 #include <ft2build.h> |
|
20 #include FT_INTERNAL_DEBUG_H |
|
21 #include FT_INTERNAL_STREAM_H |
|
22 #include FT_TRUETYPE_TAGS_H |
|
23 #include FT_INTERNAL_SFNT_H |
|
24 |
|
25 #include "ttgload.h" |
|
26 #include "ttpload.h" |
|
27 |
|
28 #include "tterrors.h" |
|
29 |
|
30 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
31 #include "ttinterp.h" |
|
32 #endif |
|
33 |
|
34 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING |
|
35 #include FT_TRUETYPE_UNPATENTED_H |
|
36 #endif |
|
37 |
|
38 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
|
39 #include "ttgxvar.h" |
|
40 #endif |
|
41 |
|
42 /*************************************************************************/ |
|
43 /* */ |
|
44 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
|
45 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
|
46 /* messages during execution. */ |
|
47 /* */ |
|
48 #undef FT_COMPONENT |
|
49 #define FT_COMPONENT trace_ttobjs |
|
50 |
|
51 |
|
52 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
53 |
|
54 /*************************************************************************/ |
|
55 /* */ |
|
56 /* GLYPH ZONE FUNCTIONS */ |
|
57 /* */ |
|
58 /*************************************************************************/ |
|
59 |
|
60 |
|
61 /*************************************************************************/ |
|
62 /* */ |
|
63 /* <Function> */ |
|
64 /* tt_glyphzone_done */ |
|
65 /* */ |
|
66 /* <Description> */ |
|
67 /* Deallocate a glyph zone. */ |
|
68 /* */ |
|
69 /* <Input> */ |
|
70 /* zone :: A pointer to the target glyph zone. */ |
|
71 /* */ |
|
72 FT_LOCAL_DEF( void ) |
|
73 tt_glyphzone_done( TT_GlyphZone zone ) |
|
74 { |
|
75 FT_Memory memory = zone->memory; |
|
76 |
|
77 |
|
78 if ( memory ) |
|
79 { |
|
80 FT_FREE( zone->contours ); |
|
81 FT_FREE( zone->tags ); |
|
82 FT_FREE( zone->cur ); |
|
83 FT_FREE( zone->org ); |
|
84 FT_FREE( zone->orus ); |
|
85 |
|
86 zone->max_points = zone->n_points = 0; |
|
87 zone->max_contours = zone->n_contours = 0; |
|
88 zone->memory = NULL; |
|
89 } |
|
90 } |
|
91 |
|
92 |
|
93 /*************************************************************************/ |
|
94 /* */ |
|
95 /* <Function> */ |
|
96 /* tt_glyphzone_new */ |
|
97 /* */ |
|
98 /* <Description> */ |
|
99 /* Allocate a new glyph zone. */ |
|
100 /* */ |
|
101 /* <Input> */ |
|
102 /* memory :: A handle to the current memory object. */ |
|
103 /* */ |
|
104 /* maxPoints :: The capacity of glyph zone in points. */ |
|
105 /* */ |
|
106 /* maxContours :: The capacity of glyph zone in contours. */ |
|
107 /* */ |
|
108 /* <Output> */ |
|
109 /* zone :: A pointer to the target glyph zone record. */ |
|
110 /* */ |
|
111 /* <Return> */ |
|
112 /* FreeType error code. 0 means success. */ |
|
113 /* */ |
|
114 FT_LOCAL_DEF( FT_Error ) |
|
115 tt_glyphzone_new( FT_Memory memory, |
|
116 FT_UShort maxPoints, |
|
117 FT_Short maxContours, |
|
118 TT_GlyphZone zone ) |
|
119 { |
|
120 FT_Error error; |
|
121 |
|
122 |
|
123 FT_MEM_ZERO( zone, sizeof ( *zone ) ); |
|
124 zone->memory = memory; |
|
125 |
|
126 if ( FT_NEW_ARRAY( zone->org, maxPoints ) || |
|
127 FT_NEW_ARRAY( zone->cur, maxPoints ) || |
|
128 FT_NEW_ARRAY( zone->orus, maxPoints ) || |
|
129 FT_NEW_ARRAY( zone->tags, maxPoints ) || |
|
130 FT_NEW_ARRAY( zone->contours, maxContours ) ) |
|
131 { |
|
132 tt_glyphzone_done( zone ); |
|
133 } |
|
134 else |
|
135 { |
|
136 zone->max_points = maxPoints; |
|
137 zone->max_contours = maxContours; |
|
138 } |
|
139 |
|
140 return error; |
|
141 } |
|
142 #endif /* TT_USE_BYTECODE_INTERPRETER */ |
|
143 |
|
144 |
|
145 /* Compare the face with a list of well-known `tricky' fonts. */ |
|
146 /* This list shall be expanded as we find more of them. */ |
|
147 |
|
148 static FT_Bool |
|
149 tt_check_trickyness_family( FT_String* name ) |
|
150 { |
|
151 |
|
152 #define TRICK_NAMES_MAX_CHARACTERS 16 |
|
153 #define TRICK_NAMES_COUNT 8 |
|
154 |
|
155 static const char trick_names[TRICK_NAMES_COUNT] |
|
156 [TRICK_NAMES_MAX_CHARACTERS + 1] = |
|
157 { |
|
158 "DFKaiSho-SB", /* dfkaisb.ttf */ |
|
159 "DFKaiShu", |
|
160 "DFKai-SB", /* kaiu.ttf */ |
|
161 "HuaTianKaiTi?", /* htkt2.ttf */ |
|
162 "HuaTianSongTi?", /* htst3.ttf */ |
|
163 "MingLiU", /* mingliu.ttf & mingliu.ttc */ |
|
164 "PMingLiU", /* mingliu.ttc */ |
|
165 "MingLi43", /* mingli.ttf */ |
|
166 }; |
|
167 |
|
168 int nn; |
|
169 |
|
170 |
|
171 for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ ) |
|
172 if ( ft_strstr( name, trick_names[nn] ) ) |
|
173 return TRUE; |
|
174 |
|
175 return FALSE; |
|
176 } |
|
177 |
|
178 |
|
179 /* XXX: This function should be in the `sfnt' module. */ |
|
180 |
|
181 /* Some PDF generators clear the checksums in the TrueType header table. */ |
|
182 /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */ |
|
183 /* Printer clears the entries for subsetted subtables. We thus have to */ |
|
184 /* recalculate the checksums where necessary. */ |
|
185 |
|
186 static FT_UInt32 |
|
187 tt_synth_sfnt_checksum( FT_Stream stream, |
|
188 FT_ULong length ) |
|
189 { |
|
190 FT_Error error; |
|
191 FT_UInt32 checksum = 0; |
|
192 int i; |
|
193 |
|
194 |
|
195 if ( FT_FRAME_ENTER( length ) ) |
|
196 return 0; |
|
197 |
|
198 for ( ; length > 3; length -= 4 ) |
|
199 checksum += (FT_UInt32)FT_GET_ULONG(); |
|
200 |
|
201 for ( i = 3; length > 0; length --, i-- ) |
|
202 checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) ); |
|
203 |
|
204 FT_FRAME_EXIT(); |
|
205 |
|
206 return checksum; |
|
207 } |
|
208 |
|
209 |
|
210 /* XXX: This function should be in the `sfnt' module. */ |
|
211 |
|
212 static FT_ULong |
|
213 tt_get_sfnt_checksum( TT_Face face, |
|
214 FT_UShort i ) |
|
215 { |
|
216 if ( face->dir_tables[i].CheckSum ) |
|
217 return face->dir_tables[i].CheckSum; |
|
218 |
|
219 else if ( !face->goto_table ) |
|
220 return 0; |
|
221 |
|
222 else if ( !face->goto_table( face, |
|
223 face->dir_tables[i].Tag, |
|
224 face->root.stream, |
|
225 NULL ) ) |
|
226 return 0; |
|
227 |
|
228 return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream, |
|
229 face->dir_tables[i].Length ); |
|
230 } |
|
231 |
|
232 |
|
233 typedef struct tt_sfnt_id_rec_ |
|
234 { |
|
235 FT_ULong CheckSum; |
|
236 FT_ULong Length; |
|
237 |
|
238 } tt_sfnt_id_rec; |
|
239 |
|
240 |
|
241 static FT_Bool |
|
242 tt_check_trickyness_sfnt_ids( TT_Face face ) |
|
243 { |
|
244 #define TRICK_SFNT_IDS_PER_FACE 3 |
|
245 #define TRICK_SFNT_IDS_NUM_FACES 5 |
|
246 |
|
247 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] |
|
248 [TRICK_SFNT_IDS_PER_FACE] = { |
|
249 |
|
250 #define TRICK_SFNT_ID_cvt 0 |
|
251 #define TRICK_SFNT_ID_fpgm 1 |
|
252 #define TRICK_SFNT_ID_prep 2 |
|
253 |
|
254 { /* MingLiU 1995 */ |
|
255 { 0x05bcf058, 0x000002e4 }, /* cvt */ |
|
256 { 0x28233bf1, 0x000087c4 }, /* fpgm */ |
|
257 { 0xa344a1ea, 0x000001e1 } /* prep */ |
|
258 }, |
|
259 { /* MingLiU 1996- */ |
|
260 { 0x05bcf058, 0x000002e4 }, /* cvt */ |
|
261 { 0x28233bf1, 0x000087c4 }, /* fpgm */ |
|
262 { 0xa344a1eb, 0x000001e1 } /* prep */ |
|
263 }, |
|
264 { /* DFKaiShu */ |
|
265 { 0x11e5ead4, 0x00000350 }, /* cvt */ |
|
266 { 0x5a30ca3b, 0x00009063 }, /* fpgm */ |
|
267 { 0x13a42602, 0x0000007e } /* prep */ |
|
268 }, |
|
269 { /* HuaTianKaiTi */ |
|
270 { 0xfffbfffc, 0x00000008 }, /* cvt */ |
|
271 { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */ |
|
272 { 0x70020112, 0x00000008 } /* prep */ |
|
273 }, |
|
274 { /* HuaTianSongTi */ |
|
275 { 0xfffbfffc, 0x00000008 }, /* cvt */ |
|
276 { 0x0a5a0483, 0x00017c39 }, /* fpgm */ |
|
277 { 0x70020112, 0x00000008 } /* prep */ |
|
278 } |
|
279 }; |
|
280 |
|
281 FT_ULong checksum; |
|
282 int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES]; |
|
283 int i, j, k; |
|
284 |
|
285 |
|
286 FT_MEM_SET( num_matched_ids, 0, |
|
287 sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES ); |
|
288 |
|
289 for ( i = 0; i < face->num_tables; i++ ) |
|
290 { |
|
291 checksum = 0; |
|
292 |
|
293 switch( face->dir_tables[i].Tag ) |
|
294 { |
|
295 case TTAG_cvt: |
|
296 k = TRICK_SFNT_ID_cvt; |
|
297 break; |
|
298 |
|
299 case TTAG_fpgm: |
|
300 k = TRICK_SFNT_ID_fpgm; |
|
301 break; |
|
302 |
|
303 case TTAG_prep: |
|
304 k = TRICK_SFNT_ID_prep; |
|
305 break; |
|
306 |
|
307 default: |
|
308 continue; |
|
309 } |
|
310 |
|
311 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) |
|
312 if ( face->dir_tables[i].Length == sfnt_id[j][k].Length ) |
|
313 { |
|
314 if ( !checksum ) |
|
315 checksum = tt_get_sfnt_checksum( face, i ); |
|
316 |
|
317 if ( sfnt_id[j][k].CheckSum == checksum ) |
|
318 num_matched_ids[j]++; |
|
319 |
|
320 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) |
|
321 return TRUE; |
|
322 } |
|
323 } |
|
324 |
|
325 return FALSE; |
|
326 } |
|
327 |
|
328 |
|
329 static FT_Bool |
|
330 tt_check_trickyness( FT_Face face ) |
|
331 { |
|
332 if ( !face ) |
|
333 return FALSE; |
|
334 |
|
335 /* First, check the face name. */ |
|
336 if ( face->family_name ) |
|
337 { |
|
338 if ( tt_check_trickyness_family( face->family_name ) ) |
|
339 return TRUE; |
|
340 else |
|
341 return FALSE; |
|
342 } |
|
343 |
|
344 /* Type42 fonts may lack `name' tables, we thus try to identify */ |
|
345 /* tricky fonts by checking the checksums of Type42-persistent */ |
|
346 /* sfnt tables (`cvt', `fpgm', and `prep'). */ |
|
347 if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) ) |
|
348 return TRUE; |
|
349 |
|
350 return FALSE; |
|
351 } |
|
352 |
|
353 |
|
354 /*************************************************************************/ |
|
355 /* */ |
|
356 /* <Function> */ |
|
357 /* tt_face_init */ |
|
358 /* */ |
|
359 /* <Description> */ |
|
360 /* Initialize a given TrueType face object. */ |
|
361 /* */ |
|
362 /* <Input> */ |
|
363 /* stream :: The source font stream. */ |
|
364 /* */ |
|
365 /* face_index :: The index of the font face in the resource. */ |
|
366 /* */ |
|
367 /* num_params :: Number of additional generic parameters. Ignored. */ |
|
368 /* */ |
|
369 /* params :: Additional generic parameters. Ignored. */ |
|
370 /* */ |
|
371 /* <InOut> */ |
|
372 /* face :: The newly built face object. */ |
|
373 /* */ |
|
374 /* <Return> */ |
|
375 /* FreeType error code. 0 means success. */ |
|
376 /* */ |
|
377 FT_LOCAL_DEF( FT_Error ) |
|
378 tt_face_init( FT_Stream stream, |
|
379 FT_Face ttface, /* TT_Face */ |
|
380 FT_Int face_index, |
|
381 FT_Int num_params, |
|
382 FT_Parameter* params ) |
|
383 { |
|
384 FT_Error error; |
|
385 FT_Library library; |
|
386 SFNT_Service sfnt; |
|
387 TT_Face face = (TT_Face)ttface; |
|
388 |
|
389 |
|
390 library = ttface->driver->root.library; |
|
391 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); |
|
392 if ( !sfnt ) |
|
393 goto Bad_Format; |
|
394 |
|
395 /* create input stream from resource */ |
|
396 if ( FT_STREAM_SEEK( 0 ) ) |
|
397 goto Exit; |
|
398 |
|
399 /* check that we have a valid TrueType file */ |
|
400 error = sfnt->init_face( stream, face, face_index, num_params, params ); |
|
401 if ( error ) |
|
402 goto Exit; |
|
403 |
|
404 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ |
|
405 /* The 0x00020000 tag is completely undocumented; some fonts from */ |
|
406 /* Arphic made for Chinese Windows 3.1 have this. */ |
|
407 if ( face->format_tag != 0x00010000L && /* MS fonts */ |
|
408 face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ |
|
409 face->format_tag != TTAG_true ) /* Mac fonts */ |
|
410 { |
|
411 FT_TRACE2(( "[not a valid TTF font]\n" )); |
|
412 goto Bad_Format; |
|
413 } |
|
414 |
|
415 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
416 ttface->face_flags |= FT_FACE_FLAG_HINTER; |
|
417 #endif |
|
418 |
|
419 /* If we are performing a simple font format check, exit immediately. */ |
|
420 if ( face_index < 0 ) |
|
421 return TT_Err_Ok; |
|
422 |
|
423 /* Load font directory */ |
|
424 error = sfnt->load_face( stream, face, face_index, num_params, params ); |
|
425 if ( error ) |
|
426 goto Exit; |
|
427 |
|
428 if ( tt_check_trickyness( ttface ) ) |
|
429 ttface->face_flags |= FT_FACE_FLAG_TRICKY; |
|
430 |
|
431 error = tt_face_load_hdmx( face, stream ); |
|
432 if ( error ) |
|
433 goto Exit; |
|
434 |
|
435 if ( FT_IS_SCALABLE( ttface ) ) |
|
436 { |
|
437 |
|
438 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
439 |
|
440 if ( !ttface->internal->incremental_interface ) |
|
441 error = tt_face_load_loca( face, stream ); |
|
442 if ( !error ) |
|
443 error = tt_face_load_cvt( face, stream ); |
|
444 if ( !error ) |
|
445 error = tt_face_load_fpgm( face, stream ); |
|
446 if ( !error ) |
|
447 error = tt_face_load_prep( face, stream ); |
|
448 |
|
449 #else |
|
450 |
|
451 if ( !error ) |
|
452 error = tt_face_load_loca( face, stream ); |
|
453 if ( !error ) |
|
454 error = tt_face_load_cvt( face, stream ); |
|
455 if ( !error ) |
|
456 error = tt_face_load_fpgm( face, stream ); |
|
457 if ( !error ) |
|
458 error = tt_face_load_prep( face, stream ); |
|
459 |
|
460 #endif |
|
461 |
|
462 } |
|
463 |
|
464 #if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ |
|
465 !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) |
|
466 |
|
467 { |
|
468 FT_Bool unpatented_hinting; |
|
469 int i; |
|
470 |
|
471 |
|
472 /* Determine whether unpatented hinting is to be used for this face. */ |
|
473 unpatented_hinting = FT_BOOL |
|
474 ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL ); |
|
475 |
|
476 for ( i = 0; i < num_params && !face->unpatented_hinting; i++ ) |
|
477 if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING ) |
|
478 unpatented_hinting = TRUE; |
|
479 |
|
480 if ( !unpatented_hinting ) |
|
481 ttface->internal->ignore_unpatented_hinter = TRUE; |
|
482 } |
|
483 |
|
484 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING && |
|
485 !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ |
|
486 |
|
487 /* initialize standard glyph loading routines */ |
|
488 TT_Init_Glyph_Loading( face ); |
|
489 |
|
490 Exit: |
|
491 return error; |
|
492 |
|
493 Bad_Format: |
|
494 error = TT_Err_Unknown_File_Format; |
|
495 goto Exit; |
|
496 } |
|
497 |
|
498 |
|
499 /*************************************************************************/ |
|
500 /* */ |
|
501 /* <Function> */ |
|
502 /* tt_face_done */ |
|
503 /* */ |
|
504 /* <Description> */ |
|
505 /* Finalize a given face object. */ |
|
506 /* */ |
|
507 /* <Input> */ |
|
508 /* face :: A pointer to the face object to destroy. */ |
|
509 /* */ |
|
510 FT_LOCAL_DEF( void ) |
|
511 tt_face_done( FT_Face ttface ) /* TT_Face */ |
|
512 { |
|
513 TT_Face face = (TT_Face)ttface; |
|
514 FT_Memory memory; |
|
515 FT_Stream stream; |
|
516 SFNT_Service sfnt; |
|
517 |
|
518 |
|
519 if ( !face ) |
|
520 return; |
|
521 |
|
522 memory = ttface->memory; |
|
523 stream = ttface->stream; |
|
524 sfnt = (SFNT_Service)face->sfnt; |
|
525 |
|
526 /* for `extended TrueType formats' (i.e. compressed versions) */ |
|
527 if ( face->extra.finalizer ) |
|
528 face->extra.finalizer( face->extra.data ); |
|
529 |
|
530 if ( sfnt ) |
|
531 sfnt->done_face( face ); |
|
532 |
|
533 /* freeing the locations table */ |
|
534 tt_face_done_loca( face ); |
|
535 |
|
536 tt_face_free_hdmx( face ); |
|
537 |
|
538 /* freeing the CVT */ |
|
539 FT_FREE( face->cvt ); |
|
540 face->cvt_size = 0; |
|
541 |
|
542 /* freeing the programs */ |
|
543 FT_FRAME_RELEASE( face->font_program ); |
|
544 FT_FRAME_RELEASE( face->cvt_program ); |
|
545 face->font_program_size = 0; |
|
546 face->cvt_program_size = 0; |
|
547 |
|
548 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
|
549 tt_done_blend( memory, face->blend ); |
|
550 face->blend = NULL; |
|
551 #endif |
|
552 } |
|
553 |
|
554 |
|
555 /*************************************************************************/ |
|
556 /* */ |
|
557 /* SIZE FUNCTIONS */ |
|
558 /* */ |
|
559 /*************************************************************************/ |
|
560 |
|
561 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
562 |
|
563 /*************************************************************************/ |
|
564 /* */ |
|
565 /* <Function> */ |
|
566 /* tt_size_run_fpgm */ |
|
567 /* */ |
|
568 /* <Description> */ |
|
569 /* Run the font program. */ |
|
570 /* */ |
|
571 /* <Input> */ |
|
572 /* size :: A handle to the size object. */ |
|
573 /* */ |
|
574 /* pedantic :: Set if bytecode execution should be pedantic. */ |
|
575 /* */ |
|
576 /* <Return> */ |
|
577 /* FreeType error code. 0 means success. */ |
|
578 /* */ |
|
579 FT_LOCAL_DEF( FT_Error ) |
|
580 tt_size_run_fpgm( TT_Size size, |
|
581 FT_Bool pedantic ) |
|
582 { |
|
583 TT_Face face = (TT_Face)size->root.face; |
|
584 TT_ExecContext exec; |
|
585 FT_Error error; |
|
586 |
|
587 |
|
588 /* debugging instances have their own context */ |
|
589 if ( size->debug ) |
|
590 exec = size->context; |
|
591 else |
|
592 exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; |
|
593 |
|
594 if ( !exec ) |
|
595 return TT_Err_Could_Not_Find_Context; |
|
596 |
|
597 TT_Load_Context( exec, face, size ); |
|
598 |
|
599 exec->callTop = 0; |
|
600 exec->top = 0; |
|
601 |
|
602 exec->period = 64; |
|
603 exec->phase = 0; |
|
604 exec->threshold = 0; |
|
605 |
|
606 exec->instruction_trap = FALSE; |
|
607 exec->F_dot_P = 0x10000L; |
|
608 |
|
609 exec->pedantic_hinting = pedantic; |
|
610 |
|
611 { |
|
612 FT_Size_Metrics* metrics = &exec->metrics; |
|
613 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; |
|
614 |
|
615 |
|
616 metrics->x_ppem = 0; |
|
617 metrics->y_ppem = 0; |
|
618 metrics->x_scale = 0; |
|
619 metrics->y_scale = 0; |
|
620 |
|
621 tt_metrics->ppem = 0; |
|
622 tt_metrics->scale = 0; |
|
623 tt_metrics->ratio = 0x10000L; |
|
624 } |
|
625 |
|
626 /* allow font program execution */ |
|
627 TT_Set_CodeRange( exec, |
|
628 tt_coderange_font, |
|
629 face->font_program, |
|
630 face->font_program_size ); |
|
631 |
|
632 /* disable CVT and glyph programs coderange */ |
|
633 TT_Clear_CodeRange( exec, tt_coderange_cvt ); |
|
634 TT_Clear_CodeRange( exec, tt_coderange_glyph ); |
|
635 |
|
636 if ( face->font_program_size > 0 ) |
|
637 { |
|
638 error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); |
|
639 |
|
640 if ( !error ) |
|
641 { |
|
642 FT_TRACE4(( "Executing `fpgm' table.\n" )); |
|
643 |
|
644 error = face->interpreter( exec ); |
|
645 } |
|
646 } |
|
647 else |
|
648 error = TT_Err_Ok; |
|
649 |
|
650 if ( !error ) |
|
651 TT_Save_Context( exec, size ); |
|
652 |
|
653 return error; |
|
654 } |
|
655 |
|
656 |
|
657 /*************************************************************************/ |
|
658 /* */ |
|
659 /* <Function> */ |
|
660 /* tt_size_run_prep */ |
|
661 /* */ |
|
662 /* <Description> */ |
|
663 /* Run the control value program. */ |
|
664 /* */ |
|
665 /* <Input> */ |
|
666 /* size :: A handle to the size object. */ |
|
667 /* */ |
|
668 /* pedantic :: Set if bytecode execution should be pedantic. */ |
|
669 /* */ |
|
670 /* <Return> */ |
|
671 /* FreeType error code. 0 means success. */ |
|
672 /* */ |
|
673 FT_LOCAL_DEF( FT_Error ) |
|
674 tt_size_run_prep( TT_Size size, |
|
675 FT_Bool pedantic ) |
|
676 { |
|
677 TT_Face face = (TT_Face)size->root.face; |
|
678 TT_ExecContext exec; |
|
679 FT_Error error; |
|
680 |
|
681 |
|
682 /* debugging instances have their own context */ |
|
683 if ( size->debug ) |
|
684 exec = size->context; |
|
685 else |
|
686 exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; |
|
687 |
|
688 if ( !exec ) |
|
689 return TT_Err_Could_Not_Find_Context; |
|
690 |
|
691 TT_Load_Context( exec, face, size ); |
|
692 |
|
693 exec->callTop = 0; |
|
694 exec->top = 0; |
|
695 |
|
696 exec->instruction_trap = FALSE; |
|
697 |
|
698 exec->pedantic_hinting = pedantic; |
|
699 |
|
700 TT_Set_CodeRange( exec, |
|
701 tt_coderange_cvt, |
|
702 face->cvt_program, |
|
703 face->cvt_program_size ); |
|
704 |
|
705 TT_Clear_CodeRange( exec, tt_coderange_glyph ); |
|
706 |
|
707 if ( face->cvt_program_size > 0 ) |
|
708 { |
|
709 error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); |
|
710 |
|
711 if ( !error && !size->debug ) |
|
712 { |
|
713 FT_TRACE4(( "Executing `prep' table.\n" )); |
|
714 |
|
715 error = face->interpreter( exec ); |
|
716 } |
|
717 } |
|
718 else |
|
719 error = TT_Err_Ok; |
|
720 |
|
721 /* save as default graphics state */ |
|
722 size->GS = exec->GS; |
|
723 |
|
724 TT_Save_Context( exec, size ); |
|
725 |
|
726 return error; |
|
727 } |
|
728 |
|
729 #endif /* TT_USE_BYTECODE_INTERPRETER */ |
|
730 |
|
731 |
|
732 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
733 |
|
734 static void |
|
735 tt_size_done_bytecode( FT_Size ftsize ) |
|
736 { |
|
737 TT_Size size = (TT_Size)ftsize; |
|
738 TT_Face face = (TT_Face)ftsize->face; |
|
739 FT_Memory memory = face->root.memory; |
|
740 |
|
741 |
|
742 if ( size->debug ) |
|
743 { |
|
744 /* the debug context must be deleted by the debugger itself */ |
|
745 size->context = NULL; |
|
746 size->debug = FALSE; |
|
747 } |
|
748 |
|
749 FT_FREE( size->cvt ); |
|
750 size->cvt_size = 0; |
|
751 |
|
752 /* free storage area */ |
|
753 FT_FREE( size->storage ); |
|
754 size->storage_size = 0; |
|
755 |
|
756 /* twilight zone */ |
|
757 tt_glyphzone_done( &size->twilight ); |
|
758 |
|
759 FT_FREE( size->function_defs ); |
|
760 FT_FREE( size->instruction_defs ); |
|
761 |
|
762 size->num_function_defs = 0; |
|
763 size->max_function_defs = 0; |
|
764 size->num_instruction_defs = 0; |
|
765 size->max_instruction_defs = 0; |
|
766 |
|
767 size->max_func = 0; |
|
768 size->max_ins = 0; |
|
769 |
|
770 size->bytecode_ready = 0; |
|
771 size->cvt_ready = 0; |
|
772 } |
|
773 |
|
774 |
|
775 /* Initialize bytecode-related fields in the size object. */ |
|
776 /* We do this only if bytecode interpretation is really needed. */ |
|
777 static FT_Error |
|
778 tt_size_init_bytecode( FT_Size ftsize, |
|
779 FT_Bool pedantic ) |
|
780 { |
|
781 FT_Error error; |
|
782 TT_Size size = (TT_Size)ftsize; |
|
783 TT_Face face = (TT_Face)ftsize->face; |
|
784 FT_Memory memory = face->root.memory; |
|
785 FT_Int i; |
|
786 |
|
787 FT_UShort n_twilight; |
|
788 TT_MaxProfile* maxp = &face->max_profile; |
|
789 |
|
790 |
|
791 size->bytecode_ready = 1; |
|
792 size->cvt_ready = 0; |
|
793 |
|
794 size->max_function_defs = maxp->maxFunctionDefs; |
|
795 size->max_instruction_defs = maxp->maxInstructionDefs; |
|
796 |
|
797 size->num_function_defs = 0; |
|
798 size->num_instruction_defs = 0; |
|
799 |
|
800 size->max_func = 0; |
|
801 size->max_ins = 0; |
|
802 |
|
803 size->cvt_size = face->cvt_size; |
|
804 size->storage_size = maxp->maxStorage; |
|
805 |
|
806 /* Set default metrics */ |
|
807 { |
|
808 TT_Size_Metrics* metrics = &size->ttmetrics; |
|
809 |
|
810 |
|
811 metrics->rotated = FALSE; |
|
812 metrics->stretched = FALSE; |
|
813 |
|
814 /* set default compensation (all 0) */ |
|
815 for ( i = 0; i < 4; i++ ) |
|
816 metrics->compensations[i] = 0; |
|
817 } |
|
818 |
|
819 /* allocate function defs, instruction defs, cvt, and storage area */ |
|
820 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || |
|
821 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || |
|
822 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || |
|
823 FT_NEW_ARRAY( size->storage, size->storage_size ) ) |
|
824 goto Exit; |
|
825 |
|
826 /* reserve twilight zone */ |
|
827 n_twilight = maxp->maxTwilightPoints; |
|
828 |
|
829 /* there are 4 phantom points (do we need this?) */ |
|
830 n_twilight += 4; |
|
831 |
|
832 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); |
|
833 if ( error ) |
|
834 goto Exit; |
|
835 |
|
836 size->twilight.n_points = n_twilight; |
|
837 |
|
838 size->GS = tt_default_graphics_state; |
|
839 |
|
840 /* set `face->interpreter' according to the debug hook present */ |
|
841 { |
|
842 FT_Library library = face->root.driver->root.library; |
|
843 |
|
844 |
|
845 face->interpreter = (TT_Interpreter) |
|
846 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; |
|
847 if ( !face->interpreter ) |
|
848 face->interpreter = (TT_Interpreter)TT_RunIns; |
|
849 } |
|
850 |
|
851 /* Fine, now run the font program! */ |
|
852 error = tt_size_run_fpgm( size, pedantic ); |
|
853 |
|
854 Exit: |
|
855 if ( error ) |
|
856 tt_size_done_bytecode( ftsize ); |
|
857 |
|
858 return error; |
|
859 } |
|
860 |
|
861 |
|
862 FT_LOCAL_DEF( FT_Error ) |
|
863 tt_size_ready_bytecode( TT_Size size, |
|
864 FT_Bool pedantic ) |
|
865 { |
|
866 FT_Error error = TT_Err_Ok; |
|
867 |
|
868 |
|
869 if ( !size->bytecode_ready ) |
|
870 { |
|
871 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); |
|
872 if ( error ) |
|
873 goto Exit; |
|
874 } |
|
875 |
|
876 /* rescale CVT when needed */ |
|
877 if ( !size->cvt_ready ) |
|
878 { |
|
879 FT_UInt i; |
|
880 TT_Face face = (TT_Face)size->root.face; |
|
881 |
|
882 |
|
883 /* Scale the cvt values to the new ppem. */ |
|
884 /* We use by default the y ppem to scale the CVT. */ |
|
885 for ( i = 0; i < size->cvt_size; i++ ) |
|
886 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); |
|
887 |
|
888 /* all twilight points are originally zero */ |
|
889 for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ ) |
|
890 { |
|
891 size->twilight.org[i].x = 0; |
|
892 size->twilight.org[i].y = 0; |
|
893 size->twilight.cur[i].x = 0; |
|
894 size->twilight.cur[i].y = 0; |
|
895 } |
|
896 |
|
897 /* clear storage area */ |
|
898 for ( i = 0; i < (FT_UInt)size->storage_size; i++ ) |
|
899 size->storage[i] = 0; |
|
900 |
|
901 size->GS = tt_default_graphics_state; |
|
902 |
|
903 error = tt_size_run_prep( size, pedantic ); |
|
904 if ( !error ) |
|
905 size->cvt_ready = 1; |
|
906 } |
|
907 |
|
908 Exit: |
|
909 return error; |
|
910 } |
|
911 |
|
912 #endif /* TT_USE_BYTECODE_INTERPRETER */ |
|
913 |
|
914 |
|
915 /*************************************************************************/ |
|
916 /* */ |
|
917 /* <Function> */ |
|
918 /* tt_size_init */ |
|
919 /* */ |
|
920 /* <Description> */ |
|
921 /* Initialize a new TrueType size object. */ |
|
922 /* */ |
|
923 /* <InOut> */ |
|
924 /* size :: A handle to the size object. */ |
|
925 /* */ |
|
926 /* <Return> */ |
|
927 /* FreeType error code. 0 means success. */ |
|
928 /* */ |
|
929 FT_LOCAL_DEF( FT_Error ) |
|
930 tt_size_init( FT_Size ttsize ) /* TT_Size */ |
|
931 { |
|
932 TT_Size size = (TT_Size)ttsize; |
|
933 FT_Error error = TT_Err_Ok; |
|
934 |
|
935 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
936 size->bytecode_ready = 0; |
|
937 size->cvt_ready = 0; |
|
938 #endif |
|
939 |
|
940 size->ttmetrics.valid = FALSE; |
|
941 size->strike_index = 0xFFFFFFFFUL; |
|
942 |
|
943 return error; |
|
944 } |
|
945 |
|
946 |
|
947 /*************************************************************************/ |
|
948 /* */ |
|
949 /* <Function> */ |
|
950 /* tt_size_done */ |
|
951 /* */ |
|
952 /* <Description> */ |
|
953 /* The TrueType size object finalizer. */ |
|
954 /* */ |
|
955 /* <Input> */ |
|
956 /* size :: A handle to the target size object. */ |
|
957 /* */ |
|
958 FT_LOCAL_DEF( void ) |
|
959 tt_size_done( FT_Size ttsize ) /* TT_Size */ |
|
960 { |
|
961 TT_Size size = (TT_Size)ttsize; |
|
962 |
|
963 |
|
964 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
965 if ( size->bytecode_ready ) |
|
966 tt_size_done_bytecode( ttsize ); |
|
967 #endif |
|
968 |
|
969 size->ttmetrics.valid = FALSE; |
|
970 } |
|
971 |
|
972 |
|
973 /*************************************************************************/ |
|
974 /* */ |
|
975 /* <Function> */ |
|
976 /* tt_size_reset */ |
|
977 /* */ |
|
978 /* <Description> */ |
|
979 /* Reset a TrueType size when resolutions and character dimensions */ |
|
980 /* have been changed. */ |
|
981 /* */ |
|
982 /* <Input> */ |
|
983 /* size :: A handle to the target size object. */ |
|
984 /* */ |
|
985 FT_LOCAL_DEF( FT_Error ) |
|
986 tt_size_reset( TT_Size size ) |
|
987 { |
|
988 TT_Face face; |
|
989 FT_Error error = TT_Err_Ok; |
|
990 FT_Size_Metrics* metrics; |
|
991 |
|
992 |
|
993 size->ttmetrics.valid = FALSE; |
|
994 |
|
995 face = (TT_Face)size->root.face; |
|
996 |
|
997 metrics = &size->metrics; |
|
998 |
|
999 /* copy the result from base layer */ |
|
1000 *metrics = size->root.metrics; |
|
1001 |
|
1002 if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) |
|
1003 return TT_Err_Invalid_PPem; |
|
1004 |
|
1005 /* This bit flag, if set, indicates that the ppems must be */ |
|
1006 /* rounded to integers. Nearly all TrueType fonts have this bit */ |
|
1007 /* set, as hinting won't work really well otherwise. */ |
|
1008 /* */ |
|
1009 if ( face->header.Flags & 8 ) |
|
1010 { |
|
1011 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, |
|
1012 face->root.units_per_EM ); |
|
1013 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, |
|
1014 face->root.units_per_EM ); |
|
1015 |
|
1016 metrics->ascender = |
|
1017 FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); |
|
1018 metrics->descender = |
|
1019 FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); |
|
1020 metrics->height = |
|
1021 FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); |
|
1022 metrics->max_advance = |
|
1023 FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, |
|
1024 metrics->x_scale ) ); |
|
1025 } |
|
1026 |
|
1027 /* compute new transformation */ |
|
1028 if ( metrics->x_ppem >= metrics->y_ppem ) |
|
1029 { |
|
1030 size->ttmetrics.scale = metrics->x_scale; |
|
1031 size->ttmetrics.ppem = metrics->x_ppem; |
|
1032 size->ttmetrics.x_ratio = 0x10000L; |
|
1033 size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem, |
|
1034 0x10000L, |
|
1035 metrics->x_ppem ); |
|
1036 } |
|
1037 else |
|
1038 { |
|
1039 size->ttmetrics.scale = metrics->y_scale; |
|
1040 size->ttmetrics.ppem = metrics->y_ppem; |
|
1041 size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem, |
|
1042 0x10000L, |
|
1043 metrics->y_ppem ); |
|
1044 size->ttmetrics.y_ratio = 0x10000L; |
|
1045 } |
|
1046 |
|
1047 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
1048 size->cvt_ready = 0; |
|
1049 #endif /* TT_USE_BYTECODE_INTERPRETER */ |
|
1050 |
|
1051 if ( !error ) |
|
1052 size->ttmetrics.valid = TRUE; |
|
1053 |
|
1054 return error; |
|
1055 } |
|
1056 |
|
1057 |
|
1058 /*************************************************************************/ |
|
1059 /* */ |
|
1060 /* <Function> */ |
|
1061 /* tt_driver_init */ |
|
1062 /* */ |
|
1063 /* <Description> */ |
|
1064 /* Initialize a given TrueType driver object. */ |
|
1065 /* */ |
|
1066 /* <Input> */ |
|
1067 /* driver :: A handle to the target driver object. */ |
|
1068 /* */ |
|
1069 /* <Return> */ |
|
1070 /* FreeType error code. 0 means success. */ |
|
1071 /* */ |
|
1072 FT_LOCAL_DEF( FT_Error ) |
|
1073 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ |
|
1074 { |
|
1075 |
|
1076 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
1077 |
|
1078 TT_Driver driver = (TT_Driver)ttdriver; |
|
1079 |
|
1080 |
|
1081 if ( !TT_New_Context( driver ) ) |
|
1082 return TT_Err_Could_Not_Find_Context; |
|
1083 |
|
1084 #else |
|
1085 |
|
1086 FT_UNUSED( ttdriver ); |
|
1087 |
|
1088 #endif |
|
1089 |
|
1090 return TT_Err_Ok; |
|
1091 } |
|
1092 |
|
1093 |
|
1094 /*************************************************************************/ |
|
1095 /* */ |
|
1096 /* <Function> */ |
|
1097 /* tt_driver_done */ |
|
1098 /* */ |
|
1099 /* <Description> */ |
|
1100 /* Finalize a given TrueType driver. */ |
|
1101 /* */ |
|
1102 /* <Input> */ |
|
1103 /* driver :: A handle to the target TrueType driver. */ |
|
1104 /* */ |
|
1105 FT_LOCAL_DEF( void ) |
|
1106 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ |
|
1107 { |
|
1108 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
1109 TT_Driver driver = (TT_Driver)ttdriver; |
|
1110 |
|
1111 |
|
1112 /* destroy the execution context */ |
|
1113 if ( driver->context ) |
|
1114 { |
|
1115 TT_Done_Context( driver->context ); |
|
1116 driver->context = NULL; |
|
1117 } |
|
1118 #else |
|
1119 FT_UNUSED( ttdriver ); |
|
1120 #endif |
|
1121 |
|
1122 } |
|
1123 |
|
1124 |
|
1125 /*************************************************************************/ |
|
1126 /* */ |
|
1127 /* <Function> */ |
|
1128 /* tt_slot_init */ |
|
1129 /* */ |
|
1130 /* <Description> */ |
|
1131 /* Initialize a new slot object. */ |
|
1132 /* */ |
|
1133 /* <InOut> */ |
|
1134 /* slot :: A handle to the slot object. */ |
|
1135 /* */ |
|
1136 /* <Return> */ |
|
1137 /* FreeType error code. 0 means success. */ |
|
1138 /* */ |
|
1139 FT_LOCAL_DEF( FT_Error ) |
|
1140 tt_slot_init( FT_GlyphSlot slot ) |
|
1141 { |
|
1142 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); |
|
1143 } |
|
1144 |
|
1145 |
|
1146 /* END */ |