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