Coverage Report

Created: 2025-06-24 07:01

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