Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/ttobjs.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, 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
135k
  {
72
135k
    PCodeRange  cr;
73
74
135k
    if ( range < 1 || range > 3 )
75
0
      return TT_Err_Bad_Argument;
76
77
135k
    cr = &exec->codeRangeTable[range - 1];
78
79
135k
    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
135k
    if ( IP > cr->Size )
87
0
      return TT_Err_Code_Overflow;
88
89
135k
    exec->code     = cr->Base;
90
135k
    exec->codeSize = cr->Size;
91
135k
    exec->IP       = IP;
92
135k
    exec->curRange = range;
93
94
135k
    return TT_Err_Ok;
95
135k
  }
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
241k
  {
114
241k
    exec->code = 0;
115
241k
    exec->codeSize = 0;
116
241k
  }
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
244k
  {
161
244k
    if ( range < 1 || range > 3 )
162
0
      return TT_Err_Bad_Argument;
163
164
244k
    exec->codeRangeTable[range - 1].Base = (unsigned char*)base;
165
244k
    exec->codeRangeTable[range - 1].Size = length;
166
167
244k
    return TT_Err_Ok;
168
244k
  }
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
313k
  {
187
313k
    if ( range < 1 || range > 3 )
188
0
      return TT_Err_Bad_Argument;
189
190
313k
    exec->codeRangeTable[range - 1].Base = (Byte*)NULL;
191
313k
    exec->codeRangeTable[range - 1].Size = 0;
192
193
313k
    return TT_Err_Ok;
194
313k
  }
195
196
/*******************************************************************
197
 *                                                                 *
198
 *                EXECUTION CONTEXT ROUTINES                       *
199
 *                                                                 *
200
 *                                                                 *
201
 *******************************************************************/
202
203
508k
#define FREE(ptr) { mem->free(mem, ptr, "ttobjs.c"); ptr = NULL; }
204
#define ALLOC_ARRAY(ptr, old_count, count, type) \
205
2.21M
        (old_count >= count ? 0 : \
206
2.21M
          !(free_aux(mem, ptr),   \
207
905k
            ptr = mem->alloc_bytes(mem, (count) * sizeof(type), "ttobjs.c")))
208
415k
#define SETMAX(a, b) a = (a > b ? a : b)
209
210
static int free_aux(ttfMemory *mem, void *ptr)
211
905k
{
212
905k
    mem->free(mem, ptr, "ttobjs.c");
213
905k
    return 0;
214
905k
}
215
216
/*******************************************************************
217
 *
218
 *  Function    :  Context_Destroy
219
 *
220
 *****************************************************************/
221
222
 TT_Error  Context_Destroy( void*  _context )
223
69.2k
 {
224
69.2k
   PExecution_Context  exec = (PExecution_Context)_context;
225
69.2k
   ttfMemory *mem;
226
227
69.2k
   if ( !exec )
228
0
     return TT_Err_Ok;
229
69.2k
   if (--exec->lock)
230
67.5k
     return TT_Err_Ok; /* Still in use */
231
1.69k
   mem = exec->memory;
232
1.69k
   if (!mem)
233
0
     return TT_Err_Ok; /* Never used */
234
235
   /* points zone */
236
1.69k
   FREE( exec->pts.cur_y );
237
1.69k
   FREE( exec->pts.cur_x );
238
1.69k
   FREE( exec->pts.org_y );
239
1.69k
   FREE( exec->pts.org_x );
240
1.69k
   FREE( exec->pts.touch );
241
1.69k
   FREE( exec->pts.contours );
242
1.69k
   exec->pts.n_points   = 0;
243
1.69k
   exec->pts.n_contours = 0;
244
245
   /* twilight zone */
246
1.69k
   FREE( exec->twilight.touch );
247
1.69k
   FREE( exec->twilight.cur_y );
248
1.69k
   FREE( exec->twilight.cur_x );
249
1.69k
   FREE( exec->twilight.org_y );
250
1.69k
   FREE( exec->twilight.org_x );
251
1.69k
   FREE( exec->twilight.contours );
252
1.69k
   exec->twilight.n_points   = 0;
253
1.69k
   exec->twilight.n_contours = 0;
254
255
   /* free stack */
256
1.69k
   FREE( exec->stack );
257
1.69k
   exec->stackSize = 0;
258
259
   /* free call stack */
260
1.69k
   FREE( exec->callStack );
261
1.69k
   exec->callSize = 0;
262
1.69k
   exec->callTop  = 0;
263
264
   /* free glyph code range */
265
1.69k
   exec->glyphSize = 0;
266
1.69k
   exec->maxGlyphSize = 0;
267
268
1.69k
   exec->current_face    = (PFace)NULL;
269
270
1.69k
   return TT_Err_Ok;
271
1.69k
 }
