Coverage Report

Created: 2025-06-10 07:27

/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
21.6k
  {
72
21.6k
    PCodeRange  cr;
73
74
21.6k
    if ( range < 1 || range > 3 )
75
0
      return TT_Err_Bad_Argument;
76
77
21.6k
    cr = &exec->codeRangeTable[range - 1];
78
79
21.6k
    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
21.6k
    if ( IP > cr->Size )
87
0
      return TT_Err_Code_Overflow;
88
89
21.6k
    exec->code     = cr->Base;
90
21.6k
    exec->codeSize = cr->Size;
91
21.6k
    exec->IP       = IP;
92
21.6k
    exec->curRange = range;
93
94
21.6k
    return TT_Err_Ok;
95
21.6k
  }
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
87.7k
  {
114
87.7k
    exec->code = 0;
115
87.7k
    exec->codeSize = 0;
116
87.7k
  }
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
72.6k
  {
161
72.6k
    if ( range < 1 || range > 3 )
162
0
      return TT_Err_Bad_Argument;
163
164
72.6k
    exec->codeRangeTable[range - 1].Base = (unsigned char*)base;
165
72.6k
    exec->codeRangeTable[range - 1].Size = length;
166
167
72.6k
    return TT_Err_Ok;
168
72.6k
  }
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
75.8k
  {
187
75.8k
    if ( range < 1 || range > 3 )
188
0
      return TT_Err_Bad_Argument;
189
190
75.8k
    exec->codeRangeTable[range - 1].Base = (Byte*)NULL;
191
75.8k
    exec->codeRangeTable[range - 1].Size = 0;
192
193
75.8k
    return TT_Err_Ok;
194
75.8k
  }
195
196
/*******************************************************************
197
 *                                                                 *
198
 *                EXECUTION CONTEXT ROUTINES                       *
199
 *                                                                 *
200
 *                                                                 *
201
 *******************************************************************/
202
203
46.9k
#define FREE(ptr) { mem->free(mem, ptr, "ttobjs.c"); ptr = NULL; }
204
#define ALLOC_ARRAY(ptr, old_count, count, type) \
205
103k
        (old_count >= count ? 0 : \
206
103k
          !(free_aux(mem, ptr),   \
207
47.9k
            ptr = mem->alloc_bytes(mem, (count) * sizeof(type), "ttobjs.c")))
208
209
19.3k
#define SETMAX(a, b) a = (a > b ? a : b)
210
211
static int free_aux(ttfMemory *mem, void *ptr)
212
47.9k
{
213
47.9k
    mem->free(mem, ptr, "ttobjs.c");
214
47.9k
    return 0;
215
47.9k
}
216
217
/*******************************************************************
218
 *
219
 *  Function    :  Context_Destroy
220
 *
221
 *****************************************************************/
222
223
 TT_Error  Context_Destroy( void*  _context )
224
3.23k
 {
225
3.23k
   PExecution_Context  exec = (PExecution_Context)_context;
226
3.23k
   ttfMemory *mem;
227
228
3.23k
   if ( !exec )
229
0
     return TT_Err_Ok;
230
3.23k
   if (--exec->lock)
231
1.49k
     return TT_Err_Ok; /* Still in use */
232
1.73k
   mem = exec->memory;
233
1.73k
   if (!mem)
234
0
     return TT_Err_Ok; /* Never used */
235
236
   /* points zone */
237
1.73k
   FREE( exec->pts.cur_y );
238
1.73k
   FREE( exec->pts.cur_x );
239
1.73k
   FREE( exec->pts.org_y );
240
1.73k
   FREE( exec->pts.org_x );
241
1.73k
   FREE( exec->pts.touch );
242
1.73k
   FREE( exec->pts.contours );
243
1.73k
   exec->pts.n_points   = 0;
244
1.73k
   exec->pts.n_contours = 0;
245
246
   /* twilight zone */
247
1.73k
   FREE( exec->twilight.touch );
248
1.73k
   FREE( exec->twilight.cur_y );
249
1.73k
   FREE( exec->twilight.cur_x );
250
1.73k
   FREE( exec->twilight.org_y );
251
1.73k
   FREE( exec->twilight.org_x );
252
1.73k
   FREE( exec->twilight.contours );
253
1.73k
   exec->twilight.n_points   = 0;
254
1.73k
   exec->twilight.n_contours = 0;
255
256
   /* free stack */
257
1.73k
   FREE( exec->stack );
258
1.73k
   exec->stackSize = 0;
259
260
   /* free call stack */
261
1.73k
   FREE( exec->callStack );
262
1.73k
   exec->callSize = 0;
263
1.73k
   exec->callTop  = 0;
264
265
   /* free glyph code range */
266
1.73k
   exec->glyphSize = 0;
267
1.73k
   exec->maxGlyphSize = 0;
268
269
1.73k
   exec->current_face    = (PFace)NULL;
270
271
1.73k
   return TT_Err_Ok;
272
1.73k
 }
