1 /* Copyright (C) 1997, 1998, 1999, 2000 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gxtype1.c,v 1.8.4.1.2.1 2003/01/17 00:49:04 giles Exp $ */
20 /* Adobe Type 1 font interpreter support */
21 #include "math_.h"
22 #include "gx.h"
23 #include "gserrors.h"
24 #include "gsccode.h"
25 #include "gsline.h"
26 #include "gsstruct.h"
27 #include "gxarith.h"
28 #include "gxchrout.h"
29 #include "gxfixed.h"
30 #include "gxistate.h"
31 #include "gxmatrix.h"
32 #include "gxcoord.h"
33 #include "gxfont.h"
34 #include "gxfont1.h"
35 #include "gxtype1.h"
36 #include "gzpath.h"
37 
38 /*
39  * The routines in this file are used for both Type 1 and Type 2
40  * charstring interpreters.
41  */
42 
43 /*
44  * Define whether or not to force hints to "big pixel" boundaries
45  * when rasterizing at higher resolution.  With the current algorithms,
46  * a value of 1 is better for devices without alpha capability,
47  * but 0 is better if alpha is available.
48  */
49 #define FORCE_HINTS_TO_BIG_PIXELS 1
50 
51 /* Structure descriptor */
52 public_st_gs_font_type1();
53 
54 /* Define the structure type for a Type 1 interpreter state. */
55 public_st_gs_type1_state();
56 /* GC procedures */
57 private
ENUM_PTRS_WITH(gs_type1_state_enum_ptrs,gs_type1_state * pcis)58 ENUM_PTRS_WITH(gs_type1_state_enum_ptrs, gs_type1_state *pcis)
59 {
60     if (index < pcis->ips_count + 4) {
61 	ENUM_RETURN_CONST_STRING_PTR(gs_type1_state,
62 				     ipstack[index - 4].char_string);
63     }
64     return 0;
65 }
66 ENUM_PTR3(0, gs_type1_state, pfont, pis, path);
67 ENUM_PTR(3, gs_type1_state, callback_data);
68 ENUM_PTRS_END
RELOC_PTRS_WITH(gs_type1_state_reloc_ptrs,gs_type1_state * pcis)69 private RELOC_PTRS_WITH(gs_type1_state_reloc_ptrs, gs_type1_state *pcis)
70 {
71     int i;
72 
73     RELOC_PTR(gs_type1_state, pfont);
74     RELOC_PTR(gs_type1_state, pis);
75     RELOC_PTR(gs_type1_state, path);
76     RELOC_PTR(gs_type1_state, callback_data);
77     for (i = 0; i < pcis->ips_count; i++) {
78 	ip_state_t *ipsp = &pcis->ipstack[i];
79 	int diff = ipsp->ip - ipsp->char_string.data;
80 
81 	RELOC_CONST_STRING_VAR(ipsp->char_string);
82 	ipsp->ip = ipsp->char_string.data + diff;
83     }
84 } RELOC_PTRS_END
85 
86 /* ------ Interpreter services ------ */
87 
88 #define s (*ps)
89 
90 /* We export this for the Type 2 charstring interpreter. */
91 void
accum_xy_proc(register is_ptr ps,fixed dx,fixed dy)92 accum_xy_proc(register is_ptr ps, fixed dx, fixed dy)
93 {
94     ptx += c_fixed(dx, xx),
95 	pty += c_fixed(dy, yy);
96     if (sfc.skewed)
97 	ptx += c_fixed(dy, yx),
98 	    pty += c_fixed(dx, xy);
99 }
100 
101 /* Initialize a Type 1 interpreter. */
102 /* The caller must supply a string to the first call of gs_type1_interpret. */
103 int
gs_type1_interp_init(register gs_type1_state * pcis,gs_imager_state * pis,gx_path * ppath,const gs_log2_scale_point * pscale,bool charpath_flag,int paint_type,gs_font_type1 * pfont)104 gs_type1_interp_init(register gs_type1_state * pcis, gs_imager_state * pis,
105     gx_path * ppath, const gs_log2_scale_point * pscale, bool charpath_flag,
106 		     int paint_type, gs_font_type1 * pfont)
107 {
108     static const gs_log2_scale_point no_scale = {0, 0};
109     const gs_log2_scale_point *plog2_scale =
110 	(FORCE_HINTS_TO_BIG_PIXELS ? pscale : &no_scale);
111 
112     pcis->pfont = pfont;
113     pcis->pis = pis;
114     pcis->path = ppath;
115     pcis->callback_data = pfont; /* default callback data */
116     /*
117      * charpath_flag controls coordinate rounding, hinting, and
118      * flatness enhancement.  If we allow it to be set to true,
119      * charpath may produce results quite different from show.
120      */
121     pcis->charpath_flag = false /*charpath_flag */ ;
122     pcis->paint_type = paint_type;
123     pcis->os_count = 0;
124     pcis->ips_count = 1;
125     pcis->ipstack[0].ip = 0;
126     pcis->ipstack[0].char_string.data = 0;
127     pcis->ipstack[0].char_string.size = 0;
128     pcis->ignore_pops = 0;
129     pcis->init_done = -1;
130     pcis->sb_set = false;
131     pcis->width_set = false;
132     pcis->have_hintmask = false;
133     pcis->num_hints = 0;
134     pcis->seac_accent = -1;
135 
136     /* Set the sampling scale. */
137     set_pixel_scale(&pcis->scale.x, plog2_scale->x);
138     set_pixel_scale(&pcis->scale.y, plog2_scale->y);
139 
140     return 0;
141 }
142 
143 /* Set the push/pop callback data. */
144 void
gs_type1_set_callback_data(gs_type1_state * pcis,void * callback_data)145 gs_type1_set_callback_data(gs_type1_state *pcis, void *callback_data)
146 {
147     pcis->callback_data = callback_data;
148 }
149 
150 
151 /* Preset the left side bearing and/or width. */
152 void
gs_type1_set_lsb(gs_type1_state * pcis,const gs_point * psbpt)153 gs_type1_set_lsb(gs_type1_state * pcis, const gs_point * psbpt)
154 {
155     pcis->lsb.x = float2fixed(psbpt->x);
156     pcis->lsb.y = float2fixed(psbpt->y);
157     pcis->sb_set = true;
158 }
159 void
gs_type1_set_width(gs_type1_state * pcis,const gs_point * pwpt)160 gs_type1_set_width(gs_type1_state * pcis, const gs_point * pwpt)
161 {
162     pcis->width.x = float2fixed(pwpt->x);
163     pcis->width.y = float2fixed(pwpt->y);
164     pcis->width_set = true;
165 }
166 
167 /* Finish initializing the interpreter if we are actually rasterizing */
168 /* the character, as opposed to just computing the side bearing and width. */
169 void
gs_type1_finish_init(gs_type1_state * pcis,gs_op1_state * ps)170 gs_type1_finish_init(gs_type1_state * pcis, gs_op1_state * ps)
171 {
172     gs_imager_state *pis = pcis->pis;
173 
174     /* Set up the fixed version of the transformation. */
175     gx_matrix_to_fixed_coeff(&ctm_only(pis), &pcis->fc, max_coeff_bits);
176     sfc = pcis->fc;
177 
178     /* Set the current point of the path to the origin, */
179     /* in anticipation of the initial [h]sbw. */
180     {
181 	gx_path *ppath = pcis->path;
182 
183 	ptx = pcis->origin.x = ppath->position.x;
184 	pty = pcis->origin.y = ppath->position.y;
185     }
186 
187     /* Initialize hint-related scalars. */
188     pcis->asb_diff = pcis->adxy.x = pcis->adxy.y = 0;
189     pcis->flex_count = flex_max;	/* not in Flex */
190     pcis->dotsection_flag = dotsection_out;
191     pcis->vstem3_set = false;
192     pcis->vs_offset.x = pcis->vs_offset.y = 0;
193     pcis->hints_initial = 0;	/* probably not needed */
194     pcis->hint_next = 0;
195     pcis->hints_pending = 0;
196 
197     /* Assimilate the hints proper. */
198     {
199 	gs_log2_scale_point log2_scale;
200 
201 	log2_scale.x = pcis->scale.x.log2_unit;
202 	log2_scale.y = pcis->scale.y.log2_unit;
203 	if (pcis->charpath_flag)
204 	    reset_font_hints(&pcis->fh, &log2_scale);
205 	else
206 	    compute_font_hints(&pcis->fh, &pis->ctm, &log2_scale,
207 			       &pcis->pfont->data);
208     }
209     reset_stem_hints(pcis);
210 
211     /* Compute the flatness needed for accurate rendering. */
212     pcis->flatness = gs_char_flatness(pis, 0.001);
213 
214     /* Move to the side bearing point. */
215     accum_xy(pcis->lsb.x, pcis->lsb.y);
216     pcis->position.x = ptx;
217     pcis->position.y = pty;
218 
219     pcis->init_done = 1;
220 }
221 
222 /* ------ Operator procedures ------ */
223 
224 int
gs_op1_closepath(register is_ptr ps)225 gs_op1_closepath(register is_ptr ps)
226 {				/* Note that this does NOT reset the current point! */
227     gx_path *ppath = sppath;
228     subpath *psub;
229     segment *pseg;
230     fixed dx, dy;
231     int code;
232 
233     /* Check for and suppress a microscopic closing line. */
234     if ((psub = ppath->current_subpath) != 0 &&
235 	(pseg = psub->last) != 0 &&
236 	(dx = pseg->pt.x - psub->pt.x,
237 	 any_abs(dx) < float2fixed(0.1)) &&
238 	(dy = pseg->pt.y - psub->pt.y,
239 	 any_abs(dy) < float2fixed(0.1))
240 	)
241 	switch (pseg->type) {
242 	    case s_line:
243 		code = gx_path_pop_close_subpath(sppath);
244 		break;
245 	    case s_curve:
246 		/*
247 		 * Unfortunately, there is no "s_curve_close".  (Maybe there
248 		 * should be?)  Just adjust the final point of the curve so it
249 		 * is identical to the closing point.
250 		 */
251 		pseg->pt = psub->pt;
252 #define pcseg ((curve_segment *)pseg)
253 		pcseg->p2.x -= dx;
254 		pcseg->p2.y -= dy;
255 #undef pcseg
256 		/* falls through */
257 	    default:
258 		/* What else could it be?? */
259 		code = gx_path_close_subpath(sppath);
260     } else
261 	code = gx_path_close_subpath(sppath);
262     if (code < 0)
263 	return code;
264     return gx_path_add_point(ppath, ptx, pty);	/* put the point where it was */
265 }
266 
267 int
gs_op1_rrcurveto(register is_ptr ps,fixed dx1,fixed dy1,fixed dx2,fixed dy2,fixed dx3,fixed dy3)268 gs_op1_rrcurveto(register is_ptr ps, fixed dx1, fixed dy1,
269 		 fixed dx2, fixed dy2, fixed dx3, fixed dy3)
270 {
271     gs_fixed_point pt1, pt2;
272     fixed ax0 = sppath->position.x - ptx;
273     fixed ay0 = sppath->position.y - pty;
274 
275     accum_xy(dx1, dy1);
276     pt1.x = ptx + ax0, pt1.y = pty + ay0;
277     accum_xy(dx2, dy2);
278     pt2.x = ptx, pt2.y = pty;
279     accum_xy(dx3, dy3);
280     return gx_path_add_curve(sppath, pt1.x, pt1.y, pt2.x, pt2.y, ptx, pty);
281 }
282 
283 #undef s
284 
285 /* Record the side bearing and character width. */
286 int
gs_type1_sbw(gs_type1_state * pcis,fixed lsbx,fixed lsby,fixed wx,fixed wy)287 gs_type1_sbw(gs_type1_state * pcis, fixed lsbx, fixed lsby, fixed wx, fixed wy)
288 {
289     if (!pcis->sb_set)
290 	pcis->lsb.x = lsbx, pcis->lsb.y = lsby,
291 	    pcis->sb_set = true;	/* needed for accented chars */
292     if (!pcis->width_set)
293 	pcis->width.x = wx, pcis->width.y = wy,
294 	    pcis->width_set = true;
295     if_debug4('1', "[1]sb=(%g,%g) w=(%g,%g)\n",
296 	      fixed2float(pcis->lsb.x), fixed2float(pcis->lsb.y),
297 	      fixed2float(pcis->width.x), fixed2float(pcis->width.y));
298     return 0;
299 }
300 
301 /* Blend values for a Multiple Master font instance. */
302 /* The stack holds values ... K*N othersubr#. */
303 int
gs_type1_blend(gs_type1_state * pcis,fixed * csp,int num_results)304 gs_type1_blend(gs_type1_state *pcis, fixed *csp, int num_results)
305 {
306     gs_type1_data *pdata = &pcis->pfont->data;
307     int num_values = fixed2int_var(csp[-1]);
308     int k1 = num_values / num_results - 1;
309     int i, j;
310     fixed *base;
311     fixed *deltas;
312 
313     if (num_values < num_results ||
314 	num_values % num_results != 0
315 	)
316 	return_error(gs_error_invalidfont);
317     base = csp - 1 - num_values;
318     deltas = base + num_results - 1;
319     for (j = 0; j < num_results;
320 	 j++, base++, deltas += k1
321 	 )
322 	for (i = 1; i <= k1; i++)
323 	    *base += deltas[i] *
324 		pdata->WeightVector.values[i];
325     pcis->ignore_pops = num_results;
326     return num_values - num_results + 2;
327 }
328 
329 /*
330  * Handle a seac.  Do the base character now; when it finishes (detected
331  * in endchar), do the accent.  Note that we pass only 4 operands on the
332  * stack, and pass asb separately.
333  */
334 int
gs_type1_seac(gs_type1_state * pcis,const fixed * cstack,fixed asb,ip_state_t * ipsp)335 gs_type1_seac(gs_type1_state * pcis, const fixed * cstack, fixed asb,
336 	      ip_state_t * ipsp)
337 {
338     gs_font_type1 *pfont = pcis->pfont;
339     gs_const_string bcstr;
340     int code;
341 
342     /* Save away all the operands. */
343     pcis->seac_accent = fixed2int_var(cstack[3]);
344     pcis->save_asb = asb;
345     pcis->save_lsb = pcis->lsb;
346     pcis->save_adxy.x = cstack[0];
347     pcis->save_adxy.y = cstack[1];
348     pcis->os_count = 0;		/* clear */
349     /* Ask the caller to provide the base character's CharString. */
350     code = pfont->data.procs.seac_data
351 	(pfont, fixed2int_var(cstack[2]), NULL, &bcstr);
352     if (code < 0)
353 	return code;
354     /* Continue with the supplied string. */
355     ipsp->char_string = bcstr;
356     ipsp->free_char_string = code;
357     return 0;
358 }
359 
360 /*
361  * Handle the end of a character.  Return 0 if this is really the end of a
362  * character, or 1 if we still have to process the accent of a seac.
363  * In the latter case, the interpreter control stack has been set up to
364  * point to the start of the accent's CharString; the caller must
365  * also set ptx/y to pcis->position.x/y.
366  */
367 int
gs_type1_endchar(gs_type1_state * pcis)368 gs_type1_endchar(gs_type1_state * pcis)
369 {
370     gs_imager_state *pis = pcis->pis;
371     gx_path *ppath = pcis->path;
372 
373     if (pcis->seac_accent >= 0) {	/* We just finished the base character of a seac. */
374 	/* Do the accent. */
375 	gs_font_type1 *pfont = pcis->pfont;
376 	gs_op1_state s;
377 	gs_const_string astr;
378 	int achar = pcis->seac_accent;
379 	int code;
380 
381 	pcis->seac_accent = -1;
382 	/* Reset the coordinate system origin */
383 	sfc = pcis->fc;
384 	ptx = pcis->origin.x, pty = pcis->origin.y;
385 	pcis->asb_diff = pcis->save_asb - pcis->save_lsb.x;
386 	pcis->adxy = pcis->save_adxy;
387 	/*
388 	 * We're going to add in the lsb of the accented character
389 	 * (*not* the lsb of the accent) when we encounter the
390 	 * [h]sbw of the accent, so ignore the lsb for now.
391 	 */
392 	accum_xy(pcis->adxy.x, pcis->adxy.y);
393 	ppath->position.x = pcis->position.x = ptx;
394 	ppath->position.y = pcis->position.y = pty;
395 	pcis->os_count = 0;	/* clear */
396 	/* Clear the ipstack, in case the base character */
397 	/* ended inside a subroutine. */
398 	pcis->ips_count = 1;
399 	/* Remove any base character hints. */
400 	reset_stem_hints(pcis);
401 	/* Ask the caller to provide the accent's CharString. */
402 	code = pfont->data.procs.seac_data(pfont, achar, NULL, &astr);
403 	if (code < 0)
404 	    return code;
405 	/* Continue with the supplied string. */
406 	pcis->ips_count = 1;
407 	pcis->ipstack[0].char_string = astr;
408 	pcis->ipstack[0].free_char_string = code;
409 	return 1;
410     }
411     if (pcis->hint_next != 0 || path_is_drawing(ppath))
412 	apply_path_hints(pcis, true);
413     /* Set the current point to the character origin */
414     /* plus the width. */
415     {
416 	gs_fixed_point pt;
417 
418 	gs_point_transform2fixed(&pis->ctm,
419 				 fixed2float(pcis->width.x),
420 				 fixed2float(pcis->width.y),
421 				 &pt);
422 	gx_path_add_point(ppath, pt.x, pt.y);
423     }
424     if (pcis->scale.x.log2_unit + pcis->scale.y.log2_unit == 0) {	/*
425 									 * Tweak up the fill adjustment.  This is a hack for when
426 									 * we can't oversample.  The values here are based entirely
427 									 * on experience, not theory, and are designed primarily
428 									 * for displays and low-resolution fax.
429 									 */
430 	gs_fixed_rect bbox;
431 	int dx, dy, dmax;
432 
433 	gx_path_bbox(ppath, &bbox);
434 	dx = fixed2int_ceiling(bbox.q.x - bbox.p.x);
435 	dy = fixed2int_ceiling(bbox.q.y - bbox.p.y);
436 	dmax = max(dx, dy);
437 	if (pcis->fh.snap_h.count || pcis->fh.snap_v.count ||
438 	    pcis->fh.a_zone_count
439 	    ) {			/* We have hints.  Only tweak up a little at */
440 	    /* very small sizes, to help nearly-vertical */
441 	    /* or nearly-horizontal diagonals. */
442 	    pis->fill_adjust.x = pis->fill_adjust.y =
443 		(dmax < 15 ? float2fixed(0.15) :
444 		 dmax < 25 ? float2fixed(0.1) :
445 		 fixed_0);
446 	} else {		/* No hints.  Tweak a little more to compensate */
447 	    /* for lack of snapping to pixel grid. */
448 	    pis->fill_adjust.x = pis->fill_adjust.y =
449 		(dmax < 10 ? float2fixed(0.2) :
450 		 dmax < 25 ? float2fixed(0.1) :
451 		 float2fixed(0.05));
452 	}
453     } else {			/* Don't do any adjusting. */
454 	pis->fill_adjust.x = pis->fill_adjust.y = fixed_0;
455     }
456     /* Set the flatness for curve rendering. */
457     if (!pcis->charpath_flag)
458 	gs_imager_setflat(pis, pcis->flatness);
459     return 0;
460 }
461 
462 /* ------ Font procedures ------ */
463 
464 int
gs_type1_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)465 gs_type1_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
466 		    int members, gs_glyph_info_t *info)
467 {
468     gs_font_type1 *const pfont = (gs_font_type1 *)font;
469     gs_type1_data *const pdata = &pfont->data;
470     int wmode = pfont->WMode;
471     int piece_members = members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES);
472     int width_members = members & (GLYPH_INFO_WIDTH0 << wmode);
473     int default_members = members - (piece_members + width_members);
474     int code = 0, gcode = 0;
475     gs_const_string str;
476 
477     if (default_members) {
478 	code = gs_default_glyph_info(font, glyph, pmat, default_members, info);
479 
480 	if (code < 0)
481 	    return code;
482     } else
483 	info->members = 0;
484 
485     if (default_members != members) {
486 	if ((gcode = pdata->procs.glyph_data(pfont, glyph, &str)) < 0)
487 	    return gcode;		/* non-existent glyph */
488     }
489 
490     if (piece_members) {
491 	gs_glyph *pieces =
492 	    (members & GLYPH_INFO_PIECES ? info->pieces : (gs_glyph *)0);
493 	/*
494 	 * Decode the CharString looking for seac.  We have to process
495 	 * callsubr, callothersubr, and return operators, but if we see
496 	 * any other operators other than [h]sbw, pop, hint operators,
497 	 * or endchar, we can return immediately.  We have to include
498 	 * endchar because it is an (undocumented) equivalent for seac
499 	 * in Type 2 CharStrings: see the cx_endchar case in
500 	 * gs_type2_interpret in gstype2.c.
501 	 *
502 	 * It's really unfortunate that we have to duplicate so much parsing
503 	 * code, but factoring out the parser from the interpreter would
504 	 * involve more restructuring than we're prepared to do right now.
505 	 */
506 	bool encrypted = pdata->lenIV >= 0;
507 	fixed cstack[ostack_size];
508 	fixed *csp;
509 	ip_state_t ipstack[ipstack_size + 1];
510 	ip_state_t *ipsp = &ipstack[0];
511 	const byte *cip;
512 	crypt_state state;
513 	int c;
514 
515 	CLEAR_CSTACK(cstack, csp);
516 	info->num_pieces = 0;	/* default */
517 	cip = str.data;
518     call:
519 	state = crypt_charstring_seed;
520 	if (encrypted) {
521 	    int skip = pdata->lenIV;
522 
523 	    /* Skip initial random bytes */
524 	    for (; skip > 0; ++cip, --skip)
525 		decrypt_skip_next(*cip, state);
526 	}
527     top:
528 	for (;;) {
529 	    uint c0 = *cip++;
530 
531 	    charstring_next(c0, state, c, encrypted);
532 	    if (c >= c_num1) {
533 		/* This is a number, decode it and push it on the stack. */
534 		if (c < c_pos2_0) {	/* 1-byte number */
535 		    decode_push_num1(csp, c);
536 		} else if (c < cx_num4) {	/* 2-byte number */
537 		    decode_push_num2(csp, c, cip, state, encrypted);
538 		} else if (c == cx_num4) {	/* 4-byte number */
539 		    long lw;
540 
541 		    decode_num4(lw, cip, state, encrypted);
542 		    *++csp = int2fixed(lw);
543 		} else		/* not possible */
544 		    return_error(gs_error_invalidfont);
545 		continue;
546 	    }
547 #define cnext CLEAR_CSTACK(cstack, csp); goto top
548 	    switch ((char_command) c) {
549 	    default:
550 		goto out;
551 	    case c_callsubr:
552 		c = fixed2int_var(*csp);
553 		code = pdata->procs.subr_data
554 		    (pfont, c, false, &ipsp[1].char_string);
555 		if (code < 0)
556 		    return_error(code);
557 		--csp;
558 		ipsp->ip = cip, ipsp->dstate = state;
559 		++ipsp;
560 		ipsp->free_char_string = code;
561 		cip = ipsp->char_string.data;
562 		goto call;
563 	    case c_return:
564 		if (ipsp->free_char_string > 0)
565 		    gs_free_const_string(pfont->memory,
566 					 ipsp->char_string.data,
567 					 ipsp->char_string.size,
568 					 "gs_type1_glyph_info");
569 		--ipsp;
570 		cip = ipsp->ip, state = ipsp->dstate;
571 		goto top;
572 	    case cx_hstem:
573 	    case cx_vstem:
574 	    case c1_hsbw:
575 		cnext;
576 	    case cx_endchar:
577 		if (csp < cstack + 3)
578 		    goto out;	/* not seac */
579 	    do_seac:
580 		/* This is the payoff for all this code! */
581 		if (pieces) {
582 		    gs_char bchar = fixed2int(csp[-1]);
583 		    gs_char achar = fixed2int(csp[0]);
584 		    int bcode =
585 			pdata->procs.seac_data(pfont, bchar,
586 					       &pieces[0], NULL);
587 		    int acode =
588 			pdata->procs.seac_data(pfont, achar,
589 					       &pieces[1], NULL);
590 
591 		    code = (bcode < 0 ? bcode : acode);
592 		}
593 		info->num_pieces = 2;
594 		goto out;
595 	    case cx_escape:
596 		charstring_next(*cip, state, c, encrypted);
597 		++cip;
598 		switch ((char1_extended_command) c) {
599 		default:
600 		    goto out;
601 		case ce1_vstem3:
602 		case ce1_hstem3:
603 		case ce1_sbw:
604 		    cnext;
605 		case ce1_pop:
606 		    /*
607 		     * pop must do nothing, since it is used after
608 		     * subr# 1 3 callothersubr.
609 		     */
610 		    goto top;
611 		case ce1_seac:
612 		    goto do_seac;
613 		case ce1_callothersubr:
614 		    switch (fixed2int_var(*csp)) {
615 		    default:
616 			goto out;
617 		    case 3:
618 			csp -= 2;
619 			goto top;
620 		    case 12:
621 		    case 13:
622 		    case 14:
623 		    case 15:
624 		    case 16:
625 		    case 17:
626 		    case 18:
627 			cnext;
628 		    }
629 		}
630 	    }
631 #undef cnext
632 	}
633 out:	info->members |= piece_members;
634     }
635 
636     if (width_members) {
637 	/*
638 	 * Interpret the CharString until we get to the [h]sbw.
639 	 */
640 	gs_imager_state gis;
641 	gs_type1_state cis;
642 	static const gs_log2_scale_point no_scale = {0, 0};
643 	int value;
644 
645 	/* Initialize just enough of the imager state. */
646 	if (pmat)
647 	    gs_matrix_fixed_from_matrix(&gis.ctm, pmat);
648 	else {
649 	    gs_matrix imat;
650 
651 	    gs_make_identity(&imat);
652 	    gs_matrix_fixed_from_matrix(&gis.ctm, &imat);
653 	}
654 	gis.flatness = 0;
655 	code = gs_type1_interp_init(&cis, &gis, NULL /* no path needed */,
656 				    &no_scale, true, 0, pfont);
657 	if (code < 0)
658 	    return code;
659 	cis.charpath_flag = true;	/* suppress hinting */
660 	code = pdata->interpret(&cis, &str, &value);
661 	switch (code) {
662 	case 0:		/* done with no [h]sbw, error */
663 	    code = gs_note_error(gs_error_invalidfont);
664 	default:		/* code < 0, error */
665 	    return code;
666 	case type1_result_callothersubr:	/* unknown OtherSubr */
667 	    return_error(gs_error_rangecheck); /* can't handle it */
668 	case type1_result_sbw:
669 	    info->width[wmode].x = fixed2float(cis.width.x);
670 	    info->width[wmode].y = fixed2float(cis.width.y);
671 	    break;
672 	}
673 	info->members |= width_members;
674     }
675 
676     if (gcode > 0)
677 	gs_free_const_string(font->memory, str.data, str.size,
678 			     "gs_type1_glyph_info");
679     return code;
680 }
681