Commit | Line | Data |
---|---|---|
9ef61858 WJ |
1 | /* Copyright (C) 1990, 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* gstype1.c */ | |
21 | /* Adobe Type 1 font routines for Ghostscript library */ | |
22 | #include "math_.h" | |
23 | #include "memory_.h" | |
24 | #include "gx.h" | |
25 | #include "gserrors.h" | |
26 | #include "gxarith.h" | |
27 | #include "gxfixed.h" | |
28 | #include "gxmatrix.h" | |
29 | #include "gzstate.h" | |
30 | #include "gzdevice.h" /* for gxchar */ | |
31 | #include "gxdevmem.h" /* ditto */ | |
32 | #include "gzpath.h" | |
33 | #include "gxchar.h" | |
34 | #include "gxfont.h" | |
35 | #include "gxtype1.h" | |
36 | #include "gxop1.h" | |
37 | ||
38 | /* Define the amount of thickening to be applied to characters. */ | |
39 | #define type1_fill_adjust 0.25 | |
40 | ||
41 | /* Encrypt a string. */ | |
42 | int | |
43 | gs_type1_encrypt(byte *dest, byte *src, uint len, crypt_state *pstate) | |
44 | { register crypt_state state = *pstate; | |
45 | register byte *from = src; | |
46 | register byte *to = dest; | |
47 | register uint count = len; | |
48 | while ( count ) | |
49 | { encrypt_next(*from, state, *to); | |
50 | from++, to++, count--; | |
51 | } | |
52 | *pstate = state; | |
53 | return 0; | |
54 | } | |
55 | /* Decrypt a string. */ | |
56 | int | |
57 | gs_type1_decrypt(byte *dest, byte *src, uint len, crypt_state *pstate) | |
58 | { register crypt_state state = *pstate; | |
59 | register byte *from = src; | |
60 | register byte *to = dest; | |
61 | register uint count = len; | |
62 | while ( count ) | |
63 | { /* If from == to, we can't use the obvious */ | |
64 | /* decrypt_next(*from, state, *to); */ | |
65 | register byte ch = *from++; | |
66 | decrypt_next(ch, state, *to); | |
67 | to++, count--; | |
68 | } | |
69 | *pstate = state; | |
70 | return 0; | |
71 | } | |
72 | ||
73 | /* Define the structures for the state of a Type 1 interpreter. */ | |
74 | /* This is the interpreter state that must be saved and restored */ | |
75 | /* when calling a CharString subroutine. */ | |
76 | typedef struct { | |
77 | byte *ip; | |
78 | crypt_state dstate; | |
79 | } ip_state; | |
80 | /* Define the stem hint tables. */ | |
81 | /* Each stem hint table is kept sorted. */ | |
82 | #define max_stems 3 /* arbitrary */ | |
83 | typedef struct { | |
84 | fixed v0, v1; /* coordinates (widened a little) */ | |
85 | gs_fixed_point adjust_lower, adjust_upper; /* adjustments */ | |
86 | } stem_hint; | |
87 | typedef struct { | |
88 | int count; | |
89 | stem_hint *current; /* cache cursor for search */ | |
90 | stem_hint data[max_stems]; | |
91 | } stem_hint_table; | |
92 | /* This is the full state of the Type 1 interpreter. */ | |
93 | #define ostack_size 24 /* per documentation */ | |
94 | #define ipstack_size 10 /* per documentation */ | |
95 | struct gs_type1_state_s { | |
96 | /* The following are set at initialization */ | |
97 | gs_show_enum *penum; /* show enumerator */ | |
98 | gs_state *pgs; /* graphics state */ | |
99 | gs_type1_data *pdata; /* font-specific data */ | |
100 | int charpath_flag; /* 0 for show, 1 for false */ | |
101 | /* charpath, 2 for true charpath */ | |
102 | int paint_type; /* 0/3 for fill, 1/2 for stroke */ | |
103 | fixed_coeff fc; /* cached fixed coefficients */ | |
104 | float flatness; /* flatness for character curves */ | |
105 | /* The following are updated dynamically */ | |
106 | fixed ostack[ostack_size]; /* the Type 1 operand stack */ | |
107 | int os_count; /* # of occupied stack entries */ | |
108 | ip_state ipstack[ipstack_size+1]; /* control stack */ | |
109 | int ips_count; /* # of occupied entries */ | |
110 | gs_fixed_point lsb; /* left side bearing */ | |
111 | gs_fixed_point width; /* character width */ | |
112 | int seac_base; /* base character code for seac, */ | |
113 | /* or -1 */ | |
114 | /* The following are set dynamically, */ | |
115 | /* but not actually used yet. */ | |
116 | int in_dotsection; /* true if inside dotsection */ | |
117 | stem_hint_table hstem_hints; /* horizontal stem hints */ | |
118 | stem_hint_table vstem_hints; /* vertical stem hints */ | |
119 | }; | |
120 | ||
121 | /* Export the size of the structure */ | |
122 | const uint gs_type1_state_sizeof = sizeof(gs_type1_state); | |
123 | ||
124 | /* Imported procedures */ | |
125 | extern int gx_matrix_to_fixed_coeff(P3(gs_matrix *, fixed_coeff *, int)); | |
126 | ||
127 | /* Initialize a Type 1 interpreter. */ | |
128 | /* The caller must supply a string to the first call of gs_type1_interpret. */ | |
129 | int | |
130 | gs_type1_init(register gs_type1_state *pis, gs_show_enum *penum, | |
131 | int charpath_flag, int paint_type, gs_type1_data *pdata) | |
132 | { gs_state *pgs = penum->pgs; | |
133 | pis->penum = penum; | |
134 | pis->pgs = pgs; | |
135 | pis->pdata = pdata; | |
136 | pis->charpath_flag = charpath_flag; | |
137 | pis->paint_type = paint_type; | |
138 | pis->os_count = 0; | |
139 | pis->ips_count = 1; | |
140 | pis->seac_base = -1; | |
141 | pis->in_dotsection = 0; | |
142 | pis->hstem_hints.count = 0; | |
143 | pis->hstem_hints.current = &pis->hstem_hints.data[0]; | |
144 | pis->vstem_hints.count = 0; | |
145 | pis->vstem_hints.current = &pis->vstem_hints.data[0]; | |
146 | gx_matrix_to_fixed_coeff(&ctm_only(pgs), &pis->fc, max_coeff_bits); | |
147 | /* Set the current point of the path to the origin, */ | |
148 | /* in anticipation of the initial [h]sbw. */ | |
149 | { gx_path *ppath = pgs->path; | |
150 | ppath->position.x = pgs->ctm.tx_fixed; | |
151 | ppath->position.y = pgs->ctm.ty_fixed; | |
152 | } | |
153 | /* Set the flatness to a value that is likely to produce */ | |
154 | /* reasonably good-looking curves, regardless of its */ | |
155 | /* current value in the graphics state. */ | |
156 | if ( (pis->flatness = pgs->flatness) > 1.0 ) | |
157 | { /* With the conventional 1000-unit characters, */ | |
158 | /* a small "o" will be about 250 units, */ | |
159 | /* so set the flatness to 10 units. */ | |
160 | float cxx = pgs->ctm.xx, cyy = pgs->ctm.yy; | |
161 | if ( cxx < 0 ) cxx = -cxx; | |
162 | if ( cyy < 0 ) cyy = -cyy; | |
163 | if ( cyy > cxx ) cxx = cyy; | |
164 | if ( is_skewed(&pgs->ctm) ) | |
165 | { float cxy = pgs->ctm.xy, cyx = pgs->ctm.yx; | |
166 | if ( cxy < 0 ) cxy = -cxy; | |
167 | if ( cyx < 0 ) cyx = -cyx; | |
168 | if ( cxy > cxx ) cxx = cxy; | |
169 | if ( cyx > cxx ) cxx = cyx; | |
170 | } | |
171 | pis->flatness = (cxx > 0.1 ? cxx * 10 : 1.0); | |
172 | } | |
173 | return 0; | |
174 | } | |
175 | ||
176 | /* Tracing for type 1 interpreter */ | |
177 | #ifdef DEBUG | |
178 | # define dc(str) if ( gs_debug['1'] ) type1_trace(cip, c, str); | |
179 | private void near | |
180 | type1_trace(byte *cip, byte c, char _ds *str) | |
181 | { dprintf3("[1]%lx: %02x %s\n", (ulong)(cip - 1), c, (char *)str); | |
182 | } | |
183 | #else | |
184 | # define dc(str) | |
185 | #endif | |
186 | ||
187 | /* Define the state used by operator procedures. */ | |
188 | /* These macros refer to a current instance (s) of gs_op1_state. */ | |
189 | #define sppath s.ppath | |
190 | #define sfc s.fc | |
191 | #define ptx s.px | |
192 | #define pty s.py | |
193 | #define sctx s.ctx | |
194 | #define scty s.cty | |
195 | ||
196 | /* Accumulate relative coordinates */ | |
197 | /****** THESE ARE NOT ACCURATE FOR NON-INTEGER DELTAS. ******/ | |
198 | /* This probably doesn't make any difference in practice. */ | |
199 | #define c_fixed(d, c) m_fixed(arg2int(d), c, sfc) | |
200 | #define accum_x(dx)\ | |
201 | ptx += c_fixed(dx, sfc.xx);\ | |
202 | if ( sfc.skewed ) pty += c_fixed(dx, sfc.xy) | |
203 | #define accum_y(dy)\ | |
204 | pty += c_fixed(dy, sfc.yy);\ | |
205 | if ( sfc.skewed ) ptx += c_fixed(dy, sfc.yx) | |
206 | #define accum_xy(dx,dy)\ | |
207 | accum_xy_proc(&s, dx, dy) | |
208 | ||
209 | #define s (*ps) | |
210 | #define arg2int(f) fixed2int_var(f) | |
211 | ||
212 | private void near | |
213 | accum_xy_proc(register is_ptr ps, fixed dx, fixed dy) | |
214 | { int idx, idy; | |
215 | ptx += m_fixed((idx = arg2int(dx)), sfc.xx, sfc), | |
216 | pty += m_fixed((idy = arg2int(dy)), sfc.yy, sfc); | |
217 | if ( sfc.skewed ) | |
218 | ptx += m_fixed(idy, sfc.yx, sfc), | |
219 | pty += m_fixed(idx, sfc.xy, sfc); | |
220 | } | |
221 | ||
222 | /* We round all endpoints of lines or curves */ | |
223 | /* to the center of the nearest quarter-pixel, and suppress null lines. */ | |
224 | /* (Rounding to the half-pixel causes too many dropouts.) */ | |
225 | /* This saves a lot of rendering work for small characters. */ | |
226 | #define pixel_rounded(fx)\ | |
227 | (((fx) | float2fixed(0.125)) & float2fixed(-0.125)) | |
228 | #define must_draw_to(lpx, lpy, px, py)\ | |
229 | ((lpx = pixel_rounded(px)), (lpy = pixel_rounded(py)),\ | |
230 | (psub = sppath->current_subpath) == 0 ||\ | |
231 | (pseg = psub->last)->type == s_line_close ||\ | |
232 | lpx != pseg->pt.x || lpy != pseg->pt.y) | |
233 | ||
234 | /* ------ Operator procedures ------ */ | |
235 | ||
236 | /* We put these before the interpreter to save having to write */ | |
237 | /* prototypes for all of them. */ | |
238 | ||
239 | int | |
240 | gs_op1_closepath(register is_ptr ps) | |
241 | { /* Note that this does NOT reset the current point! */ | |
242 | int code = gx_path_close_subpath(sppath); | |
243 | if ( code < 0 ) return code; | |
244 | return gx_path_add_point(sppath, ptx, pty); /* put the point where it was */ | |
245 | } | |
246 | ||
247 | int | |
248 | gs_op1_sbw(register is_ptr ps, fixed sbx, fixed sby, fixed wx, fixed wy) | |
249 | { register gs_type1_state *pis = ps->pis; | |
250 | gs_show_enum *penum = pis->penum; | |
251 | if ( penum->sb_set ) | |
252 | pis->lsb = penum->metrics_sb; | |
253 | else | |
254 | pis->lsb.x = sbx, pis->lsb.y = sby; | |
255 | if ( penum->width_set ) | |
256 | pis->width = penum->metrics_width; | |
257 | else | |
258 | pis->width.x = wx, pis->width.y = wy; | |
259 | #ifdef DEBUG | |
260 | if ( gs_debug['1'] ) | |
261 | dprintf4("[1]sb=(%g,%g) w=(%g,%g)\n", | |
262 | fixed2float(pis->lsb.x), fixed2float(pis->lsb.y), | |
263 | fixed2float(pis->width.x), fixed2float(pis->width.y)); | |
264 | #endif | |
265 | accum_xy(pis->lsb.x, pis->lsb.y); | |
266 | return 0; | |
267 | } | |
268 | ||
269 | int | |
270 | gs_op1_hsbw(register is_ptr ps, fixed sbx, fixed wx) | |
271 | { return gs_op1_sbw(ps, sbx, (fixed)0, wx, (fixed)0); | |
272 | } | |
273 | ||
274 | int | |
275 | gs_op1_rrcurveto(register is_ptr ps, fixed dx1, fixed dy1, | |
276 | fixed dx2, fixed dy2, fixed dx3, fixed dy3) | |
277 | { fixed ptx1, pty1, ptx2, pty2; | |
278 | /* Following declarations are only for must_draw_to */ | |
279 | fixed lpx, lpy; | |
280 | subpath *psub; | |
281 | segment *pseg; | |
282 | accum_xy(dx1, dy1); | |
283 | ptx1 = ptx, pty1 = pty; | |
284 | accum_xy(dx2, dy2); | |
285 | ptx2 = ptx, pty2 = pty; | |
286 | accum_xy(dx3, dy3); | |
287 | if ( must_draw_to(lpx, lpy, ptx, pty) ) | |
288 | return gx_path_add_flattened_curve(sppath, ptx1, pty1, ptx2, pty2, lpx, lpy, ps->pis->flatness); | |
289 | return 0; | |
290 | } | |
291 | ||
292 | #undef s | |
293 | ||
294 | /* ------ Main interpreter ------ */ | |
295 | ||
296 | /* Continue interpreting a Type 1 CharString. */ | |
297 | /* If str != 0, it is taken as the byte string to interpret. */ | |
298 | /* Return 0 on successful completion, <0 on error, */ | |
299 | /* or >0 when client intervention is required. */ | |
300 | /* The int * argument is where the character is stored for seac, */ | |
301 | /* or the othersubr # for callothersubr. */ | |
302 | private void near type1_hstem(P3(gs_type1_state *, fixed, fixed)); | |
303 | private void near type1_vstem(P3(gs_type1_state *, fixed, fixed)); | |
304 | private stem_hint *near type1_stem(P3(stem_hint_table *, fixed, fixed)); | |
305 | private int near type1_endchar(P3(gs_type1_state *, gs_state *, gx_path *)); | |
306 | int | |
307 | gs_type1_interpret(register gs_type1_state *pis, byte *str, int *pindex) | |
308 | { gs_state *pgs = pis->pgs; | |
309 | gs_type1_data *pdata = pis->pdata; | |
310 | gs_op1_state s; | |
311 | fixed cstack[ostack_size]; | |
312 | #define cs0 cstack[0] | |
313 | #define ics0 fixed2int_var(cs0) | |
314 | #define cs1 cstack[1] | |
315 | #define ics1 fixed2int_var(cs1) | |
316 | #define cs2 cstack[2] | |
317 | #define ics2 fixed2int_var(cs2) | |
318 | #define cs3 cstack[3] | |
319 | #define ics3 fixed2int_var(cs3) | |
320 | #define cs4 cstack[4] | |
321 | #define ics4 fixed2int_var(cs4) | |
322 | #define cs5 cstack[5] | |
323 | #define ics5 fixed2int_var(cs5) | |
324 | register fixed _ss *csp; | |
325 | #define clear csp = cstack - 1 | |
326 | ip_state *ipsp = &pis->ipstack[pis->ips_count - 1]; | |
327 | register byte *cip; | |
328 | register crypt_state state; | |
329 | register int c; | |
330 | int code = 0; | |
331 | fixed ftx = pgs->ctm.tx_fixed, fty = pgs->ctm.ty_fixed; | |
332 | fixed lpx, lpy; | |
333 | subpath *psub; | |
334 | segment *pseg; | |
335 | ||
336 | sppath = pgs->path; | |
337 | s.pis = pis; | |
338 | sfc = pis->fc; | |
339 | ptx = sppath->position.x; | |
340 | pty = sppath->position.y; | |
341 | ||
342 | /* Copy the operand stack out of the saved state. */ | |
343 | if ( pis->os_count == 0 ) | |
344 | { clear; | |
345 | } | |
346 | else | |
347 | { memcpy(cstack, pis->ostack, pis->os_count * sizeof(fixed)); | |
348 | csp = &cstack[pis->os_count - 1]; | |
349 | } | |
350 | ||
351 | if ( str == 0 ) goto cont; | |
352 | cip = str; | |
353 | call: state = crypt_charstring_seed; | |
354 | { int skip = pdata->lenIV; | |
355 | /* Skip initial random bytes */ | |
356 | for ( ; skip > 0; --skip ) | |
357 | { decrypt_skip_next(*cip, state); ++cip; | |
358 | } | |
359 | } | |
360 | goto top; | |
361 | cont: cip = ipsp->ip; | |
362 | state = ipsp->dstate; | |
363 | top: while ( 1 ) | |
364 | { uint c0; | |
365 | c = decrypt_this((c0 = *cip++), state); | |
366 | decrypt_skip_next(c0, state); | |
367 | switch ( (char_command)c ) | |
368 | { | |
369 | #define cnext clear; break | |
370 | case c_hstem: dc("hstem") | |
371 | type1_hstem(pis, cs0, cs1); | |
372 | cnext; | |
373 | case c_vstem: dc("vstem") | |
374 | type1_vstem(pis, cs0, cs1); | |
375 | cnext; | |
376 | case c_vmoveto: dc("vmoveto") | |
377 | accum_y(cs0); | |
378 | move: /* Round to the nearest center of a quarter-pixel. */ | |
379 | if ( must_draw_to(lpx, lpy, ptx, pty) ) | |
380 | code = gx_path_add_point(sppath, lpx, lpy); | |
381 | goto cc; | |
382 | case c_rlineto: dc("rlineto") | |
383 | accum_xy(cs0, cs1); | |
384 | line: /* Round to the nearest center of a quarter-pixel. */ | |
385 | if ( must_draw_to(lpx, lpy, ptx, pty) ) | |
386 | code = gx_path_add_line(sppath, lpx, lpy); | |
387 | cc: if ( code < 0 ) return code; | |
388 | pp: | |
389 | #ifdef DEBUG | |
390 | if ( gs_debug['1'] ) | |
391 | dprintf2("[1]pt=(%g,%g)\n", | |
392 | fixed2float(ptx), fixed2float(pty)); | |
393 | #endif | |
394 | cnext; | |
395 | case c_hlineto: dc("hlineto") | |
396 | accum_x(cs0); | |
397 | goto line; | |
398 | case c_vlineto: dc("vlineto") | |
399 | accum_y(cs0); | |
400 | goto line; | |
401 | case c_rrcurveto: dc("rrcurveto") | |
402 | code = gs_op1_rrcurveto(&s, cs0, cs1, cs2, cs3, cs4, cs5); | |
403 | goto cc; | |
404 | case c_closepath: dc("closepath") | |
405 | code = gs_op1_closepath(&s); | |
406 | goto cc; | |
407 | case c_callsubr: dc("callsubr") | |
408 | { int index = fixed2int_var(*csp); | |
409 | byte *nip; | |
410 | code = (*pdata->subr_proc)(pdata, index, &nip); | |
411 | if ( code < 0 ) return_error(code); | |
412 | --csp; | |
413 | ipsp->ip = cip, ipsp->dstate = state; | |
414 | ++ipsp; | |
415 | cip = nip; | |
416 | } | |
417 | goto call; | |
418 | case c_return: dc("return") | |
419 | --ipsp; | |
420 | goto cont; | |
421 | case c_escape: dc("escape:") | |
422 | decrypt_next(*cip, state, c); ++cip; | |
423 | switch ( (char_extended_command)c ) | |
424 | { | |
425 | case ce_dotsection: dc(" dotsection") | |
426 | pis->in_dotsection = !pis->in_dotsection; | |
427 | cnext; | |
428 | case ce_vstem3: dc(" vstem3") | |
429 | type1_vstem(pis, cs0, cs1); | |
430 | type1_vstem(pis, cs2, cs3); | |
431 | type1_vstem(pis, cs4, cs5); | |
432 | cnext; | |
433 | case ce_hstem3: dc(" hstem3") | |
434 | type1_hstem(pis, cs0, cs1); | |
435 | type1_hstem(pis, cs2, cs3); | |
436 | type1_hstem(pis, cs4, cs5); | |
437 | cnext; | |
438 | case ce_seac: dc(" seac") | |
439 | /* Do the accent now. When it finishes */ | |
440 | /* (detected in endchar), do the base character. */ | |
441 | pis->seac_base = ics3; | |
442 | /* Adjust the origin of the coordinate system */ | |
443 | /* for the accent (endchar puts it back). */ | |
444 | ptx = ftx, pty = fty; | |
445 | cs1 -= cs0; /* subtract off asb */ | |
446 | accum_xy(cs1, cs2); | |
447 | sppath->position.x = ptx; | |
448 | sppath->position.y = pty; | |
449 | pis->os_count = 0; /* clear */ | |
450 | /* Give control back to the caller, who must */ | |
451 | /* re-invoke the interpreter with the seac string. */ | |
452 | *pindex = ics4; | |
453 | return type1_result_seac; | |
454 | case ce_sbw: dc(" sbw") | |
455 | code = gs_op1_sbw(&s, cs0, cs1, cs2, cs3); | |
456 | goto cc; | |
457 | case ce_div: dc(" div") | |
458 | csp[-1] = float2fixed((float)csp[-1] / (float)*csp); | |
459 | --csp; goto pushed; | |
460 | case ce_undoc15: dc(" undoc15") | |
461 | /* | |
462 | * NOTE: this opcode is not documented by Adobe, | |
463 | * but is used in some Adobe fonts. I have no idea | |
464 | * what it is supposed to do. | |
465 | */ | |
466 | cnext; | |
467 | case ce_callothersubr: dc(" callothersubr") | |
468 | { int scount = csp - cstack; | |
469 | *pindex = fixed2int_var(*csp); | |
470 | /* Update path position so it will be right */ | |
471 | /* when we come back in. */ | |
472 | sppath->position.x = ptx; | |
473 | sppath->position.y = pty; | |
474 | /* Exit to caller */ | |
475 | ipsp->ip = cip, ipsp->dstate = state; | |
476 | pis->os_count = scount; | |
477 | pis->ips_count = ipsp - &pis->ipstack[0] + 1; | |
478 | if ( scount ) | |
479 | memcpy(pis->ostack, cstack, | |
480 | scount * sizeof(fixed)); | |
481 | return type1_result_callothersubr; | |
482 | } | |
483 | case ce_pop: dc(" pop") | |
484 | ++csp; | |
485 | code = (*pdata->pop_proc)(pdata, csp); | |
486 | if ( code < 0 ) return_error(code); | |
487 | goto pushed; | |
488 | case ce_setcurrentpoint: dc(" setcurrentpoint") | |
489 | ptx = ftx, pty = fty; | |
490 | accum_xy(cs0, cs1); | |
491 | goto pp; | |
492 | default: | |
493 | return_error(gs_error_invalidfont); | |
494 | } | |
495 | break; | |
496 | case c_hsbw: dc("hsbw") | |
497 | code = gs_op1_hsbw(&s, cs0, cs1); | |
498 | goto cc; | |
499 | case c_endchar: dc("endchar") | |
500 | if ( pis->seac_base >= 0 ) | |
501 | { /* We just finished the accent of a seac. */ | |
502 | /* Do the base character. */ | |
503 | *pindex = pis->seac_base; | |
504 | pis->seac_base = -1; | |
505 | /* Restore the coordinate system origin */ | |
506 | sppath->position.x = ftx; | |
507 | sppath->position.y = fty; | |
508 | pis->os_count = 0; /* clear */ | |
509 | /* Clear the ipstack, in case the accent ended */ | |
510 | /* inside a subroutine. */ | |
511 | pis->ips_count = 1; | |
512 | /* Give control back to the caller, who must */ | |
513 | /* re-invoke the interpreter with the */ | |
514 | /* base character string. */ | |
515 | return type1_result_seac; | |
516 | } | |
517 | /* This is a real endchar. Handle it below. */ | |
518 | return type1_endchar(pis, pgs, sppath); | |
519 | case c_undoc15: dc(" undoc15") | |
520 | /* | |
521 | * NOTE: this opcode is not documented by Adobe, | |
522 | * but is used in some Adobe fonts. I have no idea | |
523 | * what it is supposed to do. | |
524 | */ | |
525 | cnext; | |
526 | case c_rmoveto: dc("rmoveto") | |
527 | accum_xy(cs0, cs1); | |
528 | goto move; | |
529 | case c_hmoveto: dc("hmoveto") | |
530 | accum_x(cs0); | |
531 | goto move; | |
532 | case c_vhcurveto: dc("vhcurveto") | |
533 | code = gs_op1_rrcurveto(&s, (fixed)0, cs0, cs1, cs2, cs3, (fixed)0); | |
534 | goto cc; | |
535 | case c_hvcurveto: dc("hvcurveto") | |
536 | code = gs_op1_rrcurveto(&s, cs0, (fixed)0, cs1, cs2, (fixed)0, cs3); | |
537 | goto cc; | |
538 | /* Fill up the dispatch up to 32. */ | |
539 | case c_undef0: case c_undef2: | |
540 | case c_undef16: case c_undef17: case c_undef18: case c_undef19: | |
541 | case c_undef20: case c_undef23: | |
542 | case c_undef24: case c_undef25: case c_undef26: case c_undef27: | |
543 | case c_undef28: case c_undef29: | |
544 | return_error(gs_error_invalidfont); | |
545 | /* Fill up the dispatch for 1-byte numbers. */ | |
546 | #define icase(n) case n: | |
547 | #define ncase(n) case n: *++csp = int2fixed(c_value_num1(n)); goto pushed; | |
548 | #define icase10(n)\ | |
549 | icase(n) icase(n+1) icase(n+2) icase(n+3) icase(n+4)\ | |
550 | icase(n+5) icase(n+6) icase(n+7) icase(n+8) icase(n+9) | |
551 | #define ncase10(n)\ | |
552 | ncase(n) ncase(n+1) ncase(n+2) ncase(n+3) ncase(n+4)\ | |
553 | ncase(n+5) ncase(n+6) ncase(n+7) ncase(n+8) ncase(n+9) | |
554 | icase(32) icase(33) icase(34) | |
555 | icase(35) icase(36) icase(37) icase(38) icase(39) | |
556 | icase10(40) | |
557 | icase10(50) icase10(60) icase10(70) icase10(80) icase10(90) | |
558 | icase10(100) icase10(110) goto pi; ncase10(120) ncase10(130) ncase10(140) | |
559 | ncase10(150) icase10(160) icase10(170) icase10(180) icase10(190) | |
560 | icase10(200) icase10(210) icase10(220) icase10(230) | |
561 | icase(240) icase(241) icase(242) icase(243) icase(244) | |
562 | icase(245) icase(246) | |
563 | pi: *++csp = int2fixed(c_value_num1(c)); | |
564 | pushed: | |
565 | #ifdef DEBUG | |
566 | if ( gs_debug['1'] ) | |
567 | dprintf3("[1]%d: (%d) %f\n", | |
568 | (int)(csp - cstack), c, fixed2float(*csp)); | |
569 | #endif | |
570 | break; | |
571 | /* Handle 2-byte positive numbers. */ | |
572 | #define case_num2(n)\ | |
573 | case c_num2+n: *++csp = int2fixed(c_value_num2(c_num2+n, 0)) | |
574 | case_num2(0); goto pos2; | |
575 | case_num2(1); goto pos2; | |
576 | case_num2(2); goto pos2; | |
577 | case_num2(3); | |
578 | #undef case_num2 | |
579 | pos2: { c0 = *cip++; | |
580 | *csp += int2fixed(decrypt_this(c0, state)); | |
581 | decrypt_skip_next(c0, state); | |
582 | } goto pushed; | |
583 | /* Handle 2-byte negative numbers. */ | |
584 | #define case_num3(n)\ | |
585 | case c_num3+n: *++csp = int2fixed(c_value_num3(c_num3+n, 0)) | |
586 | case_num3(0); goto neg2; | |
587 | case_num3(1); goto neg2; | |
588 | case_num3(2); goto neg2; | |
589 | case_num3(3); | |
590 | #undef case_num3 | |
591 | neg2: { c0 = *cip++; | |
592 | *csp -= int2fixed(decrypt_this(c0, state)); | |
593 | decrypt_skip_next(c0, state); | |
594 | } goto pushed; | |
595 | /* Handle 5-byte numbers. */ | |
596 | case c_num4: | |
597 | { uint c1, c2; | |
598 | long lw; | |
599 | decrypt_next(*cip, state, c0); | |
600 | decrypt_next(cip[1], state, c1); | |
601 | decrypt_next(cip[2], state, c2); | |
602 | decrypt_next(cip[3], state, lw); | |
603 | cip += 4; | |
604 | lw += (ulong)c0 << 24; | |
605 | lw += (ulong)c1 << 16; | |
606 | lw += c2 << 8; | |
607 | *++csp = int2fixed(lw); | |
608 | if ( lw != fixed2long(*csp) ) | |
609 | return_error(gs_error_rangecheck); | |
610 | } goto pushed; | |
611 | } | |
612 | } | |
613 | } | |
614 | ||
615 | /* Add a horizontal stem hint. */ | |
616 | private void near | |
617 | type1_hstem(gs_type1_state *pis, fixed y, fixed dy) | |
618 | { stem_hint *psh; | |
619 | if ( dy < 0 ) y += dy, dy = -dy; | |
620 | psh = type1_stem(&pis->hstem_hints, y, dy); | |
621 | if ( psh == 0 ) return; | |
622 | /* Compute adjustments here */ | |
623 | } | |
624 | ||
625 | /* Add a vertical stem hint. */ | |
626 | private void near | |
627 | type1_vstem(gs_type1_state *pis, fixed x, fixed dx) | |
628 | { stem_hint *psh; | |
629 | if ( dx < 0 ) x += dx, dx = -dx; | |
630 | psh = type1_stem(&pis->vstem_hints, x, dx); | |
631 | if ( psh == 0 ) return; | |
632 | /* Compute adjustments here */ | |
633 | } | |
634 | ||
635 | /* Add a stem hint, keeping the table sorted. */ | |
636 | /* Return the stem hint pointer, or 0 if the table is full. */ | |
637 | private stem_hint *near | |
638 | type1_stem(stem_hint_table *psht, fixed v0, fixed d) | |
639 | { stem_hint *bot = &psht->data[0]; | |
640 | stem_hint *top = bot + psht->count; | |
641 | if ( psht->count >= max_stems ) return 0; | |
642 | while ( top > bot && v0 < top[-1].v0 ) | |
643 | { *top = top[-1]; | |
644 | top--; | |
645 | } | |
646 | top->v0 = v0, top->v1 = v0 + d; | |
647 | psht->count++; | |
648 | return top; | |
649 | } | |
650 | ||
651 | /* Handle the end of a character. We break this out into a separate */ | |
652 | /* procedure so as not to overwhelm the optimizing compilers. */ | |
653 | private int near | |
654 | type1_endchar(gs_type1_state *pis, gs_state *pgs, gx_path *ppath) | |
655 | { int use_stroke = pis->paint_type == 1 || pis->paint_type == 2; | |
656 | fixed ftx = pgs->ctm.tx_fixed, fty = pgs->ctm.ty_fixed; | |
657 | int code; | |
658 | /* Set the current point to the character origin: */ | |
659 | /* the 'show' loop will take care of adding in */ | |
660 | /* the width we supply to setcharwidth/cachedevice. */ | |
661 | gx_path_add_point(ppath, ftx, fty); | |
662 | if ( pis->charpath_flag ) | |
663 | { code = gs_setcharwidth(pis->penum, pgs, | |
664 | fixed2float(pis->width.x), | |
665 | fixed2float(pis->width.y)); | |
666 | if ( code < 0 ) return code; | |
667 | /* Merge the path into its parent */ | |
668 | return gx_path_add_path(pgs->saved->path, ppath); | |
669 | } | |
670 | { gs_rect bbox; | |
671 | code = gs_pathbbox(pgs, &bbox); | |
672 | if ( code < 0 ) /* must be a null path */ | |
673 | { bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0; | |
674 | } | |
675 | #ifdef DEBUG | |
676 | if ( gs_debug['1'] ) | |
677 | dprintf4("[1]bbox=(%g,%g),(%g,%g)\n", | |
678 | bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y); | |
679 | #endif | |
680 | { /* Expand the bounding box to encompass */ | |
681 | /* the width of the stroke (if stroking). */ | |
682 | /* setcachedevice also adds 1 or 2 pixels, */ | |
683 | /* so we don't have to worry about rounding. */ | |
684 | if ( use_stroke ) | |
685 | { float adjust = gs_currentlinewidth(pgs); | |
686 | if ( adjust < 1 ) adjust = 1; | |
687 | /****** SHOULD SCALE ******/ | |
688 | bbox.p.x -= adjust; | |
689 | bbox.p.y -= adjust; | |
690 | bbox.q.x += adjust; | |
691 | bbox.q.y += adjust; | |
692 | } | |
693 | } | |
694 | code = gs_setcachedevice(pis->penum, pgs, | |
695 | fixed2float(pis->width.x), | |
696 | fixed2float(pis->width.y), | |
697 | bbox.p.x, bbox.p.y, | |
698 | bbox.q.x, bbox.q.y); | |
699 | if ( code < 0 ) return code; | |
700 | } | |
701 | /* We've already constructed the path: */ | |
702 | /* translate it so it matches the cache device. */ | |
703 | gx_path_translate(pgs->path, pgs->ctm.tx_fixed - ftx, | |
704 | pgs->ctm.ty_fixed - fty); | |
705 | if ( code < 0 ) return code; | |
706 | /****** | |
707 | ****** The adjust parameter is a hack to make | |
708 | ****** characters come out more bold, since we | |
709 | ****** don't look at the hints. | |
710 | ******/ | |
711 | gx_color_load(pgs->dev_color, pgs); | |
712 | return (use_stroke ? gs_stroke(pgs) : | |
713 | gs_fill_adjust(pgs, float2fixed(type1_fill_adjust))); | |
714 | } | |
715 | ||
716 | /* Pop a (fixed) number off the internal stack. */ | |
717 | /* The client uses this to get the arguments for an OtherSubr. */ | |
718 | int | |
719 | gs_type1_pop(gs_type1_state *pis, fixed *pf) | |
720 | { *pf = pis->ostack[--(pis->os_count)]; | |
721 | return 0; | |
722 | } |