273
274
/*******************************************************************
275
 *
276
 *  Function    :  Context_Create
277
 *
278
 *****************************************************************/
279
280
 TT_Error  Context_Create( void*  _context, void*  _face )
281
3.23k
 {
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
3.23k
   PExecution_Context  exec = (PExecution_Context)_context;
289
290
3.23k
   PFace        face = (PFace)_face;
291
3.23k
   ttfMemory   *mem = face->font->tti->ttf_memory;
292
3.23k
   TMaxProfile *maxp = &face->maxProfile;
293
3.23k
   Int          n_points, n_twilight;
294
3.23k
   Int          callSize, stackSize;
295
296
3.23k
   callSize  = 32;
297
3.23k
   exec->memory = mem;
298
299
   /* reserve a little extra for broken fonts like courbs or timesbs */
300
3.23k
   stackSize = maxp->maxStackElements + 32;
301
302
3.23k
   n_points        = face->maxPoints + 2;
303
3.23k
   n_twilight      = maxp->maxTwilightPoints;
304
3.23k
   if (n_points < 100)
305
453
       n_points = 100; /* Bug 689907 */
306
307
3.23k
   exec->n_contours = exec->n_points = 0;
308
3.23k
   exec->twilight.n_points = 0;
309
310
3.23k
   if ( ALLOC_ARRAY( exec->callStack, exec->callSize, callSize, TCallRecord ) ||
311
        /* reserve interpreter call stack */
312
313
3.23k
        ALLOC_ARRAY( exec->stack, exec->stackSize, stackSize, Long )           ||
314
        /* reserve interpreter stack */
315
316
3.23k
        ALLOC_ARRAY( exec->pts.org_x, exec->n_points, n_points, TT_F26Dot6 )        ||
317
3.23k
        ALLOC_ARRAY( exec->pts.org_y, exec->n_points, n_points, TT_F26Dot6 )        ||
318
3.23k
        ALLOC_ARRAY( exec->pts.cur_x, exec->n_points, n_points, TT_F26Dot6 )        ||
319
3.23k
        ALLOC_ARRAY( exec->pts.cur_y, exec->n_points, n_points, TT_F26Dot6 )        ||
320
3.23k
        ALLOC_ARRAY( exec->pts.touch, exec->n_points, n_points, Byte )                          ||
321
        /* reserve points zone */
322
323
3.23k
        ALLOC_ARRAY( exec->twilight.org_x, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
324
3.23k
        ALLOC_ARRAY( exec->twilight.org_y, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
325
3.23k
        ALLOC_ARRAY( exec->twilight.cur_x, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
326
3.23k
        ALLOC_ARRAY( exec->twilight.cur_y, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
327
3.23k
        ALLOC_ARRAY( exec->twilight.touch, exec->twilight.n_points, n_twilight, Byte )                   ||
328
        /* reserve twilight zone */
329
330
3.23k
        ALLOC_ARRAY( exec->pts.contours, exec->n_contours, face->maxContours, UShort )
331
        /* reserve contours array */
332
3.23k
      ) {
333
0
       goto Fail_Memory;
334
0
   }
335
336
3.23k
   SETMAX(exec->callSize, callSize);
337
3.23k
   SETMAX(exec->stackSize, stackSize);
338
3.23k
   SETMAX(exec->twilight.n_points, n_twilight);
339
3.23k
   SETMAX(exec->maxGlyphSize, maxp->maxSizeOfInstructions);
340
3.23k
   SETMAX(exec->n_contours, face->maxContours);
341
3.23k
   SETMAX(exec->n_points, n_points);
342
3.23k
   exec->lock++;
343
344
3.23k
   memset(exec->pts.contours, 0x00, exec->n_contours * sizeof(UShort));
345
346
3.23k
   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
3.23k
 }
352
353
/*******************************************************************
354
 *
355
 *  Function    :  Context_Load
356
 *
357
 *****************************************************************/
358
359
 TT_Error Context_Load( PExecution_Context  exec,
360
                        PInstance           ins )
361
81.4k
 {
362
81.4k
   Int  i;
363
364
81.4k
   exec->current_face = ins->face;
365
366
81.4k
   exec->numFDefs = ins->numFDefs;
367
81.4k
   exec->numIDefs = ins->numIDefs;
368
81.4k
   exec->FDefs    = ins->FDefs;
369
81.4k
   exec->IDefs    = ins->IDefs;
370
81.4k
   exec->countIDefs = ins->countIDefs;
371
81.4k
   memcpy(exec->IDefPtr, ins->IDefPtr, sizeof(exec->IDefPtr));
372
373
81.4k
   exec->metrics  = ins->metrics;
374
375
325k
   for ( i = 0; i < MAX_CODE_RANGES; i++ )
376
244k
     exec->codeRangeTable[i] = ins->codeRangeTable[i];
377
378
81.4k
   exec->pts.n_points   = 0;
379
81.4k
   exec->pts.n_contours = 0;
380
381
81.4k
   exec->instruction_trap = FALSE;
382
383
   /* set default graphics state */
384
81.4k
   exec->GS = ins->GS;
385
386
81.4k
   exec->cvtSize = ins->cvtSize;
387
81.4k
   exec->cvt     = ins->cvt;
388
389
81.4k
   exec->storeSize = ins->storeSize;
390
81.4k
   exec->storage   = ins->storage;
391
392
81.4k
   return TT_Err_Ok;
393
81.4k
 }
394
395
/*******************************************************************
396
 *
397
 *  Function    :  Context_Save
398
 *
399
 *****************************************************************/
400
401
 TT_Error  Context_Save( PExecution_Context  exec,
402
                         PInstance           ins )
403
81.4k
 {
404
81.4k
   Int  i;
405
406
325k
   for ( i = 0; i < MAX_CODE_RANGES; i++ ) {
407
244k
     ins->codeRangeTable[i] = exec->codeRangeTable[i];
408
244k
     exec->codeRangeTable[i].Base = 0;
409
244k
     exec->codeRangeTable[i].Size = 0;
410
244k
   }
411
81.4k
   exec->numFDefs = 0;
412
81.4k
   exec->numIDefs = 0;
413
81.4k
   memcpy(ins->IDefPtr, exec->IDefPtr, sizeof(ins->IDefPtr));
414
81.4k
   ins->countIDefs = exec->countIDefs;
415
81.4k
   exec->countIDefs = 0;
416
81.4k
   exec->FDefs    = 0;
417
81.4k
   exec->IDefs    = 0;
418
81.4k
   exec->cvtSize = 0;
419
81.4k
   exec->cvt     = 0;
420
81.4k
   exec->storeSize = 0;
421
81.4k
   exec->storage   = 0;
422
81.4k
   exec->current_face = 0;
423
424
81.4k
   return TT_Err_Ok;
425
81.4k
 }
426
427
/*******************************************************************
428
 *
429
 *  Function    :  Context_Run
430
 *
431
 *****************************************************************/
432
433
 TT_Error  Context_Run( PExecution_Context  exec,
434
                        Bool                debug )
435
15.3k
 {
436
15.3k
   TT_Error  error;
437
438
15.3k
   if ( ( error = Goto_CodeRange( exec, TT_CodeRange_Glyph, 0 ) ) )
439
0
     return error;
440
441
15.3k
   exec->zp0 = exec->pts;
442
15.3k
   exec->zp1 = exec->pts;
443
15.3k
   exec->zp2 = exec->pts;
444
445
15.3k
   exec->GS.gep0 = 1;
446
15.3k
   exec->GS.gep1 = 1;
447
15.3k
   exec->GS.gep2 = 1;
448
449
15.3k
   exec->GS.projVector.x = 0x4000;
450
15.3k
   exec->GS.projVector.y = 0x0000;
451
452
15.3k
   exec->GS.freeVector = exec->GS.projVector;
453
15.3k
   exec->GS.dualVector = exec->GS.projVector;
454
455
15.3k
   exec->GS.round_state = 1;
456
15.3k
   exec->GS.loop        = 1;
457
458
   /* some glyphs leave something on the stack. so we clean it */
459
   /* before a new execution.                                  */
460
15.3k
   exec->top     = 0;
461
15.3k
   exec->callTop = 0;
462
463
15.3k
   if ( !debug ) {
464
15.3k
     error = RunIns( exec );
465
15.3k
     Unset_CodeRange(exec);
466
15.3k
     return error;
467
15.3k
   } else
468
0
     return TT_Err_Ok;
469
15.3k
 }
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
3.23k
  {
503
3.23k
    PInstance  ins = (PInstance)_instance;
504
3.23k
    ttfMemory *mem;
505
506
3.23k
    if ( !_instance )
507
0
      return TT_Err_Ok;
508
3.23k
    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
3.23k
    mem = ins->face->font->tti->ttf_memory;
515
516
3.23k
    FREE( ins->cvt );
517
3.23k
    ins->cvtSize = 0;
518
519
3.23k
    FREE( ins->FDefs );
520
3.23k
    FREE( ins->IDefs );
521
3.23k
    FREE( ins->storage );
522
3.23k
    ins->numFDefs = 0;
523
3.23k
    ins->numIDefs = 0;
524
525
3.23k
    ins->face = (PFace)NULL;
526
3.23k
    ins->valid = FALSE;
527
528
3.23k
    return TT_Err_Ok;
529
3.23k
  }
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
3.23k
  {
548
3.23k
    PInstance ins  = (PInstance)_instance;
549
3.23k
    PFace     face = (PFace)_face;
550
3.23k
    ttfMemory *mem = face->font->tti->ttf_memory;
551
3.23k
    PMaxProfile  maxp = &face->maxProfile;
552
3.23k
    Int       i;
553
554
3.23k
    ins->FDefs=NULL;
555
3.23k
    ins->IDefs=NULL;
556
3.23k
    ins->cvt=NULL;
557
3.23k
    ins->storage=NULL;
558
559
3.23k
    ins->face = face;
560
3.23k
    ins->valid = FALSE;
561
562
3.23k
    ins->numFDefs = maxp->maxFunctionDefs;
563
3.23k
    ins->numIDefs = maxp->maxInstructionDefs;
564
3.23k
    ins->countIDefs = 0;
565
3.23k
    if (maxp->maxInstructionDefs > 255)
566
116
        maxp->maxInstructionDefs = 255;  /* Bug 689960 */
567
3.23k
    memset(ins->IDefPtr, (Byte)ins->numIDefs, sizeof(ins->IDefPtr));
568
3.23k
    if (ins->numFDefs < 50)
569
450
        ins->numFDefs = 50; /* Bug 687858 */
570
3.23k
    ins->cvtSize  = face->cvtSize;
571
572
3.23k
    ins->metrics.pointSize    = 10 * 64;     /* default pointsize  = 10pts */
573
574
3.23k
    ins->metrics.x_resolution = 96;          /* default resolution = 96dpi */
575
3.23k
    ins->metrics.y_resolution = 96;
576
577
3.23k
    ins->metrics.x_ppem = 0;
578
3.23k
    ins->metrics.y_ppem = 0;
579
580
3.23k
    ins->metrics.rotated   = FALSE;
581
3.23k
    ins->metrics.stretched = FALSE;
582
583
3.23k
    ins->storeSize = maxp->maxStorage;
584
585
16.1k
    for ( i = 0; i < 4; i++ )
586
12.9k
      ins->metrics.compensations[i] = 0;     /* Default compensations */
587
588
3.23k
    if ( ALLOC_ARRAY( ins->FDefs, 0, ins->numFDefs, TDefRecord )  ||
589
3.23k
         ALLOC_ARRAY( ins->IDefs, 0, ins->numIDefs, TDefRecord )  ||
590
3.23k
         ALLOC_ARRAY( ins->cvt, 0, ins->cvtSize, Long )           ||
591
3.23k
         ALLOC_ARRAY( ins->storage, 0, ins->storeSize, Long )     )
592
0
      goto Fail_Memory;
593
594
3.23k
    memset (ins->FDefs, 0, ins->numFDefs * sizeof(TDefRecord));
595
3.23k
    memset (ins->IDefs, 0, ins->numIDefs * sizeof(TDefRecord));
596
597
3.23k
    ins->GS = Default_GraphicsState;
598
599
3.23k
    return TT_Err_Ok;
600
601
0
  Fail_Memory:
602
0
    Instance_Destroy( ins );
603
0
    return TT_Err_Out_Of_Memory;
604
3.23k
  }
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
3.23k
  {
621
3.23k
    PExecution_Context  exec;
622
623
3.23k
    TT_Error  error;
624
3.23k
    PFace     face = ins->face;
625
626
3.23k
    exec = ins->face->font->exec;
627
    /* debugging instances have their own context */
628
629
3.23k
    ins->GS = Default_GraphicsState;
630
631
3.23k
    Context_Load( exec, ins );
632
633
3.23k
    exec->callTop   = 0;
634
3.23k
    exec->top       = 0;
635
636
3.23k
    exec->period    = 64;
637
3.23k
    exec->phase     = 0;
638
3.23k
    exec->threshold = 0;
639
640
3.23k
    exec->metrics.x_ppem    = 0;
641
3.23k
    exec->metrics.y_ppem    = 0;
642
3.23k
    exec->metrics.pointSize = 0;
643
3.23k
    exec->metrics.x_scale1  = 0;
644
3.23k
    exec->metrics.x_scale2  = 1;
645
3.23k
    exec->metrics.y_scale1  = 0;
646
3.23k
    exec->metrics.y_scale2  = 1;
647
648
3.23k
    exec->metrics.ppem      = 0;
649
3.23k
    exec->metrics.scale1    = 0;
650
3.23k
    exec->metrics.scale2    = 1;
651
3.23k
    exec->metrics.ratio     = 1 << 16;
652
653
3.23k
    exec->instruction_trap = FALSE;
654
655
3.23k
    exec->cvtSize = ins->cvtSize;
656
3.23k
    exec->cvt     = ins->cvt;
657
658
3.23k
    exec->F_dot_P = 0x10000;
659
660
    /* allow font program execution */
661
3.23k
    Set_CodeRange( exec,
662
3.23k
                   TT_CodeRange_Font,
663
3.23k
                   face->fontProgram,
664
3.23k
                   face->fontPgmSize );
665
666
    /* disable CVT and glyph programs coderange */
667
3.23k
    Clear_CodeRange( exec, TT_CodeRange_Cvt );
668
3.23k
    Clear_CodeRange( exec, TT_CodeRange_Glyph );
669
670
3.23k
    if ( face->fontPgmSize > 0 )
671
3.11k
    {
672
3.11k
      error = Goto_CodeRange( exec, TT_CodeRange_Font, 0 );
673
3.11k
      if ( error )
674
0
        goto Fin;
675
676
3.11k
      exec->zp0 = exec->pts;
677
3.11k
      exec->zp1 = exec->pts;
678
3.11k
      exec->zp2 = exec->pts;
679
680
3.11k
      exec->GS.gep0 = 1;
681
3.11k
      exec->GS.gep1 = 1;
682
3.11k
      exec->GS.gep2 = 1;
683
684
3.11k
      exec->GS.projVector.x = 0x4000;
685
3.11k
      exec->GS.projVector.y = 0x0000;
686
687
3.11k
      exec->GS.freeVector = exec->GS.projVector;
688
3.11k
      exec->GS.dualVector = exec->GS.projVector;
689
690
3.11k
      exec->GS.round_state = 1;
691
3.11k
      exec->GS.loop        = 1;
692
693
      /* some glyphs leave something on the stack. so we clean it */
694
      /* before a new execution.                                  */
695
3.11k
      exec->top     = 0;
696
3.11k
      exec->callTop = 0;
697
698
3.11k
      error = RunIns( exec );
699
3.11k
      Unset_CodeRange(exec);
700
3.11k
    }
701
119
    else
702
119
      error = TT_Err_Ok;
703
704
3.23k
  Fin:
705
3.23k
    Context_Save( exec, ins );
706
707
3.23k
    ins->valid = FALSE;
708
709
3.23k
    return error;
710
3.23k
  }
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
3.23k
  {
728
3.23k
    TT_Error  error;
729
3.23k
    Int       i;
730
3.23k
    PFace     face;
731
3.23k
    PExecution_Context exec;
732
733
3.23k
    if ( !ins )
734
0
      return TT_Err_Invalid_Instance_Handle;
735
736
3.23k
    if ( ins->valid )
737
0
      return TT_Err_Ok;
738
739
3.23k
    face = ins->face;
740
3.23k
    exec = face->font->exec;
741
742
3.23k
    if ( ins->metrics.x_ppem < 1 ||
743
3.23k
         ins->metrics.y_ppem < 1 )
744
0
      return TT_Err_Invalid_PPem;
745
746
    /* compute new transformation */
747
3.23k
    if ( ins->metrics.x_ppem >= ins->metrics.y_ppem )
748
3.23k
    {
749
3.23k
      ins->metrics.scale1  = ins->metrics.x_scale1;
750
3.23k
      ins->metrics.scale2  = ins->metrics.x_scale2;
751
3.23k
      ins->metrics.ppem    = ins->metrics.x_ppem;
752
3.23k
      ins->metrics.x_ratio = 1 << 16;
753
3.23k
      ins->metrics.y_ratio = MulDiv_Round( ins->metrics.y_ppem,
754
3.23k
                                           0x10000,
755
3.23k
                                           ins->metrics.x_ppem );
756
3.23k
    }
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
2.11M
    for ( i = 0; i < ins->cvtSize; i++ )
772
2.11M
      ins->cvt[i] = MulDiv_Round( face->cvt[i],
773
2.11M
                                  ins->metrics.scale1,
774
2.11M
                                  ins->metrics.scale2 );
775
776
3.23k
    ins->GS = Default_GraphicsState;
777
778
    /* get execution context and run prep program */
779
780
3.23k
    Context_Load( exec, ins );
781
782
3.23k
    Set_CodeRange( exec,
783
3.23k
                   TT_CodeRange_Cvt,
784
3.23k
                   face->cvtProgram,
785
3.23k
                   face->cvtPgmSize );
786
787
3.23k
    Clear_CodeRange( exec, TT_CodeRange_Glyph );
788
789
3.03M
    for ( i = 0; i < exec->storeSize; i++ )
790
3.03M
      exec->storage[i] = 0;
791
792
3.23k
    exec->instruction_trap = FALSE;
793
794
3.23k
    exec->top     = 0;
795
3.23k
    exec->callTop = 0;
796
797
    /* All twilight points are originally zero */
798
799
2.57M
    for ( i = 0; i < exec->twilight.n_points; i++ )
800
2.57M
    {
801
2.57M
      exec->twilight.org_x[i] = 0;
802
2.57M
      exec->twilight.org_y[i] = 0;
803
2.57M
      exec->twilight.cur_x[i] = 0;
804
2.57M
      exec->twilight.cur_y[i] = 0;
805
2.57M
    }
806
807
3.23k
    if ( face->cvtPgmSize > 0 )
808
3.11k
    {
809
3.11k
      error = Goto_CodeRange( exec, TT_CodeRange_Cvt, 0 );
810
3.11k
      if (error)
811
0
        goto Fin;
812
813
3.11k
      exec->zp0 = exec->pts;
814
3.11k
      exec->zp1 = exec->pts;
815
3.11k
      exec->zp2 = exec->pts;
816
817
3.11k
      exec->GS.gep0 = 1;
818
3.11k
      exec->GS.gep1 = 1;
819
3.11k
      exec->GS.gep2 = 1;
820
821
3.11k
      exec->GS.projVector.x = 0x4000;
822
3.11k
      exec->GS.projVector.y = 0x0000;
823
824
3.11k
      exec->GS.freeVector = exec->GS.projVector;
825
3.11k
      exec->GS.dualVector = exec->GS.projVector;
826
827
3.11k
      exec->GS.round_state = 1;
828
3.11k
      exec->GS.loop        = 1;
829
830
      /* some glyphs leave something on the stack. so we clean it */
831
      /* before a new execution.                                  */
832
3.11k
      exec->top     = 0;
833
3.11k
      exec->callTop = 0;
834
835
3.11k
      error = RunIns( exec );
836
3.11k
      Unset_CodeRange(exec);
837
3.11k
    }
838
119
    else
839
119
      error = TT_Err_Ok;
840
841
3.23k
    ins->GS = exec->GS;
842
    /* save default graphics state */
843
844
3.23k
  Fin:
845
3.23k
    Context_Save( exec, ins );
846
847
3.23k
    if ( !error )
848
2.55k
      ins->valid = TRUE;
849
850
3.23k
    return error;
851
3.23k
  }
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
3.23k
  {
874
3.23k
    if ( face ) {
875
3.23k
        ttfMemory *mem = face->font->tti->ttf_memory;
876
877
        /* freeing the CVT */
878
3.23k
        FREE( face->cvt );
879
3.23k
        face->cvtSize = 0;
880
881
        /* freeing the programs */
882
3.23k
        FREE( face->fontProgram );
883
3.23k
        FREE( face->cvtProgram );
884
3.23k
        face->fontPgmSize = 0;
885
3.23k
        face->cvtPgmSize  = 0;
886
3.23k
    }
887
3.23k
    return TT_Err_Ok;
888
3.23k
  }
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
16.1k
          ( error = Load_TrueType_##table (face) )
908
909
  TT_Error  Face_Create( PFace  face)
910
3.23k
  {
911
3.23k
    TT_Error      error;
912
913
    /* Load tables */
914
915
3.23k
    if ( /*LOAD_(Header)                      ||*/
916
3.23k
         LOAD_(MaxProfile)                  ||
917
         /*LOAD_(Locations)                   ||*/
918
         /*LOAD_(CMap)                        ||*/
919
3.23k
         LOAD_(CVT)                         ||
920
         /*LOAD_(Horizontal_Header)           ||*/
921
3.23k
         LOAD_(Programs)
922
         /*LOAD_(HMTX)                        ||*/
923
         /*LOAD_(Gasp)                        ||*/
924
         /*LOAD_(Names)                       ||*/
925
         /*LOAD_(OS2)                         ||*/
926
         /*LOAD_(PostScript)                  ||*/
927
         /*LOAD_(Hdmx)                        */
928
3.23k
        )
929
0
      goto Fail;
930
931
3.23k
    return TT_Err_Ok;
932
933
0
  Fail :
934
0
    Face_Destroy( face );
935
0
    return error;
936
3.23k
  }
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
2.48M
 {
954
2.48M
   return MulDiv_Round( x, metrics->x_scale1, metrics->x_scale2 );
955
2.48M
 }
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
2.48M
 {
973
2.48M
   return MulDiv_Round( y, metrics->y_scale1, metrics->y_scale2 );
974
2.48M
 }