386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / gstype1.c
CommitLineData
9ef61858
WJ
1/* Copyright (C) 1990, 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
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. */
42int
43gs_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. */
56int
57gs_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. */
76typedef 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 */
83typedef struct {
84 fixed v0, v1; /* coordinates (widened a little) */
85 gs_fixed_point adjust_lower, adjust_upper; /* adjustments */
86} stem_hint;
87typedef 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 */
95struct 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 */
122const uint gs_type1_state_sizeof = sizeof(gs_type1_state);
123
124/* Imported procedures */
125extern 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. */
129int
130gs_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);
179private void near
180type1_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
212private void near
213accum_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
239int
240gs_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
247int
248gs_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
260if ( 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
269int
270gs_op1_hsbw(register is_ptr ps, fixed sbx, fixed wx)
271{ return gs_op1_sbw(ps, sbx, (fixed)0, wx, (fixed)0);
272}
273
274int
275gs_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. */
302private void near type1_hstem(P3(gs_type1_state *, fixed, fixed));
303private void near type1_vstem(P3(gs_type1_state *, fixed, fixed));
304private stem_hint *near type1_stem(P3(stem_hint_table *, fixed, fixed));
305private int near type1_endchar(P3(gs_type1_state *, gs_state *, gx_path *));
306int
307gs_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;
353call: 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;
361cont: cip = ipsp->ip;
362 state = ipsp->dstate;
363top: 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);
378move: /* 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);
384line: /* 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);
387cc: if ( code < 0 ) return code;
388pp:
389#ifdef DEBUG
390if ( 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)
563pi: *++csp = int2fixed(c_value_num1(c));
564pushed:
565#ifdef DEBUG
566if ( 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
579pos2: { 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
591neg2: { 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. */
616private void near
617type1_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. */
626private void near
627type1_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. */
637private stem_hint *near
638type1_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. */
653private int near
654type1_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
676if ( 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. */
718int
719gs_type1_pop(gs_type1_state *pis, fixed *pf)
720{ *pf = pis->ostack[--(pis->os_count)];
721 return 0;
722}