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