1 /*******************************************************************
7 * Copyright 1996-1999 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 ******************************************************************/
27 /* Add extensions definition */
28 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
32 /* Required by tracing mode */
34 #define TT_COMPONENT trace_objs
36 /*******************************************************************
38 * Function : New_Context
40 * Description : Creates a new execution context for a given
43 ******************************************************************/
46 PExecution_Context
New_Context( PFace face
)
48 PEngine_Instance engine
;
49 PExecution_Context exec
;
55 engine
= face
->engine
;
56 CACHE_New( engine
->objs_exec_cache
, exec
, face
);
61 /*******************************************************************
63 * Function : Done_Context
65 * Description : Discards an execution context.
67 ******************************************************************/
70 TT_Error
Done_Context( PExecution_Context exec
)
72 PEngine_Instance engine
;
78 engine
= exec
->face
->engine
;
79 return CACHE_Done( engine
->objs_exec_cache
, exec
);
85 /*******************************************************************
87 * Function : New_Instance
89 * Description : Creates a new instance for a given face object.
91 ******************************************************************/
94 PInstance
New_Instance( PFace face
)
102 CACHE_New( &face
->instances
, ins
, face
);
108 /*******************************************************************
110 * Function : Done_Instance
112 * Description : Discards an instance.
114 ******************************************************************/
117 TT_Error
Done_Instance( PInstance instance
)
119 return CACHE_Done( &instance
->owner
->instances
, instance
);
125 /*******************************************************************
127 * GLYPH ZONE FUNCTIONS *
130 *******************************************************************/
132 /*******************************************************************
134 * Function : New_Glyph_Zone
136 * Description : Allocates a new glyph zone
138 * Input : pts pointer to the target glyph zone record
139 * maxPoints capacity of glyph zone in points
140 * maxContours capacity of glyph zone in contours
142 * Return : Error code.
144 *****************************************************************/
147 TT_Error
New_Glyph_Zone( PGlyph_Zone pts
,
154 if ( ALLOC( pts
->org
, maxPoints
* 2 * sizeof ( TT_F26Dot6
) ) ||
155 ALLOC( pts
->cur
, maxPoints
* 2 * sizeof ( TT_F26Dot6
) ) ||
156 ALLOC( pts
->touch
, maxPoints
* sizeof ( Byte
) ) ||
157 ALLOC( pts
->contours
, maxContours
* sizeof ( Short
) ) )
164 /*******************************************************************
166 * Function : Done_Glyph_Zone
168 * Description : Deallocates a glyph zone
170 * Input : pts pointer to the target glyph zone record
172 * Return : Error code.
174 *****************************************************************/
177 TT_Error
Done_Glyph_Zone( PGlyph_Zone pts
)
179 FREE( pts
->contours
);
189 /*******************************************************************
191 * CODERANGE FUNCTIONS *
193 *******************************************************************/
195 /*******************************************************************
197 * Function : Goto_CodeRange
199 * Description : Switch to a new code range (updates Code and IP).
201 * Input : exec target execution context
202 * range new execution code range
203 * IP new IP in new code range
205 * Output : SUCCESS on success. FAILURE on error (no code range).
207 *****************************************************************/
210 TT_Error
Goto_CodeRange( PExecution_Context exec
,
217 if ( range
< 1 || range
> 3 )
218 return TT_Err_Bad_Argument
;
220 cr
= &exec
->codeRangeTable
[range
- 1];
222 if ( cr
->Base
== NULL
)
223 return TT_Err_Invalid_CodeRange
;
225 /* NOTE: Because the last instruction of a program may be a CALL */
226 /* which will return to the first byte *after* the code */
227 /* range, we test for IP <= Size, instead of IP < Size. */
230 return TT_Err_Code_Overflow
;
232 exec
->code
= cr
->Base
;
233 exec
->codeSize
= cr
->Size
;
235 exec
->curRange
= range
;
243 /*******************************************************************
245 * Function : Get_CodeRange
247 * Description : Returns a pointer to a given code range. Should
248 * be used only by the debugger. Returns NULL if
249 * 'range' is out of current bounds.
251 * Input : exec target execution context
252 * range new execution code range
254 * Output : Pointer to the code range record. NULL on failure.
256 *****************************************************************/
259 PCodeRange
Get_CodeRange( PExecution_Context exec
, Int range
)
261 if ( range
< 1 || range
> 3 )
263 else /* arrays start with 1 in Pascal, and with 0 in C */
264 return &exec
->codeRangeTable
[range
- 1];
270 /*******************************************************************
272 * Function : Set_CodeRange
274 * Description : Sets a code range.
276 * Input : exec target execution context
277 * range code range index
279 * length range size in bytes
281 * Output : SUCCESS on success. FAILURE on error.
283 *****************************************************************/
286 TT_Error
Set_CodeRange( PExecution_Context exec
,
291 if ( range
< 1 || range
> 3 )
292 return TT_Err_Bad_Argument
;
294 exec
->codeRangeTable
[range
- 1].Base
= (Byte
*)base
;
295 exec
->codeRangeTable
[range
- 1].Size
= length
;
301 /*******************************************************************
303 * Function : Clear_CodeRange
305 * Description : Clears a code range.
307 * Input : exec target execution context
308 * range code range index
310 * Output : SUCCESS on success. FAILURE on error.
312 * Note : Does not set the Error variable.
314 *****************************************************************/
317 TT_Error
Clear_CodeRange( PExecution_Context exec
, Int range
)
319 if ( range
< 1 || range
> 3 )
320 return TT_Err_Bad_Argument
;
322 exec
->codeRangeTable
[range
- 1].Base
= NULL
;
323 exec
->codeRangeTable
[range
- 1].Size
= 0;
330 /*******************************************************************
332 * EXECUTION CONTEXT ROUTINES *
334 *******************************************************************/
336 /*******************************************************************
338 * Function : Context_Destroy
340 *****************************************************************/
343 TT_Error
Context_Destroy( void* _context
)
345 PExecution_Context exec
= (PExecution_Context
)_context
;
350 /* free composite load stack */
351 FREE( exec
->loadStack
);
355 Done_Glyph_Zone( &exec
->pts
);
357 exec
->maxContours
= 0;
363 /* free call stack */
364 FREE( exec
->callStack
);
368 /* free glyph code range */
369 FREE( exec
->glyphIns
);
372 exec
->instance
= NULL
;
379 /*******************************************************************
381 * Function : Context_Create
383 *****************************************************************/
386 TT_Error
Context_Create( void* _context
, void* _face
)
388 PExecution_Context exec
= (PExecution_Context
)_context
;
390 PFace face
= (PFace
)_face
;
394 /* XXX : We don't reserve arrays anymore, this is done automatically */
395 /* during a "Context_Load".. */
398 if ( ALLOC_ARRAY( exec
->callStack
, exec
->callSize
, TCallRecord
) )
401 /* all values in the context are set to 0 already, but this is */
402 /* here as a remainder */
404 exec
->maxContours
= 0;
411 exec
->loadStack
= NULL
;
412 exec
->glyphIns
= NULL
;
415 exec
->instance
= NULL
;
420 Context_Destroy( exec
);
425 /*******************************************************************
427 * Function : Context_Load
429 *****************************************************************/
431 /****************************************************************/
433 /* Update_Max : Reallocate a buffer if it needs to */
435 /* input: size address of buffer's current size */
436 /* expressed in elements */
438 /* multiplier size in bytes of each element in the */
441 /* buff address of the buffer base pointer */
443 /* new_max new capacity (size) of the buffer */
446 TT_Error
Update_Max( ULong
* size
,
453 if ( *size
< new_max
)
456 if ( ALLOC( *buff
, new_max
* multiplier
) )
464 /****************************************************************/
466 /* Update_Zone: Reallocate a zone if it needs to */
468 /* input: zone address of the target zone */
470 /* maxPoints address of the zone's current capacity */
473 /* maxContours address of the zone's current capacity */
476 /* newPoints new capacity in points */
478 /* newContours new capacity in contours */
482 TT_Error
Update_Zone( PGlyph_Zone zone
,
488 if ( *maxPoints
< newPoints
|| *maxContours
< newContours
)
493 Done_Glyph_Zone( zone
);
495 error
= New_Glyph_Zone( zone
, newPoints
, newContours
);
499 *maxPoints
= newPoints
;
500 *maxContours
= newContours
;
507 TT_Error
Context_Load( PExecution_Context exec
,
516 maxp
= &face
->maxProfile
;
518 exec
->instance
= ins
;
522 exec
->numFDefs
= ins
->numFDefs
;
523 exec
->numIDefs
= ins
->numIDefs
;
524 exec
->maxFDefs
= ins
->maxFDefs
;
525 exec
->maxIDefs
= ins
->maxIDefs
;
526 exec
->FDefs
= ins
->FDefs
;
527 exec
->IDefs
= ins
->IDefs
;
528 exec
->metrics
= ins
->metrics
;
530 exec
->maxFunc
= ins
->maxFunc
;
531 exec
->maxIns
= ins
->maxIns
;
533 for ( i
= 0; i
< MAX_CODE_RANGES
; i
++ )
534 exec
->codeRangeTable
[i
] = ins
->codeRangeTable
[i
];
536 /* set graphics state */
539 exec
->cvtSize
= ins
->cvtSize
;
540 exec
->cvt
= ins
->cvt
;
542 exec
->storeSize
= ins
->storeSize
;
543 exec
->storage
= ins
->storage
;
545 exec
->twilight
= ins
->twilight
;
548 error
= Update_Max( &exec
->loadSize
,
549 sizeof ( TSubglyph_Record
),
550 (void**)&exec
->loadStack
,
551 face
->maxComponents
+ 1 );
555 error
= Update_Max( &exec
->stackSize
,
556 sizeof ( TT_F26Dot6
),
557 (void**)&exec
->stack
,
558 maxp
->maxStackElements
+ 32 );
559 /* XXX : We reserve a little more elements on the stack to deal safely */
560 /* with broken fonts like arialbs, courbs, timesbs... */
564 error
= Update_Max( &exec
->glyphSize
,
566 (void**)&exec
->glyphIns
,
567 maxp
->maxSizeOfInstructions
);
571 error
= Update_Zone( &exec
->pts
,
574 exec
->face
->maxPoints
+ 2,
575 exec
->face
->maxContours
);
576 /* XXX : We reserve two positions for the phantom points! */
580 exec
->pts
.n_points
= 0;
581 exec
->pts
.n_contours
= 0;
583 exec
->instruction_trap
= FALSE
;
589 /*******************************************************************
591 * Function : Context_Save
593 *****************************************************************/
596 TT_Error
Context_Save( PExecution_Context exec
,
601 /* XXXX : Will probably disappear soon with all the coderange */
602 /* management, which is now rather obsolete. */
604 ins
->numFDefs
= exec
->numFDefs
;
605 ins
->numIDefs
= exec
->numIDefs
;
606 ins
->maxFunc
= exec
->maxFunc
;
607 ins
->maxIns
= exec
->maxIns
;
609 for ( i
= 0; i
< MAX_CODE_RANGES
; i
++ )
610 ins
->codeRangeTable
[i
] = exec
->codeRangeTable
[i
];
616 /*******************************************************************
618 * Function : Context_Run
620 *****************************************************************/
623 TT_Error
Context_Run( PExecution_Context exec
,
629 if ( (error
= Goto_CodeRange( exec
,
630 TT_CodeRange_Glyph
, 0 )) != TT_Err_Ok
)
633 exec
->zp0
= exec
->pts
;
634 exec
->zp1
= exec
->pts
;
635 exec
->zp2
= exec
->pts
;
641 exec
->GS
.projVector
.x
= 0x4000;
642 exec
->GS
.projVector
.y
= 0x0000;
644 exec
->GS
.freeVector
= exec
->GS
.projVector
;
645 exec
->GS
.dualVector
= exec
->GS
.projVector
;
647 exec
->GS
.round_state
= 1;
650 /* some glyphs leave something on the stack. so we clean it */
651 /* before a new execution. */
656 return RunIns( exec
);
663 const TGraphicsState Default_GraphicsState
=
670 TRUE
, 68, 0, 0, 9, 3,
676 /*******************************************************************
678 * INSTANCE FUNCTIONS *
681 *******************************************************************/
683 /*******************************************************************
685 * Function : Instance_Destroy
689 * Input : _instance the instance object to destroy
691 * Output : error code.
693 ******************************************************************/
696 TT_Error
Instance_Destroy( void* _instance
)
698 PInstance ins
= (PInstance
)_instance
;
706 /* the debug context must be deleted by the debugger itself */
714 /* free storage area */
715 FREE( ins
->storage
);
719 Done_Glyph_Zone( &ins
->twilight
);
737 /*******************************************************************
739 * Function : Instance_Create
743 * Input : _instance instance record to initialize
744 * _face parent face object
746 * Output : Error code. All partially built subtables are
749 ******************************************************************/
752 TT_Error
Instance_Create( void* _instance
,
755 PInstance ins
= (PInstance
)_instance
;
756 PFace face
= (PFace
)_face
;
761 PMaxProfile maxp
= &face
->maxProfile
;
767 ins
->maxFDefs
= maxp
->maxFunctionDefs
;
768 ins
->maxIDefs
= maxp
->maxInstructionDefs
;
769 ins
->cvtSize
= face
->cvtSize
;
770 ins
->storeSize
= maxp
->maxStorage
;
772 /* Set default metrics */
774 PIns_Metrics metrics
= &ins
->metrics
;
777 metrics
->pointSize
= 10 * 64; /* default pointsize = 10pts */
779 metrics
->x_resolution
= 96; /* default resolution = 96dpi */
780 metrics
->y_resolution
= 96;
785 metrics
->rotated
= FALSE
;
786 metrics
->stretched
= FALSE
;
788 /* set default compensation ( all 0 ) */
789 for ( i
= 0; i
< 4; i
++ )
790 metrics
->compensations
[i
] = 0;
793 /* allocate function defs, instruction defs, cvt and storage area */
794 if ( ALLOC_ARRAY( ins
->FDefs
, ins
->maxFDefs
, TDefRecord
) ||
795 ALLOC_ARRAY( ins
->IDefs
, ins
->maxIDefs
, TDefRecord
) ||
796 ALLOC_ARRAY( ins
->cvt
, ins
->cvtSize
, Long
) ||
797 ALLOC_ARRAY( ins
->storage
, ins
->storeSize
, Long
) )
800 /* reserve twilight zone */
801 n_twilight
= maxp
->maxTwilightPoints
;
802 error
= New_Glyph_Zone( &ins
->twilight
, n_twilight
, 0 );
806 ins
->twilight
.n_points
= n_twilight
;
811 Instance_Destroy( ins
);
816 /*******************************************************************
818 * Function : Instance_Init
820 * Description : Initialize a fresh new instance.
821 * Executes the font program if any is found.
823 * Input : _instance the instance object to destroy
825 * Output : Error code.
827 ******************************************************************/
830 TT_Error
Instance_Init( PInstance ins
)
832 PExecution_Context exec
;
835 PFace face
= ins
->owner
;
841 exec
= New_Context( face
);
842 /* debugging instances have their own context */
845 return TT_Err_Could_Not_Find_Context
;
847 ins
->GS
= Default_GraphicsState
;
854 Context_Load( exec
, face
, ins
);
864 PIns_Metrics metrics
= &exec
->metrics
;
869 metrics
->pointSize
= 0;
870 metrics
->x_scale1
= 0;
871 metrics
->x_scale2
= 1;
872 metrics
->y_scale1
= 0;
873 metrics
->y_scale2
= 1;
878 metrics
->ratio
= 1L << 16;
881 exec
->instruction_trap
= FALSE
;
883 exec
->cvtSize
= ins
->cvtSize
;
884 exec
->cvt
= ins
->cvt
;
886 exec
->F_dot_P
= 0x10000;
888 /* allow font program execution */
894 /* disable CVT and glyph programs coderange */
895 Clear_CodeRange( exec
, TT_CodeRange_Cvt
);
896 Clear_CodeRange( exec
, TT_CodeRange_Glyph
);
898 if ( face
->fontPgmSize
> 0 )
900 error
= Goto_CodeRange( exec
, TT_CodeRange_Font
, 0 );
904 error
= RunIns( exec
);
910 Context_Save( exec
, ins
);
913 Done_Context( exec
);
914 /* debugging instances keep their context */
922 /*******************************************************************
924 * Function : Instance_Reset
926 * Description : Resets an instance to a new pointsize/transform.
927 * Executes the cvt program if any is found.
929 * Input : _instance the instance object to destroy
931 * Output : Error code.
933 ******************************************************************/
936 TT_Error
Instance_Reset( PInstance ins
)
938 PExecution_Context exec
;
947 return TT_Err_Invalid_Instance_Handle
;
954 if ( ins
->metrics
.x_ppem
< 1 ||
955 ins
->metrics
.y_ppem
< 1 )
956 return TT_Err_Invalid_PPem
;
958 /* compute new transformation */
959 if ( ins
->metrics
.x_ppem
>= ins
->metrics
.y_ppem
)
961 ins
->metrics
.scale1
= ins
->metrics
.x_scale1
;
962 ins
->metrics
.scale2
= ins
->metrics
.x_scale2
;
963 ins
->metrics
.ppem
= ins
->metrics
.x_ppem
;
964 ins
->metrics
.x_ratio
= 1L << 16;
965 ins
->metrics
.y_ratio
= TT_MulDiv( ins
->metrics
.y_ppem
,
967 ins
->metrics
.x_ppem
);
971 ins
->metrics
.scale1
= ins
->metrics
.y_scale1
;
972 ins
->metrics
.scale2
= ins
->metrics
.y_scale2
;
973 ins
->metrics
.ppem
= ins
->metrics
.y_ppem
;
974 ins
->metrics
.x_ratio
= TT_MulDiv( ins
->metrics
.x_ppem
,
976 ins
->metrics
.y_ppem
);
977 ins
->metrics
.y_ratio
= 1L << 16;
980 /* Scale the cvt values to the new ppem. */
981 /* We use by default the y ppem to scale the CVT. */
983 for ( i
= 0; i
< ins
->cvtSize
; i
++ )
984 ins
->cvt
[i
] = TT_MulDiv( face
->cvt
[i
],
986 ins
->metrics
.scale2
);
988 /* All twilight points are originally zero */
989 for ( j
= 0; j
< ins
->twilight
.n_points
; j
++ )
991 ins
->twilight
.org
[j
].x
= 0;
992 ins
->twilight
.org
[j
].y
= 0;
993 ins
->twilight
.cur
[j
].x
= 0;
994 ins
->twilight
.cur
[j
].y
= 0;
997 /* clear storage area */
998 for ( i
= 0; i
< ins
->storeSize
; i
++ )
1001 ins
->GS
= Default_GraphicsState
;
1003 /* get execution context and run prep program */
1006 exec
= ins
->context
;
1008 exec
= New_Context(face
);
1009 /* debugging instances have their own context */
1012 return TT_Err_Could_Not_Find_Context
;
1014 Context_Load( exec
, face
, ins
);
1016 Set_CodeRange( exec
,
1021 Clear_CodeRange( exec
, TT_CodeRange_Glyph
);
1023 exec
->instruction_trap
= FALSE
;
1028 if ( face
->cvtPgmSize
> 0 )
1030 error
= Goto_CodeRange( exec
, TT_CodeRange_Cvt
, 0 );
1035 error
= RunIns( exec
);
1041 /* save default graphics state */
1044 Context_Save( exec
, ins
);
1047 Done_Context( exec
);
1048 /* debugging instances keep their context */
1058 /*******************************************************************
1063 *******************************************************************/
1065 /*******************************************************************
1067 * Function : Face_Destroy
1069 * Description : The face object destructor.
1071 * Input : _face typeless pointer to the face object to destroy
1073 * Output : Error code.
1075 ******************************************************************/
1078 TT_Error
Face_Destroy( void* _face
)
1080 PFace face
= (PFace
)_face
;
1087 /* well, we assume that no other thread is using the face */
1088 /* at this moment, but one is never sure enough. */
1089 MUTEX_Lock( face
->lock
);
1091 /* first of all, destroys the cached sub-objects */
1092 Cache_Destroy( &face
->instances
);
1093 Cache_Destroy( &face
->glyphs
);
1095 /* destroy the extensions */
1096 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
1097 Extension_Destroy( face
);
1100 /* freeing the collection table */
1101 FREE( face
->ttcHeader
.TableDirectory
);
1102 face
->ttcHeader
.DirCount
= 0;
1104 /* freeing table directory */
1105 FREE( face
->dirTables
);
1106 face
->numTables
= 0;
1108 /* freeing the locations table */
1109 FREE( face
->glyphLocations
);
1110 face
->numLocations
= 0;
1112 /* freeing the character mapping tables */
1113 for ( n
= 0; n
< face
->numCMaps
; n
++ )
1114 CharMap_Free( face
->cMaps
+ n
);
1116 FREE( face
->cMaps
);
1119 /* freeing the CVT */
1123 /* freeing the horizontal metrics */
1124 FREE( face
->horizontalHeader
.long_metrics
);
1125 FREE( face
->horizontalHeader
.short_metrics
);
1127 /* freeing the vertical ones, if any */
1128 if (face
->verticalInfo
)
1130 FREE( face
->verticalHeader
.long_metrics
);
1131 FREE( face
->verticalHeader
.short_metrics
);
1132 face
->verticalInfo
= 0;
1135 /* freeing the programs */
1136 FREE( face
->fontProgram
);
1137 FREE( face
->cvtProgram
);
1138 face
->fontPgmSize
= 0;
1139 face
->cvtPgmSize
= 0;
1141 /* freeing the gasp table */
1142 FREE( face
->gasp
.gaspRanges
);
1143 face
->gasp
.numRanges
= 0;
1145 /* freeing the name table */
1146 Free_TrueType_Names( face
);
1148 /* freeing the hdmx table */
1149 Free_TrueType_Hdmx( face
);
1151 /* TT_Close_Stream( &face->stream ); -- this is performed by the API */
1153 /* destroy the mutex */
1154 MUTEX_Destroy(face
->lock
);
1160 /*******************************************************************
1162 * Function : Face_Create
1164 * Description : The face object constructor.
1166 * Input : _face face record to build
1167 * _input input stream where to load font data
1169 * Output : Error code.
1171 * NOTE : The input stream is kept in the face object. The
1172 * caller shouldn't destroy it after calling Face_Create().
1174 ******************************************************************/
1177 #define LOAD_( table ) \
1178 (error = Load_TrueType_##table (face)) != TT_Err_Ok
1182 TT_Error
Face_Create( void* _face
,
1185 PEngine_Instance engine
;
1187 TFont_Input
* input
= (TFont_Input
*)_input
;
1188 PFace face
= (PFace
)_face
;
1192 face
->stream
= input
->stream
;
1193 face
->engine
= input
->engine
;
1195 engine
= face
->engine
;
1197 MUTEX_Create( face
->lock
);
1199 Cache_Create( engine
,
1200 engine
->objs_instance_class
,
1204 Cache_Create( engine
,
1205 engine
->objs_glyph_class
,
1209 /* Load collection directory if present, then font directory */
1211 error
= Load_TrueType_Directory( face
, input
->fontIndex
);
1217 if ( LOAD_( Header
) ||
1218 LOAD_( MaxProfile
) ||
1219 LOAD_( Locations
) ||
1221 (error
= Load_TrueType_Metrics_Header( face
, 0 )) != TT_Err_Ok
||
1222 /* load the 'hhea' & 'hmtx' tables at once */
1226 LOAD_( Programs
) ||
1230 LOAD_( PostScript
) ||
1232 (error
= Load_TrueType_Metrics_Header( face
, 1 )) != TT_Err_Ok
||
1233 /* try to load the 'vhea' & 'vmtx' at once if present */
1239 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
1240 if ( ( error
= Extension_Create( face
) ) != TT_Err_Ok
)
1247 Face_Destroy( face
);
1254 /*******************************************************************
1256 * Function : Glyph_Destroy
1258 * Description : The glyph object destructor.
1260 * Input : _glyph typeless pointer to the glyph record to destroy
1262 * Output : Error code.
1264 ******************************************************************/
1267 TT_Error
Glyph_Destroy( void* _glyph
)
1269 PGlyph glyph
= (PGlyph
)_glyph
;
1275 glyph
->outline
.owner
= TRUE
;
1276 return TT_Done_Outline( &glyph
->outline
);
1280 /*******************************************************************
1282 * Function : Glyph_Create
1284 * Description : The glyph object constructor.
1286 * Input : _glyph glyph record to build.
1287 * _face the glyph's parent face.
1289 * Output : Error code.
1291 ******************************************************************/
1294 TT_Error
Glyph_Create( void* _glyph
,
1297 PFace face
= (PFace
)_face
;
1298 PGlyph glyph
= (PGlyph
)_glyph
;
1302 return TT_Err_Invalid_Face_Handle
;
1305 return TT_Err_Invalid_Glyph_Handle
;
1309 /* XXX: Don't forget the space for the 2 phantom points */
1310 return TT_New_Outline( glyph
->face
->maxPoints
+ 2,
1311 glyph
->face
->maxContours
,
1316 /*******************************************************************
1318 * Function : Scale_X
1320 * Description : scale an horizontal distance from font
1321 * units to 26.6 pixels
1323 * Input : metrics pointer to metrics
1326 * Output : scaled value
1328 ******************************************************************/
1331 TT_Pos
Scale_X( PIns_Metrics metrics
, TT_Pos x
)
1333 return TT_MulDiv( x
, metrics
->x_scale1
, metrics
->x_scale2
);
1337 /*******************************************************************
1339 * Function : Scale_Y
1341 * Description : scale a vertical distance from font
1342 * units to 26.6 pixels
1344 * Input : metrics pointer to metrics
1347 * Output : scaled value
1349 ******************************************************************/
1352 TT_Pos
Scale_Y( PIns_Metrics metrics
, TT_Pos y
)
1354 return TT_MulDiv( y
, metrics
->y_scale1
, metrics
->y_scale2
);
1358 /*******************************************************************
1360 * Function : TTObjs_Init
1362 * Description : The TTObjs component initializer. Creates the
1363 * object cache classes, as well as the face record
1366 * Input : engine engine instance
1368 * Output : Error code.
1370 ******************************************************************/
1373 const TCache_Class objs_face_class
=
1384 const TCache_Class objs_instance_class
=
1386 sizeof ( TInstance
),
1394 /* Note that we use a cache size of 1 for the execution context. */
1395 /* This is to avoid re-creating a new context each time we */
1396 /* change one instance's attribute (resolution and/or char sizes) */
1397 /* or when we load a glyph. */
1400 const TCache_Class objs_exec_class
=
1402 sizeof ( TExecution_Context
),
1411 const TCache_Class objs_glyph_class
=
1423 TT_Error
TTObjs_Init( PEngine_Instance engine
)
1425 PCache face_cache
, exec_cache
;
1432 if ( ALLOC( face_cache
, sizeof ( TCache
) ) ||
1433 ALLOC( exec_cache
, sizeof ( TCache
) ) )
1436 /* create face cache */
1437 error
= Cache_Create( engine
, (PCache_Class
)&objs_face_class
,
1438 face_cache
, &engine
->lock
);
1442 engine
->objs_face_cache
= face_cache
;
1444 error
= Cache_Create( engine
, (PCache_Class
)&objs_exec_class
,
1445 exec_cache
, &engine
->lock
);
1449 engine
->objs_exec_cache
= exec_cache
;
1451 engine
->objs_face_class
= (PCache_Class
)&objs_face_class
;
1452 engine
->objs_instance_class
= (PCache_Class
)&objs_instance_class
;
1453 engine
->objs_execution_class
= (PCache_Class
)&objs_exec_class
;
1454 engine
->objs_glyph_class
= (PCache_Class
)&objs_glyph_class
;
1467 /*******************************************************************
1469 * Function : TTObjs_Done
1471 * Description : The TTObjs component finalizer.
1473 * Input : engine engine instance
1475 * Output : Error code.
1477 ******************************************************************/
1480 TT_Error
TTObjs_Done( PEngine_Instance engine
)
1482 /* destroy all active faces and contexts before releasing the */
1484 Cache_Destroy( (TCache
*)engine
->objs_exec_cache
);
1485 Cache_Destroy( (TCache
*)engine
->objs_face_cache
);
1487 /* Now frees caches and cache classes */
1488 FREE( engine
->objs_exec_cache
);
1489 FREE( engine
->objs_face_cache
);