272
273
/*******************************************************************
274
 *
275
 *  Function    :  Context_Create
276
 *
277
 *****************************************************************/
278
279
 TT_Error  Context_Create( void*  _context, void*  _face )
280
69.2k
 {
281
   /* Note : The function name is a kind of misleading due to our improvement.
282
    * Now it adjusts (enhances) the context for the specified face.
283
    * We keep the old Free Type's name for easier localization of our changes.
284
    * The context must be initialized with zeros before the first call.
285
    * (igorm).
286
    */
287
69.2k
   PExecution_Context  exec = (PExecution_Context)_context;
288
289
69.2k
   PFace        face = (PFace)_face;
290
69.2k
   ttfMemory   *mem = face->font->tti->ttf_memory;
291
69.2k
   TMaxProfile *maxp = &face->maxProfile;
292
69.2k
   Int          n_points, n_twilight;
293
69.2k
   Int          callSize, stackSize;
294
295
69.2k
   callSize  = 32;
296
69.2k
   exec->memory = mem;
297
298
   /* reserve a little extra for broken fonts like courbs or timesbs */
299
69.2k
   stackSize = maxp->maxStackElements + 32;
300
301
69.2k
   n_points        = face->maxPoints + 2;
302
69.2k
   n_twilight      = maxp->maxTwilightPoints;
303
69.2k
   if (n_points < 100)
304
16.4k
       n_points = 100; /* Bug 689907 */
305
306
69.2k
   exec->n_contours = exec->n_points = 0;
307
69.2k
   exec->twilight.n_points = 0;
308
309
69.2k
   if ( ALLOC_ARRAY( exec->callStack, exec->callSize, callSize, TCallRecord ) ||
310
        /* reserve interpreter call stack */
311
312
69.2k
        ALLOC_ARRAY( exec->stack, exec->stackSize, stackSize, Long )           ||
313
        /* reserve interpreter stack */
314
315
69.2k
        ALLOC_ARRAY( exec->pts.org_x, exec->n_points, n_points, TT_F26Dot6 )        ||
316
69.2k
        ALLOC_ARRAY( exec->pts.org_y, exec->n_points, n_points, TT_F26Dot6 )        ||
317
69.2k
        ALLOC_ARRAY( exec->pts.cur_x, exec->n_points, n_points, TT_F26Dot6 )        ||
318
69.2k
        ALLOC_ARRAY( exec->pts.cur_y, exec->n_points, n_points, TT_F26Dot6 )        ||
319
69.2k
        ALLOC_ARRAY( exec->pts.touch, exec->n_points, n_points, Byte )                          ||
320
        /* reserve points zone */
321
322
69.2k
        ALLOC_ARRAY( exec->twilight.org_x, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
323
69.2k
        ALLOC_ARRAY( exec->twilight.org_y, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
324
69.2k
        ALLOC_ARRAY( exec->twilight.cur_x, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
325
69.2k
        ALLOC_ARRAY( exec->twilight.cur_y, exec->twilight.n_points, n_twilight, TT_F26Dot6 ) ||
326
69.2k
        ALLOC_ARRAY( exec->twilight.touch, exec->twilight.n_points, n_twilight, Byte )                   ||
327
        /* reserve twilight zone */
328
329
69.2k
        ALLOC_ARRAY( exec->pts.contours, exec->n_contours, face->maxContours, UShort )
330
        /* reserve contours array */
331
69.2k
      )
332
0
     goto Fail_Memory;
333
334
69.2k
     SETMAX(exec->callSize, callSize);
335
69.2k
     SETMAX(exec->stackSize, stackSize);
336
69.2k
     SETMAX(exec->twilight.n_points, n_twilight);
337
69.2k
     SETMAX(exec->maxGlyphSize, maxp->maxSizeOfInstructions);
338
69.2k
     SETMAX(exec->n_contours, face->maxContours);
339
69.2k
     SETMAX(exec->n_points, n_points);
340
69.2k
     exec->lock++;
341
342
69.2k
     return TT_Err_Ok;
343
344
0
  Fail_Memory:
345
    /* Context_Destroy( exec ); Don't release buffers because the context is shared. */
346
0
    return TT_Err_Out_Of_Memory;
347
69.2k
 }
348
349
/*******************************************************************
350
 *
351
 *  Function    :  Context_Load
352
 *
353
 *****************************************************************/
354
355
 TT_Error Context_Load( PExecution_Context  exec,
356
                        PInstance           ins )
357
262k
 {
358
262k
   Int  i;
359
360
262k
   exec->current_face = ins->face;
361
362
262k
   exec->numFDefs = ins->numFDefs;
363
262k
   exec->numIDefs = ins->numIDefs;
364
262k
   exec->FDefs    = ins->FDefs;
365
262k
   exec->IDefs    = ins->IDefs;
366
262k
   exec->countIDefs = ins->countIDefs;
367
262k
   memcpy(exec->IDefPtr, ins->IDefPtr, sizeof(exec->IDefPtr));
368
369
262k
   exec->metrics  = ins->metrics;
370
371
1.05M
   for ( i = 0; i < MAX_CODE_RANGES; i++ )
372
788k
     exec->codeRangeTable[i] = ins->codeRangeTable[i];
373
374
262k
   exec->pts.n_points   = 0;
375
262k
   exec->pts.n_contours = 0;
376
377
262k
   exec->instruction_trap = FALSE;
378
379
   /* set default graphics state */
380
262k
   exec->GS = ins->GS;
381
382
262k
   exec->cvtSize = ins->cvtSize;
383
262k
   exec->cvt     = ins->cvt;
384
385
262k
   exec->storeSize = ins->storeSize;
386
262k
   exec->storage   = ins->storage;
387
388
262k
   return TT_Err_Ok;
389
262k
 }
390
391
/*******************************************************************
392
 *
393
 *  Function    :  Context_Save
394
 *
395
 *****************************************************************/
396
397
 TT_Error  Context_Save( PExecution_Context  exec,
398
                         PInstance           ins )
399
262k
 {
400
262k
   Int  i;
401
402
1.05M
   for ( i = 0; i < MAX_CODE_RANGES; i++ ) {
403
788k
     ins->codeRangeTable[i] = exec->codeRangeTable[i];
404
788k
     exec->codeRangeTable[i].Base = 0;
405
788k
     exec->codeRangeTable[i].Size = 0;
406
788k
   }
407
262k
   exec->numFDefs = 0;
408
262k
   exec->numIDefs = 0;
409
262k
   memcpy(ins->IDefPtr, exec->IDefPtr, sizeof(ins->IDefPtr));
410
262k
   ins->countIDefs = exec->countIDefs;
411
262k
   exec->countIDefs = 0;
412
262k
   exec->FDefs    = 0;
413
262k
   exec->IDefs    = 0;
414
262k
   exec->cvtSize = 0;
415
262k
   exec->cvt     = 0;
416
262k
   exec->storeSize = 0;
417
262k
   exec->storage   = 0;
418
262k
   exec->current_face = 0;
419
420
262k
   return TT_Err_Ok;
421
262k
 }
422
423
/*******************************************************************
424
 *
425
 *  Function    :  Context_Run
426
 *
427
 *****************************************************************/
428
429
 TT_Error  Context_Run( PExecution_Context  exec,
430
                        Bool                debug )
431
16.5k
 {
432
16.5k
   TT_Error  error;
433
434
16.5k
   if ( ( error = Goto_CodeRange( exec, TT_CodeRange_Glyph, 0 ) ) )
435
0
     return error;
436
437
16.5k
   exec->zp0 = exec->pts;
438
16.5k
   exec->zp1 = exec->pts;
439
16.5k
   exec->zp2 = exec->pts;
440
441
16.5k
   exec->GS.gep0 = 1;
442
16.5k
   exec->GS.gep1 = 1;
443
16.5k
   exec->GS.gep2 = 1;
444
445
16.5k
   exec->GS.projVector.x = 0x4000;
446
16.5k
   exec->GS.projVector.y = 0x0000;
447
448
16.5k
   exec->GS.freeVector = exec->GS.projVector;
449
16.5k
   exec->GS.dualVector = exec->GS.projVector;
450
451
16.5k
   exec->GS.round_state = 1;
452
16.5k
   exec->GS.loop        = 1;
453
454
   /* some glyphs leave something on the stack. so we clean it */
455
   /* before a new execution.                                  */
456
16.5k
   exec->top     = 0;
457
16.5k
   exec->callTop = 0;
458
459
16.5k
   if ( !debug ) {
460
16.5k
     error = RunIns( exec );
461
16.5k
     Unset_CodeRange(exec);
462
16.5k
     return error;
463
16.5k
   } else
464
0
     return TT_Err_Ok;
465
16.5k
 }
466
467
  const TGraphicsState  Default_GraphicsState =
468
  {
469
    0, 0, 0,
470
    { 0x4000, 0 },
471
    { 0x4000, 0 },
472
    { 0x4000, 0 },
473
    1, 64, 1,
474
    TRUE, 68, 0, 0, 9, 3,
475
    0, FALSE, 2, 1, 1, 1
476
  };
477
478
/*******************************************************************
479
 *                                                                 *
480
 *                     INSTANCE  FUNCTIONS                         *
481
 *                                                                 *
482
 *                                                                 *
483
 *******************************************************************/
484
485
/*******************************************************************
486
 *
487
 *  Function    : Instance_Destroy
488
 *
489
 *  Description :
490
 *
491
 *  Input  :  _instance   the instance object to destroy
492
 *
493
 *  Output :  error code.
494
 *
495
 ******************************************************************/
496
497
  TT_Error  Instance_Destroy( void* _instance )
498
69.2k
  {
499
69.2k
    PInstance  ins = (PInstance)_instance;
500
69.2k
    ttfMemory *mem;
501
502
69.2k
    if ( !_instance )
503
0
      return TT_Err_Ok;
504
69.2k
    if ( !ins->face ) {
505
      /* This may happen while closing a high level device, when allocator runs out of memory.
506
         A test case is 01_001.pdf with pdfwrite and a small vmthreshold.
507
      */
508
0
      return TT_Err_Out_Of_Memory;
509
0
    }
510
69.2k
    mem = ins->face->font->tti->ttf_memory;
511
512
69.2k
    FREE( ins->cvt );
513
69.2k
    ins->cvtSize = 0;
514
515
69.2k
    FREE( ins->FDefs );
516
69.2k
    FREE( ins->IDefs );
517
69.2k
    FREE( ins->storage );
518
69.2k
    ins->numFDefs = 0;
519
69.2k
    ins->numIDefs = 0;
520
521
69.2k
    ins->face = (PFace)NULL;
522
69.2k
    ins->valid = FALSE;
523
524
69.2k
    return TT_Err_Ok;
525
69.2k
  }
526
527
/*******************************************************************
528
 *
529
 *  Function    : Instance_Create
530
 *
531
 *  Description :
532
 *
533
 *  Input  :  _instance    instance record to initialize
534
 *            _face        parent face object
535
 *
536
 *  Output :  Error code.  All partially built subtables are
537
 *            released on error.
538
 *
539
 ******************************************************************/
540
541
  TT_Error  Instance_Create( void*  _instance,
542
                             void*  _face )
543
69.2k
  {
544
69.2k
    PInstance ins  = (PInstance)_instance;
545
69.2k
    PFace     face = (PFace)_face;
546
69.2k
    ttfMemory *mem = face->font->tti->ttf_memory;
547
69.2k
    PMaxProfile  maxp = &face->maxProfile;
548
69.2k
    Int       i;
549
550
69.2k
    ins->FDefs=NULL;
551
69.2k
    ins->IDefs=NULL;
552
69.2k
    ins->cvt=NULL;
553
69.2k
    ins->storage=NULL;
554
555
69.2k
    ins->face = face;
556
69.2k
    ins->valid = FALSE;
557
558
69.2k
    ins->numFDefs = maxp->maxFunctionDefs;
559
69.2k
    ins->numIDefs = maxp->maxInstructionDefs;
560
69.2k
    ins->countIDefs = 0;
561
69.2k
    if (maxp->maxInstructionDefs > 255)
562
4.49k
        maxp->maxInstructionDefs = 255;  /* Bug 689960 */
563
69.2k
    memset(ins->IDefPtr, (Byte)ins->numIDefs, sizeof(ins->IDefPtr));
564
69.2k
    if (ins->numFDefs < 50)
565
36.7k
        ins->numFDefs = 50; /* Bug 687858 */
566
69.2k
    ins->cvtSize  = face->cvtSize;
567
568
69.2k
    ins->metrics.pointSize    = 10 * 64;     /* default pointsize  = 10pts */
569
570
69.2k
    ins->metrics.x_resolution = 96;          /* default resolution = 96dpi */
571
69.2k
    ins->metrics.y_resolution = 96;
572
573
69.2k
    ins->metrics.x_ppem = 0;
574
69.2k
    ins->metrics.y_ppem = 0;
575
576
69.2k
    ins->metrics.rotated   = FALSE;
577
69.2k
    ins->metrics.stretched = FALSE;
578
579
69.2k
    ins->storeSize = maxp->maxStorage;
580
581
346k
    for ( i = 0; i < 4; i++ )
582
276k
      ins->metrics.compensations[i] = 0;     /* Default compensations */
583
584
69.2k
    if ( ALLOC_ARRAY( ins->FDefs, 0, ins->numFDefs, TDefRecord )  ||
585
69.2k
         ALLOC_ARRAY( ins->IDefs, 0, ins->numIDefs, TDefRecord )  ||
586
69.2k
         ALLOC_ARRAY( ins->cvt, 0, ins->cvtSize, Long )           ||
587
69.2k
         ALLOC_ARRAY( ins->storage, 0, ins->storeSize, Long )     )
588
0
      goto Fail_Memory;
589
590
69.2k
    memset (ins->FDefs, 0, ins->numFDefs * sizeof(TDefRecord));
591
69.2k
    memset (ins->IDefs, 0, ins->numIDefs * sizeof(TDefRecord));
592
593
69.2k
    ins->GS = Default_GraphicsState;
594
595
69.2k
    return TT_Err_Ok;
596
597
0
  Fail_Memory:
598
0
    Instance_Destroy( ins );
599
0
    return TT_Err_Out_Of_Memory;
600
69.2k
  }
601
602
/*******************************************************************
603
 *
604
 *  Function    : Instance_Init
605
 *
606
 *  Description : Initialize a fresh new instance.
607
 *                Executes the font program if any is found.
608
 *
609
 *  Input  :  _instance   the instance object to destroy
610
 *
611
 *  Output :  Error code.
612
 *
613
 ******************************************************************/
614
615
  TT_Error  Instance_Init( PInstance  ins )
616
69.2k
  {
617
69.2k
    PExecution_Context  exec;
618
619
69.2k
    TT_Error  error;
620
69.2k
    PFace     face = ins->face;
621
622
69.2k
    exec = ins->face->font->exec;
623
    /* debugging instances have their own context */
624
625
69.2k
    ins->GS = Default_GraphicsState;
626
627
69.2k
    Context_Load( exec, ins );
628
629
69.2k
    exec->callTop   = 0;
630
69.2k
    exec->top       = 0;
631
632
69.2k
    exec->period    = 64;
633
69.2k
    exec->phase     = 0;
634
69.2k
    exec->threshold = 0;
635
636
69.2k
    exec->metrics.x_ppem    = 0;
637
69.2k
    exec->metrics.y_ppem    = 0;
638
69.2k
    exec->metrics.pointSize = 0;
639
69.2k
    exec->metrics.x_scale1  = 0;
640
69.2k
    exec->metrics.x_scale2  = 1;
641
69.2k
    exec->metrics.y_scale1  = 0;
642
69.2k
    exec->metrics.y_scale2  = 1;
643
644
69.2k
    exec->metrics.ppem      = 0;
645
69.2k
    exec->metrics.scale1    = 0;
646
69.2k
    exec->metrics.scale2    = 1;
647
69.2k
    exec->metrics.ratio     = 1 << 16;
648
649
69.2k
    exec->instruction_trap = FALSE;
650
651
69.2k
    exec->cvtSize = ins->cvtSize;
652
69.2k
    exec->cvt     = ins->cvt;
653
654
69.2k
    exec->F_dot_P = 0x10000;
655
656
    /* allow font program execution */
657
69.2k
    Set_CodeRange( exec,
658
69.2k
                   TT_CodeRange_Font,
659
69.2k
                   face->fontProgram,
660
69.2k
                   face->fontPgmSize );
661
662
    /* disable CVT and glyph programs coderange */
663
69.2k
    Clear_CodeRange( exec, TT_CodeRange_Cvt );
664
69.2k
    Clear_CodeRange( exec, TT_CodeRange_Glyph );
665
666
69.2k
    if ( face->fontPgmSize > 0 )
667
59.5k
    {
668
59.5k
      error = Goto_CodeRange( exec, TT_CodeRange_Font, 0 );
669
59.5k
      if ( error )
670
0
        goto Fin;
671
672
59.5k
      exec->zp0 = exec->pts;
673
59.5k
      exec->zp1 = exec->pts;
674
59.5k
      exec->zp2 = exec->pts;
675
676
59.5k
      exec->GS.gep0 = 1;
677
59.5k
      exec->GS.gep1 = 1;
678
59.5k
      exec->GS.gep2 = 1;
679
680
59.5k
      exec->GS.projVector.x = 0x4000;
681
59.5k
      exec->GS.projVector.y = 0x0000;
682
683
59.5k
      exec->GS.freeVector = exec->GS.projVector;
684
59.5k
      exec->GS.dualVector = exec->GS.projVector;
685
686
59.5k
      exec->GS.round_state = 1;
687
59.5k
      exec->GS.loop        = 1;
688
689
      /* some glyphs leave something on the stack. so we clean it */
690
      /* before a new execution.                                  */
691
59.5k
      exec->top     = 0;
692
59.5k
      exec->callTop = 0;
693
694
59.5k
      error = RunIns( exec );
695
59.5k
      Unset_CodeRange(exec);
696
59.5k
    }
697
9.72k
    else
698
9.72k
      error = TT_Err_Ok;
699
700
69.2k
  Fin:
701
69.2k
    Context_Save( exec, ins );
702
703
69.2k
    ins->valid = FALSE;
704
705
69.2k
    return error;
706
69.2k
  }
707
708
/*******************************************************************
709
 *
710
 *  Function    : Instance_Reset
711
 *
712
 *  Description : Resets an instance to a new pointsize/transform.
713
 *                Executes the cvt program if any is found.
714
 *
715
 *  Input  :  _instance   the instance object to destroy
716
 *
717
 *  Output :  Error code.
718
 *
719
 ******************************************************************/
720
721
  TT_Error  Instance_Reset( PInstance  ins,
722
                            Bool       debug )
723
69.2k
  {
724
69.2k
    TT_Error  error;
725
69.2k
    Int       i;
726
69.2k
    PFace     face;
727
69.2k
    PExecution_Context exec;
728
729
69.2k
    if ( !ins )
730
0
      return TT_Err_Invalid_Instance_Handle;
731
732
69.2k
    if ( ins->valid )
733
0
      return TT_Err_Ok;
734
735
69.2k
    face = ins->face;
736
69.2k
    exec = face->font->exec;
737
738
69.2k
    if ( ins->metrics.x_ppem < 1 ||
739
69.2k
         ins->metrics.y_ppem < 1 )
740
0
      return TT_Err_Invalid_PPem;
741
742
    /* compute new transformation */
743
69.2k
    if ( ins->metrics.x_ppem >= ins->metrics.y_ppem )
744
69.2k
    {
745
69.2k
      ins->metrics.scale1  = ins->metrics.x_scale1;
746
69.2k
      ins->metrics.scale2  = ins->metrics.x_scale2;
747
69.2k
      ins->metrics.ppem    = ins->metrics.x_ppem;
748
69.2k
      ins->metrics.x_ratio = 1 << 16;
749
69.2k
      ins->metrics.y_ratio = MulDiv_Round( ins->metrics.y_ppem,
750
69.2k
                                           0x10000,
751
69.2k
                                           ins->metrics.x_ppem );
752
69.2k
    }
753
0
    else
754
0
    {
755
0
      ins->metrics.scale1  = ins->metrics.y_scale1;
756
0
      ins->metrics.scale2  = ins->metrics.y_scale2;
757
0
      ins->metrics.ppem    = ins->metrics.y_ppem;
758
0
      ins->metrics.x_ratio = MulDiv_Round( ins->metrics.x_ppem,
759
0
                                           0x10000,
760
0
                                           ins->metrics.y_ppem );
761
0
      ins->metrics.y_ratio = 1 << 16;
762
0
    }
763
764
    /* Scale the cvt values to the new ppem.          */
765
    /* We use by default the y ppem to scale the CVT. */
766
767
29.4M
    for ( i = 0; i < ins->cvtSize; i++ )
768
29.3M
      ins->cvt[i] = MulDiv_Round( face->cvt[i],
769
29.3M
                                  ins->metrics.scale1,
770
29.3M
                                  ins->metrics.scale2 );
771
772
69.2k
    ins->GS = Default_GraphicsState;
773
774
    /* get execution context and run prep program */
775
776
69.2k
    Context_Load( exec, ins );
777
778
69.2k
    Set_CodeRange( exec,
779
69.2k
                   TT_CodeRange_Cvt,
780
69.2k
                   face->cvtProgram,
781
69.2k
                   face->cvtPgmSize );
782
783
69.2k
    Clear_CodeRange( exec, TT_CodeRange_Glyph );
784
785
109M
    for ( i = 0; i < exec->storeSize; i++ )
786
108M
      exec->storage[i] = 0;
787
788
69.2k
    exec->instruction_trap = FALSE;
789
790
69.2k
    exec->top     = 0;
791
69.2k
    exec->callTop = 0;
792
793
    /* All twilight points are originally zero */
794
795
180M
    for ( i = 0; i < exec->twilight.n_points; i++ )
796
180M
    {
797
180M
      exec->twilight.org_x[i] = 0;
798
180M
      exec->twilight.org_y[i] = 0;
799
180M
      exec->twilight.cur_x[i] = 0;
800
180M
      exec->twilight.cur_y[i] = 0;
801
180M
    }
802
803
69.2k
    if ( face->cvtPgmSize > 0 )
804
59.5k
    {
805
59.5k
      error = Goto_CodeRange( exec, TT_CodeRange_Cvt, 0 );
806
59.5k
      if (error)
807
0
        goto Fin;
808
809
59.5k
      exec->zp0 = exec->pts;
810
59.5k
      exec->zp1 = exec->pts;
811
59.5k
      exec->zp2 = exec->pts;
812
813
59.5k
      exec->GS.gep0 = 1;
814
59.5k
      exec->GS.gep1 = 1;
815
59.5k
      exec->GS.gep2 = 1;
816
817
59.5k
      exec->GS.projVector.x = 0x4000;
818
59.5k
      exec->GS.projVector.y = 0x0000;
819
820
59.5k
      exec->GS.freeVector = exec->GS.projVector;
821
59.5k
      exec->GS.dualVector = exec->GS.projVector;
822
823
59.5k
      exec->GS.round_state = 1;
824
59.5k
      exec->GS.loop        = 1;
825
826
      /* some glyphs leave something on the stack. so we clean it */
827
      /* before a new execution.                                  */
828
59.5k
      exec->top     = 0;
829
59.5k
      exec->callTop = 0;
830
831
59.5k
      error = RunIns( exec );
832
59.5k
      Unset_CodeRange(exec);
833
59.5k
    }
834
9.66k
    else
835
9.66k
      error = TT_Err_Ok;
836
837
69.2k
    ins->GS = exec->GS;
838
    /* save default graphics state */
839
840
69.2k
  Fin:
841
69.2k
    Context_Save( exec, ins );
842
843
69.2k
    if ( !error )
844
46.9k
      ins->valid = TRUE;
845
846
69.2k
    return error;
847
69.2k
  }
848
849
/*******************************************************************
850
 *                                                                 *
851
 *                         FACE  FUNCTIONS                         *
852
 *                                                                 *
853
 *                                                                 *
854
 *******************************************************************/
855
856
/*******************************************************************
857
 *
858
 *  Function    :  Face_Destroy
859
 *
860
 *  Description :  The face object destructor.
861
 *
862
 *  Input  :  _face   typeless pointer to the face object to destroy
863
 *
864
 *  Output :  Error code.
865
 *
866
 ******************************************************************/
867
868
  TT_Error  Face_Destroy( PFace face )
869
69.2k
  {
870
69.2k
    if ( face ) {
871
69.2k
        ttfMemory *mem = face->font->tti->ttf_memory;
872
873
        /* freeing the CVT */
874
69.2k
        FREE( face->cvt );
875
69.2k
        face->cvtSize = 0;
876
877
        /* freeing the programs */
878
69.2k
        FREE( face->fontProgram );
879
69.2k
        FREE( face->cvtProgram );
880
69.2k
        face->fontPgmSize = 0;
881
69.2k
        face->cvtPgmSize  = 0;
882
69.2k
    }
883
69.2k
    return TT_Err_Ok;
884
69.2k
  }
885
886
/*******************************************************************
887
 *
888
 *  Function    :  Face_Create
889
 *
890
 *  Description :  The face object constructor.
891
 *
892
 *  Input  :  _face    face record to build
893
 *            _input   input stream where to load font data
894
 *
895
 *  Output :  Error code.
896
 *
897
 *  NOTE : The input stream is kept in the face object.  The
898
 *         caller shouldn't destroy it after calling Face_Create().
899
 *
900
 ******************************************************************/
901
902
#define LOAD_( table ) \
903
346k
          ( error = Load_TrueType_##table (face) )
904
905
  TT_Error  Face_Create( PFace  face)
906
69.2k
  {
907
69.2k
    TT_Error      error;
908
909
    /* Load tables */
910
911
69.2k
    if ( /*LOAD_(Header)                      ||*/
912
69.2k
         LOAD_(MaxProfile)                  ||
913
         /*LOAD_(Locations)                   ||*/
914
         /*LOAD_(CMap)                        ||*/
915
69.2k
         LOAD_(CVT)                         ||
916
         /*LOAD_(Horizontal_Header)           ||*/
917
69.2k
         LOAD_(Programs)
918
         /*LOAD_(HMTX)                        ||*/
919
         /*LOAD_(Gasp)                        ||*/
920
         /*LOAD_(Names)                       ||*/
921
         /*LOAD_(OS2)                         ||*/
922
         /*LOAD_(PostScript)                  ||*/
923
         /*LOAD_(Hdmx)                        */
924
69.2k
        )
925
0
      goto Fail;
926
927
69.2k
    return TT_Err_Ok;
928
929
0
  Fail :
930
0
    Face_Destroy( face );
931
0
    return error;
932
69.2k
  }
933
934
/*******************************************************************
935
 *
936
 *  Function    :  Scale_X
937
 *
938
 *  Description :  scale an horizontal distance from font
939
 *                 units to 26.6 pixels
940
 *
941
 *  Input  :  metrics  pointer to metrics
942
 *            x        value to scale
943
 *
944
 *  Output :  scaled value
945
 *
946
 ******************************************************************/
947
948
 TT_Pos  Scale_X( PIns_Metrics  metrics, TT_Pos  x )
949
3.40M
 {
950
3.40M
   return MulDiv_Round( x, metrics->x_scale1, metrics->x_scale2 );
951
3.40M
 }
952
953
/*******************************************************************
954
 *
955
 *  Function    :  Scale_Y
956
 *
957
 *  Description :  scale a vertical distance from font
958
 *                 units to 26.6 pixels
959
 *
960
 *  Input  :  metrics  pointer to metrics
961
 *            y        value to scale
962
 *
963
 *  Output :  scaled value
964
 *
965
 ******************************************************************/
966
967
 TT_Pos  Scale_Y( PIns_Metrics  metrics, TT_Pos  y )
968
3.40M
 {
969
3.40M
   return MulDiv_Round( y, metrics->y_scale1, metrics->y_scale2 );
970
3.40M
 }