1 /* Copyright (C) 2003 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: ttobjs.c,v 1.9 2004/12/21 20:13:41 igor Exp $ */
18
19 /* Changes after FreeType: cut out the TrueType instruction interpreter. */
20
21 /*******************************************************************
22 *
23 * ttobjs.c 1.0
24 *
25 * Objects manager.
26 *
27 * Copyright 1996-1998 by
28 * David Turner, Robert Wilhelm, and Werner Lemberg.
29 *
30 * This file is part of the FreeType project, and may only be used
31 * modified and distributed under the terms of the FreeType project
32 * license, LICENSE.TXT. By continuing to use, modify, or distribute
33 * this file you indicate that you have read the license and
34 * understand and accept it fully.
35 *
36 ******************************************************************/
37
38 #include "ttmisc.h"
39
40 #include "ttfoutl.h"
41 #include "ttobjs.h"
42 #include "ttcalc.h"
43 #include "ttload.h"
44 #include "ttinterp.h"
45
46 /* Add extensions definition */
47 #ifdef TT_EXTEND_ENGINE
48 #endif
49
50
51
52 /*******************************************************************
53 * *
54 * CODERANGE FUNCTIONS *
55 * *
56 * *
57 *******************************************************************/
58
59 /*******************************************************************
60 *
61 * Function : Goto_CodeRange
62 *
63 * Description : Switch to a new code range (updates Code and IP).
64 *
65 * Input : exec target execution context
66 * range new execution code range
67 * IP new IP in new code range
68 *
69 * Output : SUCCESS on success. FAILURE on error (no code range).
70 *
71 *****************************************************************/
72
Goto_CodeRange(PExecution_Context exec,Int range,Int IP)73 TT_Error Goto_CodeRange( PExecution_Context exec, Int range, Int IP )
74 {
75 PCodeRange cr;
76
77
78 if ( range < 1 || range > 3 )
79 return TT_Err_Bad_Argument;
80
81 cr = &exec->codeRangeTable[range - 1];
82
83 if ( cr->Base == NULL )
84 return TT_Err_Invalid_CodeRange;
85
86 /* NOTE: Because the last instruction of a program may be a CALL */
87 /* which will return to the first byte *after* the code */
88 /* range, we test for IP <= Size, instead of IP < Size. */
89
90 if ( IP > cr->Size )
91 return TT_Err_Code_Overflow;
92
93 exec->code = cr->Base;
94 exec->codeSize = cr->Size;
95 exec->IP = IP;
96 exec->curRange = range;
97
98 return TT_Err_Ok;
99 }
100
101 /*******************************************************************
102 *
103 * Function : Unset_CodeRange
104 *
105 * Description : Unsets the code range pointer.
106 *
107 * Input : exec target execution context
108 *
109 * Output :
110 *
111 * Note : The pointer must be unset after used to avoid pending pointers
112 * while a garbager invokation.
113 *
114 *****************************************************************/
115
Unset_CodeRange(PExecution_Context exec)116 void Unset_CodeRange( PExecution_Context exec )
117 {
118 exec->code = 0;
119 exec->codeSize = 0;
120 }
121
122 /*******************************************************************
123 *
124 * Function : Get_CodeRange
125 *
126 * Description : Returns a pointer to a given code range. Should
127 * be used only by the debugger. Returns NULL if
128 * 'range' is out of current bounds.
129 *
130 * Input : exec target execution context
131 * range new execution code range
132 *
133 * Output : Pointer to the code range record. NULL on failure.
134 *
135 *****************************************************************/
136
Get_CodeRange(PExecution_Context exec,Int range)137 PCodeRange Get_CodeRange( PExecution_Context exec, Int range )
138 {
139 if ( range < 1 || range > 3 )
140 return (PCodeRange)NULL;
141 else /* arrays start with 1 in Pascal, and with 0 in C */
142 return &exec->codeRangeTable[range - 1];
143 }
144
145
146 /*******************************************************************
147 *
148 * Function : Set_CodeRange
149 *
150 * Description : Sets a code range.
151 *
152 * Input : exec target execution context
153 * range code range index
154 * base new code base
155 * length sange size in bytes
156 *
157 * Output : SUCCESS on success. FAILURE on error.
158 *
159 *****************************************************************/
160
Set_CodeRange(PExecution_Context exec,Int range,void * base,Int length)161 TT_Error Set_CodeRange( PExecution_Context exec,
162 Int range,
163 void* base,
164 Int length )
165 {
166 if ( range < 1 || range > 3 )
167 return TT_Err_Bad_Argument;
168
169 exec->codeRangeTable[range - 1].Base = (unsigned char*)base;
170 exec->codeRangeTable[range - 1].Size = length;
171
172 return TT_Err_Ok;
173 }
174
175
176 /*******************************************************************
177 *
178 * Function : Clear_CodeRange
179 *
180 * Description : Clears a code range.
181 *
182 * Input : exec target execution context
183 * range code range index
184 *
185 * Output : SUCCESS on success. FAILURE on error.
186 *
187 * Note : Does not set the Error variable.
188 *
189 *****************************************************************/
190
Clear_CodeRange(PExecution_Context exec,Int range)191 TT_Error Clear_CodeRange( PExecution_Context exec, Int range )
192 {
193 if ( range < 1 || range > 3 )
194 return TT_Err_Bad_Argument;
195
196 exec->codeRangeTable[range - 1].Base = (Byte*)NULL;
197 exec->codeRangeTable[range - 1].Size = 0;
198
199 return TT_Err_Ok;
200 }
201
202
203
204 /*******************************************************************
205 * *
206 * EXECUTION CONTEXT ROUTINES *
207 * *
208 * *
209 *******************************************************************/
210
211
212 #define FREE(ptr) { mem->free(mem, ptr, "ttobjs.c"); ptr = NULL; }
213 #define ALLOC_ARRAY(ptr, old_count, count, type) \
214 (old_count >= count ? 0 : \
215 !(free_aux(mem, ptr), \
216 ptr = mem->alloc_bytes(mem, (count) * sizeof(type), "ttobjs.c")))
217 #define SETMAX(a, b) a = (a > b ? a : b)
218
free_aux(ttfMemory * mem,void * ptr)219 static int free_aux(ttfMemory *mem, void *ptr)
220 {
221 mem->free(mem, ptr, "ttobjs.c");
222 return 0;
223 }
224
225 /*******************************************************************
226 *
227 * Function : Context_Destroy
228 *
229 *****************************************************************/
230
Context_Destroy(void * _context)231 TT_Error Context_Destroy( void* _context )
232 {
233 PExecution_Context exec = (PExecution_Context)_context;
234 ttfMemory *mem;
235
236 if ( !exec )
237 return TT_Err_Ok;
238 if ( !exec->current_face ) {
239 /* This may happen while closing a high level device, when allocator runs out of memory.
240 A test case is 01_001.pdf with pdfwrite and a small vmthreshold.
241 */
242 return TT_Err_Out_Of_Memory;
243 }
244 if (--exec->lock)
245 return TT_Err_Ok; /* Still in use */
246
247 mem = exec->current_face->font->tti->ttf_memory;
248
249 /* points zone */
250 FREE( exec->pts.cur_y );
251 FREE( exec->pts.cur_x );
252 FREE( exec->pts.org_y );
253 FREE( exec->pts.org_x );
254 FREE( exec->pts.touch );
255 FREE( exec->pts.contours );
256 exec->pts.n_points = 0;
257 exec->pts.n_contours = 0;
258
259 /* twilight zone */
260 FREE( exec->twilight.touch );
261 FREE( exec->twilight.cur_y );
262 FREE( exec->twilight.cur_x );
263 FREE( exec->twilight.org_y );
264 FREE( exec->twilight.org_x );
265 FREE( exec->twilight.contours );
266 exec->twilight.n_points = 0;
267 exec->twilight.n_contours = 0;
268
269 /* free stack */
270 FREE( exec->stack );
271 exec->stackSize = 0;
272
273 /* free call stack */
274 FREE( exec->callStack );
275 exec->callSize = 0;
276 exec->callTop = 0;
277
278 /* free glyph code range */
279 exec->glyphSize = 0;
280 exec->maxGlyphSize = 0;
281
282 exec->current_face = (PFace)NULL;
283
284 return TT_Err_Ok;
285 }
286
287 /*******************************************************************
288 *
289 * Function : Context_Create
290 *
291 *****************************************************************/
292
Context_Create(void * _context,void * _face)293 TT_Error Context_Create( void* _context, void* _face )
294 {
295 /* Note : The function name is a kind of misleading due to our improvement.
296 * Now it adjusts (enhances) the context for the specified face.
297 * We keep the old Free Type's name for easier localization of our changes.
298 * The context must be initialized with zeros before the first call.
299 * (igorm).
300 */
301 PExecution_Context exec = (PExecution_Context)_context;
302
303 PFace face = (PFace)_face;
304 ttfMemory *mem = face->font->tti->ttf_memory;
305 TMaxProfile *maxp = &face->maxProfile;
306 Int n_points, n_twilight;
307 Int callSize, stackSize;
308
309 callSize = 32;
310
311 /* reserve a little extra for broken fonts like courbs or timesbs */
312 stackSize = maxp->maxStackElements + 32;
313
314 n_points = face->maxPoints + 2;
315 n_twilight = maxp->maxTwilightPoints;
316
317 if ( ALLOC_ARRAY( exec->callStack, exec->callSize, callSize, TCallRecord ) ||
318 /* reserve interpreter call stack */
319
320 ALLOC_ARRAY( exec->stack, exec->stackSize, stackSize, Long ) ||
321 /* reserve interpreter stack */
322
323 ALLOC_ARRAY( exec->pts.org_x, exec->n_points, n_points, TT_F26Dot6 ) ||
324 ALLOC_ARRAY( exec->pts.org_y, exec->n_points, n_points, TT_F26Dot6 ) ||
325 ALLOC_ARRAY( exec->pts.cur_x, exec->n_points, n_points, TT_F26Dot6 ) ||
326 ALLOC_ARRAY( exec->pts.cur_y, exec->n_points, n_points, TT_F26Dot6 ) ||
327 ALLOC_ARRAY( exec->pts.touch, exec->n_points, n_points, Byte ) ||
328 /* reserve points zone */
329
330 ALLOC_ARRAY( exec->twilight.org_x, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
331 ALLOC_ARRAY( exec->twilight.org_y, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
332 ALLOC_ARRAY( exec->twilight.cur_x, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
333 ALLOC_ARRAY( exec->twilight.cur_y, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
334 ALLOC_ARRAY( exec->twilight.touch, exec->twilight.n_points, n_twilight, Byte ) ||
335 /* reserve twilight zone */
336
337 ALLOC_ARRAY( exec->pts.contours, exec->n_contours, face->maxContours, UShort )
338 /* reserve contours array */
339 )
340 goto Fail_Memory;
341
342 SETMAX(exec->callSize, callSize);
343 SETMAX(exec->stackSize, stackSize);
344 SETMAX(exec->twilight.n_points, n_twilight);
345 SETMAX(exec->maxGlyphSize, maxp->maxSizeOfInstructions);
346 SETMAX(exec->n_contours, face->maxContours);
347 SETMAX(exec->n_points, n_points);
348 exec->lock++;
349
350 return TT_Err_Ok;
351
352 Fail_Memory:
353 /* Context_Destroy( exec ); Don't release buffers because the context is shared. */
354 return TT_Err_Out_Of_Memory;
355 }
356
357
358 /*******************************************************************
359 *
360 * Function : Context_Load
361 *
362 *****************************************************************/
363
Context_Load(PExecution_Context exec,PInstance ins)364 TT_Error Context_Load( PExecution_Context exec,
365 PInstance ins )
366 {
367 Int i;
368
369
370 exec->current_face = ins->face;
371
372 exec->numFDefs = ins->numFDefs;
373 exec->numIDefs = ins->numIDefs;
374 exec->FDefs = ins->FDefs;
375 exec->IDefs = ins->IDefs;
376 exec->countIDefs = ins->countIDefs;
377 memcpy(exec->IDefPtr, ins->IDefPtr, sizeof(exec->IDefPtr));
378
379 exec->metrics = ins->metrics;
380
381 for ( i = 0; i < MAX_CODE_RANGES; i++ )
382 exec->codeRangeTable[i] = ins->codeRangeTable[i];
383
384 exec->pts.n_points = 0;
385 exec->pts.n_contours = 0;
386
387 exec->instruction_trap = FALSE;
388
389 /* set default graphics state */
390 exec->GS = ins->GS;
391
392 exec->cvtSize = ins->cvtSize;
393 exec->cvt = ins->cvt;
394
395 exec->storeSize = ins->storeSize;
396 exec->storage = ins->storage;
397
398 return TT_Err_Ok;
399 }
400
401
402 /*******************************************************************
403 *
404 * Function : Context_Save
405 *
406 *****************************************************************/
407
Context_Save(PExecution_Context exec,PInstance ins)408 TT_Error Context_Save( PExecution_Context exec,
409 PInstance ins )
410 {
411 Int i;
412
413 for ( i = 0; i < MAX_CODE_RANGES; i++ ) {
414 ins->codeRangeTable[i] = exec->codeRangeTable[i];
415 exec->codeRangeTable[i].Base = 0;
416 exec->codeRangeTable[i].Size = 0;
417 }
418 exec->numFDefs = 0;
419 exec->numIDefs = 0;
420 memcpy(ins->IDefPtr, exec->IDefPtr, sizeof(ins->IDefPtr));
421 ins->countIDefs = exec->countIDefs;
422 exec->countIDefs = 0;
423 exec->FDefs = 0;
424 exec->IDefs = 0;
425 exec->cvtSize = 0;
426 exec->cvt = 0;
427 exec->storeSize = 0;
428 exec->storage = 0;
429 exec->current_face = 0;
430
431 return TT_Err_Ok;
432 }
433
434
435 /*******************************************************************
436 *
437 * Function : Context_Run
438 *
439 *****************************************************************/
440
Context_Run(PExecution_Context exec,Bool debug)441 TT_Error Context_Run( PExecution_Context exec,
442 Bool debug )
443 {
444 TT_Error error;
445
446
447 if ( ( error = Goto_CodeRange( exec, TT_CodeRange_Glyph, 0 ) ) )
448 return error;
449
450 exec->zp0 = exec->pts;
451 exec->zp1 = exec->pts;
452 exec->zp2 = exec->pts;
453
454 exec->GS.gep0 = 1;
455 exec->GS.gep1 = 1;
456 exec->GS.gep2 = 1;
457
458 exec->GS.projVector.x = 0x4000;
459 exec->GS.projVector.y = 0x0000;
460
461 exec->GS.freeVector = exec->GS.projVector;
462 exec->GS.dualVector = exec->GS.projVector;
463
464 exec->GS.round_state = 1;
465 exec->GS.loop = 1;
466
467 /* some glyphs leave something on the stack. so we clean it */
468 /* before a new execution. */
469 exec->top = 0;
470 exec->callTop = 0;
471
472 if ( !debug ) {
473 error = RunIns( exec );
474 Unset_CodeRange(exec);
475 return error;
476 } else
477 return TT_Err_Ok;
478 }
479
480
481 const TGraphicsState Default_GraphicsState =
482 {
483 0, 0, 0,
484 { 0x4000, 0 },
485 { 0x4000, 0 },
486 { 0x4000, 0 },
487 1, 64, 1,
488 TRUE, 68, 0, 0, 9, 3,
489 0, FALSE, 2, 1, 1, 1
490 };
491
492
493
494 /*******************************************************************
495 * *
496 * INSTANCE FUNCTIONS *
497 * *
498 * *
499 *******************************************************************/
500
501 /*******************************************************************
502 *
503 * Function : Instance_Destroy
504 *
505 * Description :
506 *
507 * Input : _instance the instance object to destroy
508 *
509 * Output : error code.
510 *
511 ******************************************************************/
512
Instance_Destroy(void * _instance)513 TT_Error Instance_Destroy( void* _instance )
514 {
515 PInstance ins = (PInstance)_instance;
516 ttfMemory *mem;
517
518 if ( !_instance )
519 return TT_Err_Ok;
520 if ( !ins->face ) {
521 /* This may happen while closing a high level device, when allocator runs out of memory.
522 A test case is 01_001.pdf with pdfwrite and a small vmthreshold.
523 */
524 return TT_Err_Out_Of_Memory;
525 }
526 mem = ins->face->font->tti->ttf_memory;
527
528 FREE( ins->cvt );
529 ins->cvtSize = 0;
530
531 FREE( ins->FDefs );
532 FREE( ins->IDefs );
533 FREE( ins->storage );
534 ins->numFDefs = 0;
535 ins->numIDefs = 0;
536
537 ins->face = (PFace)NULL;
538 ins->valid = FALSE;
539
540 return TT_Err_Ok;
541 }
542
543
544 /*******************************************************************
545 *
546 * Function : Instance_Create
547 *
548 * Description :
549 *
550 * Input : _instance instance record to initialize
551 * _face parent face object
552 *
553 * Output : Error code. All partially built subtables are
554 * released on error.
555 *
556 ******************************************************************/
557
Instance_Create(void * _instance,void * _face)558 TT_Error Instance_Create( void* _instance,
559 void* _face )
560 {
561 PInstance ins = (PInstance)_instance;
562 PFace face = (PFace)_face;
563 ttfMemory *mem = face->font->tti->ttf_memory;
564 PMaxProfile maxp = &face->maxProfile;
565 Int i;
566
567 ins->FDefs=NULL;
568 ins->IDefs=NULL;
569 ins->cvt=NULL;
570 ins->storage=NULL;
571
572 ins->face = face;
573 ins->valid = FALSE;
574
575 ins->numFDefs = maxp->maxFunctionDefs;
576 ins->numIDefs = maxp->maxInstructionDefs;
577 ins->countIDefs = 0;
578 if (maxp->maxInstructionDefs > 255)
579 goto Fail_Memory;
580 memset(ins->IDefPtr, (Byte)ins->numIDefs, sizeof(ins->IDefPtr));
581 if (ins->numFDefs < 50)
582 ins->numFDefs = 50; /* Bug 687858 */
583 ins->cvtSize = face->cvtSize;
584
585 ins->metrics.pointSize = 10 * 64; /* default pointsize = 10pts */
586
587 ins->metrics.x_resolution = 96; /* default resolution = 96dpi */
588 ins->metrics.y_resolution = 96;
589
590 ins->metrics.x_ppem = 0;
591 ins->metrics.y_ppem = 0;
592
593 ins->metrics.rotated = FALSE;
594 ins->metrics.stretched = FALSE;
595
596 ins->storeSize = maxp->maxStorage;
597
598 for ( i = 0; i < 4; i++ )
599 ins->metrics.compensations[i] = 0; /* Default compensations */
600
601 if ( ALLOC_ARRAY( ins->FDefs, 0, ins->numFDefs, TDefRecord ) ||
602 ALLOC_ARRAY( ins->IDefs, 0, ins->numIDefs, TDefRecord ) ||
603 ALLOC_ARRAY( ins->cvt, 0, ins->cvtSize, Long ) ||
604 ALLOC_ARRAY( ins->storage, 0, ins->storeSize, Long ) )
605 goto Fail_Memory;
606
607 memset (ins->FDefs, 0, ins->numFDefs * sizeof(TDefRecord));
608 memset (ins->IDefs, 0, ins->numIDefs * sizeof(TDefRecord));
609
610 ins->GS = Default_GraphicsState;
611
612 return TT_Err_Ok;
613
614 Fail_Memory:
615 Instance_Destroy( ins );
616 return TT_Err_Out_Of_Memory;
617 }
618
619 /*******************************************************************
620 *
621 * Function : Instance_Init
622 *
623 * Description : Initialize a fresh new instance.
624 * Executes the font program if any is found.
625 *
626 * Input : _instance the instance object to destroy
627 *
628 * Output : Error code.
629 *
630 ******************************************************************/
631
Instance_Init(PInstance ins)632 TT_Error Instance_Init( PInstance ins )
633 {
634 PExecution_Context exec;
635
636 TT_Error error;
637 PFace face = ins->face;
638
639 exec = ins->face->font->exec;
640 /* debugging instances have their own context */
641
642 ins->GS = Default_GraphicsState;
643
644 Context_Load( exec, ins );
645
646 exec->callTop = 0;
647 exec->top = 0;
648
649 exec->period = 64;
650 exec->phase = 0;
651 exec->threshold = 0;
652
653 exec->metrics.x_ppem = 0;
654 exec->metrics.y_ppem = 0;
655 exec->metrics.pointSize = 0;
656 exec->metrics.x_scale1 = 0;
657 exec->metrics.x_scale2 = 1;
658 exec->metrics.y_scale1 = 0;
659 exec->metrics.y_scale2 = 1;
660
661 exec->metrics.ppem = 0;
662 exec->metrics.scale1 = 0;
663 exec->metrics.scale2 = 1;
664 exec->metrics.ratio = 1 << 16;
665
666 exec->instruction_trap = FALSE;
667
668 exec->cvtSize = ins->cvtSize;
669 exec->cvt = ins->cvt;
670
671 exec->F_dot_P = 0x10000;
672
673 /* allow font program execution */
674 Set_CodeRange( exec,
675 TT_CodeRange_Font,
676 face->fontProgram,
677 face->fontPgmSize );
678
679 /* disable CVT and glyph programs coderange */
680 Clear_CodeRange( exec, TT_CodeRange_Cvt );
681 Clear_CodeRange( exec, TT_CodeRange_Glyph );
682
683 if ( face->fontPgmSize > 0 )
684 {
685 error = Goto_CodeRange( exec, TT_CodeRange_Font, 0 );
686 if ( error )
687 goto Fin;
688
689 error = RunIns( exec );
690 Unset_CodeRange(exec);
691 }
692 else
693 error = TT_Err_Ok;
694
695 Fin:
696 Context_Save( exec, ins );
697
698 ins->valid = FALSE;
699
700 return error;
701 }
702
703
704 /*******************************************************************
705 *
706 * Function : Instance_Reset
707 *
708 * Description : Resets an instance to a new pointsize/transform.
709 * Executes the cvt program if any is found.
710 *
711 * Input : _instance the instance object to destroy
712 *
713 * Output : Error code.
714 *
715 ******************************************************************/
716
Instance_Reset(PInstance ins,Bool debug)717 TT_Error Instance_Reset( PInstance ins,
718 Bool debug )
719 {
720 TT_Error error;
721 Int i;
722 PFace face = ins->face;
723 PExecution_Context exec = ins->face->font->exec;
724
725 if ( !ins )
726 return TT_Err_Invalid_Instance_Handle;
727
728 if ( ins->valid )
729 return TT_Err_Ok;
730
731 if ( ins->metrics.x_ppem < 1 ||
732 ins->metrics.y_ppem < 1 )
733 return TT_Err_Invalid_PPem;
734
735 /* compute new transformation */
736 if ( ins->metrics.x_ppem >= ins->metrics.y_ppem )
737 {
738 ins->metrics.scale1 = ins->metrics.x_scale1;
739 ins->metrics.scale2 = ins->metrics.x_scale2;
740 ins->metrics.ppem = ins->metrics.x_ppem;
741 ins->metrics.x_ratio = 1 << 16;
742 ins->metrics.y_ratio = MulDiv_Round( ins->metrics.y_ppem,
743 0x10000,
744 ins->metrics.x_ppem );
745 }
746 else
747 {
748 ins->metrics.scale1 = ins->metrics.y_scale1;
749 ins->metrics.scale2 = ins->metrics.y_scale2;
750 ins->metrics.ppem = ins->metrics.y_ppem;
751 ins->metrics.x_ratio = MulDiv_Round( ins->metrics.x_ppem,
752 0x10000,
753 ins->metrics.y_ppem );
754 ins->metrics.y_ratio = 1 << 16;
755 }
756
757 /* Scale the cvt values to the new ppem. */
758 /* We use by default the y ppem to scale the CVT. */
759
760 for ( i = 0; i < ins->cvtSize; i++ )
761 ins->cvt[i] = MulDiv_Round( face->cvt[i],
762 ins->metrics.scale1,
763 ins->metrics.scale2 );
764
765 ins->GS = Default_GraphicsState;
766
767 /* get execution context and run prep program */
768
769 Context_Load( exec, ins );
770
771 Set_CodeRange( exec,
772 TT_CodeRange_Cvt,
773 face->cvtProgram,
774 face->cvtPgmSize );
775
776 Clear_CodeRange( exec, TT_CodeRange_Glyph );
777
778 for ( i = 0; i < exec->storeSize; i++ )
779 exec->storage[i] = 0;
780
781 exec->instruction_trap = FALSE;
782
783 exec->top = 0;
784 exec->callTop = 0;
785
786 /* All twilight points are originally zero */
787
788 for ( i = 0; i < exec->twilight.n_points; i++ )
789 {
790 exec->twilight.org_x[i] = 0;
791 exec->twilight.org_y[i] = 0;
792 exec->twilight.cur_x[i] = 0;
793 exec->twilight.cur_y[i] = 0;
794 }
795
796 if ( face->cvtPgmSize > 0 )
797 {
798 error = Goto_CodeRange( exec, TT_CodeRange_Cvt, 0 );
799 if (error)
800 goto Fin;
801
802 error = RunIns( exec );
803 Unset_CodeRange(exec);
804 }
805 else
806 error = TT_Err_Ok;
807
808 ins->GS = exec->GS;
809 /* save default graphics state */
810
811 Fin:
812 Context_Save( exec, ins );
813
814 if ( !error )
815 ins->valid = TRUE;
816
817 return error;
818 }
819
820
821 /*******************************************************************
822 * *
823 * FACE FUNCTIONS *
824 * *
825 * *
826 *******************************************************************/
827
828 /*******************************************************************
829 *
830 * Function : Face_Destroy
831 *
832 * Description : The face object destructor.
833 *
834 * Input : _face typeless pointer to the face object to destroy
835 *
836 * Output : Error code.
837 *
838 ******************************************************************/
839
Face_Destroy(PFace face)840 TT_Error Face_Destroy( PFace face )
841 {
842 ttfMemory *mem = face->font->tti->ttf_memory;
843 if ( !face )
844 return TT_Err_Ok;
845
846 /* freeing the CVT */
847 FREE( face->cvt );
848 face->cvtSize = 0;
849
850 /* freeing the programs */
851 FREE( face->fontProgram );
852 FREE( face->cvtProgram );
853 face->fontPgmSize = 0;
854 face->cvtPgmSize = 0;
855
856 return TT_Err_Ok;
857 }
858
859
860 /*******************************************************************
861 *
862 * Function : Face_Create
863 *
864 * Description : The face object constructor.
865 *
866 * Input : _face face record to build
867 * _input input stream where to load font data
868 *
869 * Output : Error code.
870 *
871 * NOTE : The input stream is kept in the face object. The
872 * caller shouldn't destroy it after calling Face_Create().
873 *
874 ******************************************************************/
875
876 #define LOAD_( table ) \
877 ( error = Load_TrueType_##table (face) )
878
879
Face_Create(PFace face)880 TT_Error Face_Create( PFace face)
881 {
882 TT_Error error;
883
884 /* Load tables */
885
886 if ( /*LOAD_(Header) ||*/
887 LOAD_(MaxProfile) ||
888 /*LOAD_(Locations) ||*/
889 /*LOAD_(CMap) ||*/
890 LOAD_(CVT) ||
891 /*LOAD_(Horizontal_Header) ||*/
892 LOAD_(Programs)
893 /*LOAD_(HMTX) ||*/
894 /*LOAD_(Gasp) ||*/
895 /*LOAD_(Names) ||*/
896 /*LOAD_(OS2) ||*/
897 /*LOAD_(PostScript) ||*/
898 /*LOAD_(Hdmx) */
899 )
900 goto Fail;
901
902 return TT_Err_Ok;
903
904 Fail :
905 Face_Destroy( face );
906 return error;
907 }
908
909
910
911
912 /*******************************************************************
913 *
914 * Function : Scale_X
915 *
916 * Description : scale an horizontal distance from font
917 * units to 26.6 pixels
918 *
919 * Input : metrics pointer to metrics
920 * x value to scale
921 *
922 * Output : scaled value
923 *
924 ******************************************************************/
925
Scale_X(PIns_Metrics metrics,TT_Pos x)926 TT_Pos Scale_X( PIns_Metrics metrics, TT_Pos x )
927 {
928 return MulDiv_Round( x, metrics->x_scale1, metrics->x_scale2 );
929 }
930
931 /*******************************************************************
932 *
933 * Function : Scale_Y
934 *
935 * Description : scale a vertical distance from font
936 * units to 26.6 pixels
937 *
938 * Input : metrics pointer to metrics
939 * y value to scale
940 *
941 * Output : scaled value
942 *
943 ******************************************************************/
944
Scale_Y(PIns_Metrics metrics,TT_Pos y)945 TT_Pos Scale_Y( PIns_Metrics metrics, TT_Pos y )
946 {
947 return MulDiv_Round( y, metrics->y_scale1, metrics->y_scale2 );
948 }
949
950