/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 | } |