1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: zchar1.c 9043 2008-08-28 22:48:19Z giles $ */
15
/* Type 1 character display operator */
22
#include "gxdevice.h" /* for gxfont.h */
28
#include "gzstate.h" /* for path for gs_type1_init */
29
/* (should only be gsstate.h) */
31
#include "gspaint.h" /* for gs_fill, gs_stroke */
47
* Properly designed fonts, which have no self-intersecting outlines
48
* and in which outer and inner outlines are drawn in opposite
49
* directions, aren't affected by choice of filling rule; but some
50
* badly designed fonts in the Genoa test suite seem to require
51
* using the even-odd rule to match Adobe interpreters.
53
* Properly designed fonts will render correctly with: eofill
54
* (required for Adobe CPSI compliant behavior
57
* On April 4, 2002, we received bug report #539359
58
* which we interpret as some Genoa test are now obsolete,
59
* so we need to drop the bad font tolerance feature
60
* explained above. This temporary patch changes
61
* the even-odd rule back to non-zero rule.
62
* This patch to be kept until we accumulate
63
* enough information from regression testing and
64
* from user responses.
67
/* *********************************************************************
68
* Make this dynamic via a global (somewhat better than a COMPILE option
69
***********************************************************************/
70
#define GS_CHAR_FILL gs_fill
72
/* ---------------- Utilities ---------------- */
74
/* Test whether a font is a CharString font. */
76
font_uses_charstrings(const gs_font *pfont)
78
return (pfont->FontType == ft_encrypted ||
79
pfont->FontType == ft_encrypted2 ||
80
pfont->FontType == ft_disk_based);
83
/* Initialize a Type 1 interpreter. */
85
type1_exec_init(gs_type1_state *pcis, gs_text_enum_t *penum,
86
gs_state *pgs, gs_font_type1 *pfont1)
89
* We have to disregard penum->pis and penum->path, and render to
90
* the current gstate and path. This is a design bug that we will
91
* have to address someday!
95
gs_log2_scale_point log2_subpixels;
97
if (color_is_pure(pgs->dev_color)) /* Keep consistency with alpha_buffer_bits() */
98
alpha_bits = (*dev_proc(pgs->device, get_alpha_bits)) (pgs->device, go_text);
99
if (alpha_bits <= 1) {
100
/* We render to cache device or the target device has no alpha bits. */
101
log2_subpixels = penum->log2_scale;
103
/* We'll render to target device through alpha buffer. */
104
/* Keep consistency with alpha_buffer_init() */
105
log2_subpixels.x = log2_subpixels.y = ilog2(alpha_bits);
107
return gs_type1_interp_init(pcis, (gs_imager_state *)pgs, pgs->path,
108
&penum->log2_scale, &log2_subpixels,
109
(penum->text.operation & TEXT_DO_ANY_CHARPATH) != 0 ||
110
penum->device_disabled_grid_fitting,
111
pfont1->PaintType, pfont1);
114
/* ---------------- .type1execchar ---------------- */
117
* This is the workhorse for %Type1/2BuildChar, %Type1/2BuildGlyph,
118
* CCRun, and CID fonts. Eventually this will appear in the C API;
119
* even now, its normal control path doesn't use any continuations.
123
* Define the state record for this operator, which must save the metrics
124
* separately as well as the Type 1 interpreter state.
126
typedef struct gs_type1exec_state_s {
127
gs_type1_state cis; /* must be first */
128
i_ctx_t *i_ctx_p; /* so push/pop can access o-stack */
130
int /*metrics_present */ present;
132
bool use_FontBBox_as_Metrics2;
134
* The following elements are only used locally to make the stack clean
135
* for OtherSubrs: they don't need to be declared for the garbage
141
} gs_type1exec_state;
143
gs_private_st_suffix_add1(st_gs_type1exec_state, gs_type1exec_state,
144
"gs_type1exec_state", gs_type1exec_state_enum_ptrs,
145
gs_type1exec_state_reloc_ptrs, st_gs_type1_state,
148
/* Forward references */
149
static int bbox_continue(i_ctx_t *);
150
static int nobbox_continue(i_ctx_t *);
151
static int type1_push_OtherSubr(i_ctx_t *, const gs_type1exec_state *,
152
int (*)(i_ctx_t *), const ref *);
153
static int type1_call_OtherSubr(i_ctx_t *, const gs_type1exec_state *,
154
int (*)(i_ctx_t *), const ref *);
155
static int type1_callout_dispatch(i_ctx_t *, int (*)(i_ctx_t *), int);
156
static int type1_continue_dispatch(i_ctx_t *, gs_type1exec_state *,
157
const ref *, ref *, int);
158
static int op_type1_cleanup(i_ctx_t *);
159
static void op_type1_free(i_ctx_t *);
160
static int bbox_getsbw_continue(i_ctx_t *);
161
static int type1exec_bbox(i_ctx_t *, gs_text_enum_t *, gs_type1exec_state *, gs_font *, op_proc_t *exec_cont);
162
static int bbox_finish_fill(i_ctx_t *);
163
static int bbox_finish_stroke(i_ctx_t *);
164
static int bbox_fill(i_ctx_t *);
165
static int bbox_stroke(i_ctx_t *);
166
static int nobbox_finish(i_ctx_t *, gs_type1exec_state *);
167
static int nobbox_draw(i_ctx_t *, int (*)(gs_state *));
168
static int nobbox_fill(i_ctx_t *);
169
static int nobbox_stroke(i_ctx_t *);
171
/* <font> <code|name> <name> <charstring> .type1execchar - */
173
ztype1execchar(i_ctx_t *i_ctx_p)
175
return charstring_execchar(i_ctx_p, (1 << (int)ft_encrypted) |
176
(1 << (int)ft_disk_based));
179
charstring_execchar_aux(i_ctx_t *i_ctx_p, gs_text_enum_t *penum, gs_font *pfont)
182
gs_font_base *const pbfont = (gs_font_base *) pfont;
183
gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
184
const gs_type1_data *pdata;
185
gs_type1exec_state cxs;
186
gs_type1_state *const pcis = &cxs.cis;
187
gs_rect FontBBox = pfont1->FontBBox;
190
if (penum->current_font->FontType == ft_CID_encrypted) {
191
if (FontBBox.q.x <= FontBBox.p.x && FontBBox.q.y <= FontBBox.p.y) {
192
gs_font_cid0 *pfcid0 = (gs_font_cid0 *)penum->current_font;
194
FontBBox = pfcid0->FontBBox;
198
pdata = &pfont1->data;
200
* Any reasonable implementation would execute something like
201
* 1 setmiterlimit 0 setlinejoin 0 setlinecap
202
* here, but the Adobe implementations don't.
204
* If this is a stroked font, set the stroke width.
206
if (pfont->PaintType)
207
gs_setlinewidth(igs, pfont->StrokeWidth);
208
check_estack(3); /* for continuations */
210
* Execute the definition of the character.
213
return zchar_exec_char_proc(i_ctx_p);
215
* The definition must be a Type 1 CharString.
216
* Note that we do not require read access: this is deliberate.
218
check_type(*op, t_string);
219
if (r_size(op) <= max(pdata->lenIV, 0))
220
return_error(e_invalidfont);
222
* In order to make character oversampling work, we must
223
* set up the cache before calling .type1addpath.
224
* To do this, we must get the bounding box from the FontBBox,
225
* and the width from the CharString or the Metrics.
226
* If the FontBBox isn't valid, we can't do any of this.
229
if ((penum->FontBBox_as_Metrics2.x == 0 &&
230
penum->FontBBox_as_Metrics2.y == 0) ||
231
gs_rootfont(igs)->WMode == 0 ) {
232
code = zchar_get_metrics(pbfont, op - 1, cxs.sbw);
236
cxs.use_FontBBox_as_Metrics2 = false;
237
} else { /* pass here if FontType==9,11 && WMode==1*/
238
cxs.sbw[0] = penum->FontBBox_as_Metrics2.x / 2;
239
cxs.sbw[1] = penum->FontBBox_as_Metrics2.y;
241
cxs.sbw[3] = -penum->FontBBox_as_Metrics2.x; /* Sic! */
242
cxs.use_FontBBox_as_Metrics2 = true;
243
cxs.present = metricsNone;
245
/* Establish a current point. */
246
code = gs_moveto(igs, 0.0, 0.0);
249
code = type1_exec_init(pcis, penum, igs, pfont1);
252
gs_type1_set_callback_data(pcis, &cxs);
253
if (FontBBox.q.x > FontBBox.p.x &&
254
FontBBox.q.y > FontBBox.p.y
256
/* The FontBBox appears to be valid. */
257
op_proc_t exec_cont = 0;
259
cxs.char_bbox = pfont1->FontBBox;
260
code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, &exec_cont);
261
if (code >= 0 && exec_cont != 0)
262
code = (*exec_cont)(i_ctx_p);
265
/* The FontBBox is not valid */
266
const ref *opstr = op;
268
const gs_matrix * pctm = &ctm_only(igs);
270
/* First, check for singular CTM */
271
if (pctm->xx * pctm->yy == pctm->xy * pctm->yx) {
272
/* The code below won't be able to find the FontBBox but we
273
* don't need it anyway. Set an empty box and consider it valid.
275
op_proc_t exec_cont = 0;
277
cxs.char_bbox.p.x = 0;
278
cxs.char_bbox.p.y = 0;
279
cxs.char_bbox.q.x = 0;
280
cxs.char_bbox.q.y = 0;
281
code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, &exec_cont);
282
if (code >= 0 && exec_cont != 0)
283
code = (*exec_cont)(i_ctx_p);
286
/* Now we create the path first, then do the setcachedevice.
287
* If we are oversampling (in this case, only for anti-
288
* aliasing, not just to improve quality), we have to
289
* create the path twice, since we can't know the
290
* oversampling factor until after setcachedevice.
292
switch (cxs.present) {
293
case metricsSideBearingAndWidth: {
296
pt.x = cxs.sbw[0], pt.y = cxs.sbw[1];
297
gs_type1_set_lsb(pcis, &pt);
300
case metricsWidthOnly: {
303
pt.x = cxs.sbw[2], pt.y = cxs.sbw[3];
304
gs_type1_set_width(pcis, &pt);
308
/* Continue interpreting. */
310
code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr, 4);
311
op = osp; /* OtherSubrs might change it */
313
case 0: /* all done */
314
return nobbox_finish(i_ctx_p, &cxs);
315
default: /* code < 0, error */
317
case type1_result_callothersubr: /* unknown OtherSubr */
318
return type1_call_OtherSubr(i_ctx_p, &cxs, nobbox_continue,
320
case type1_result_sbw: /* [h]sbw, just continue */
321
switch (cxs.present) {
323
cxs.sbw[0] = fixed2float(pcis->lsb.x);
324
cxs.sbw[1] = fixed2float(pcis->lsb.y);
326
case metricsWidthOnly:
327
cxs.sbw[2] = fixed2float(pcis->width.x);
328
cxs.sbw[3] = fixed2float(pcis->width.y);
337
charstring_execchar(i_ctx_t *i_ctx_p, int font_type_mask)
339
gs_text_enum_t *penum = op_show_find(i_ctx_p);
342
int code = font_param(op - 3, &pfont);
347
pfont->FontType >= sizeof(font_type_mask) * 8 ||
348
!(font_type_mask & (1 << (int)pfont->FontType)))
349
return_error(e_undefined);
350
code = charstring_execchar_aux(i_ctx_p, penum, pfont);
351
if (code < 0 && igs->in_cachedevice == CACHE_DEVICE_CACHING) {
352
/* Perform the cache cleanup, when the cached character data
353
has been allocated (gx_alloc_char_bits) but
354
the character has not been added to the cache (gx_add_cached_char)
355
due to a falure in the character renderer.
357
gs_show_enum *const penum_s = (gs_show_enum *)penum;
359
if (penum_s->cc != NULL) {
360
gx_free_cached_char(pfont->dir, penum_s->cc);
367
/* -------- bbox case -------- */
369
/* Do all the work for the case where we have a bounding box. */
370
/* Returns exec_cont - a function, which must be called by caller after this function. */
372
type1exec_bbox(i_ctx_t *i_ctx_p, gs_text_enum_t *penum, gs_type1exec_state * pcxs,
373
gs_font * pfont, op_proc_t *exec_cont)
376
gs_type1_state *const pcis = &pcxs->cis;
377
gs_font_base *const pbfont = (gs_font_base *) pfont;
378
op_proc_t cont = (pbfont->PaintType == 0 && penum->orig_font->PaintType == 0
379
? bbox_finish_fill : bbox_finish_stroke);
384
* We appear to have a valid bounding box. If we don't have Metrics for
385
* this character, start interpreting the CharString; do the
386
* setcachedevice as soon as we know the (side bearing and) width.
388
if ((pcxs->present == metricsNone && !pcxs->use_FontBBox_as_Metrics2) ||
389
(penum->orig_font->WMode && zchar_get_CDevProc(pbfont, &pcdevproc))) {
390
/* Get the width from the CharString,
391
* then set the cache device. */
392
/* We pass here when WMode==1 and the font has CDevProc,
393
* because we do need sbw as CDevProc's argument.
394
* A more natural way would be not setting pcxs->use_FontBBox_as_Metrics2
395
* when the font has CDevProc, except for missing sbw in the glyph.
396
* We prefer to pass here because we've got examples
397
* of Tyoe 1 fonts with empty glyphs, i.e. with no sbw,
398
* so we don't want to assume that they'll never appear in a CID font.
399
* In that case penum->FontBBox_as_Metrics2 will go here to zchar_set_cache. */
404
/* Since an OtherSubr callout might change osp, */
405
/* save the character name now. */
406
ref_assign(&cnref, op - 1);
407
code = type1_continue_dispatch(i_ctx_p, pcxs, op, &other_subr, 4);
408
op = osp; /* OtherSubrs might change it */
410
default: /* code < 0 or done, error */
411
return ((code < 0 ? code :
412
gs_note_error(e_invalidfont)));
413
case type1_result_callothersubr: /* unknown OtherSubr */
414
return type1_call_OtherSubr(i_ctx_p, pcxs,
415
bbox_getsbw_continue,
417
case type1_result_sbw: /* [h]sbw, done */
420
type1_cis_get_metrics(pcis, pcxs->sbw);
421
return zchar_set_cache(i_ctx_p, pbfont, &cnref,
424
cont, exec_cont, NULL);
426
/* We have the width and bounding box: */
427
/* set up the cache device now. */
428
return zchar_set_cache(i_ctx_p, pbfont, op - 1,
429
(pcxs->present == metricsSideBearingAndWidth
430
&& !pcxs->use_FontBBox_as_Metrics2 ?
435
(pcxs->use_FontBBox_as_Metrics2 ? pcxs->sbw : NULL));
439
/* Continue from an OtherSubr callout while getting metrics. */
441
bbox_getsbw_continue(i_ctx_t *i_ctx_p)
445
gs_type1exec_state *pcxs = r_ptr(esp, gs_type1exec_state);
446
gs_type1_state *const pcis = &pcxs->cis;
449
code = type1_continue_dispatch(i_ctx_p, pcxs, NULL, &other_subr, 4);
450
op = osp; /* in case z1_push/pop_proc was called */
452
default: /* code < 0 or done, error */
453
op_type1_free(i_ctx_p);
454
return ((code < 0 ? code : gs_note_error(e_invalidfont)));
455
case type1_result_callothersubr: /* unknown OtherSubr */
456
return type1_push_OtherSubr(i_ctx_p, pcxs, bbox_getsbw_continue,
458
case type1_result_sbw: { /* [h]sbw, done */
460
const gs_font_base *const pbfont =
461
(const gs_font_base *)pcis->pfont;
463
op_proc_t cont = (pbfont->PaintType == 0 ? bbox_finish_fill : bbox_finish_stroke), exec_cont = 0;
465
/* Get the metrics before freeing the state. */
466
type1_cis_get_metrics(pcis, sbw);
467
bbox = pcxs->char_bbox;
468
op_type1_free(i_ctx_p);
469
code = zchar_set_cache(i_ctx_p, pbfont, op - 1, sbw, sbw + 2, &bbox,
470
cont, &exec_cont, NULL);
471
if (code >= 0 && exec_cont != 0)
472
code = (*exec_cont)(i_ctx_p);
478
/* <font> <code|name> <name> <charstring> <sbx> <sby> %bbox_{fill|stroke} - */
479
/* <font> <code|name> <name> <charstring> %bbox_{fill|stroke} - */
480
static int bbox_finish(i_ctx_t *i_ctx_p, op_proc_t cont, op_proc_t *exec_cont);
482
bbox_finish_fill(i_ctx_t *i_ctx_p)
484
op_proc_t exec_cont = 0;
487
code = bbox_finish(i_ctx_p, bbox_fill, &exec_cont);
488
if (code >= 0 && exec_cont != 0)
489
code = exec_cont(i_ctx_p);
493
bbox_finish_stroke(i_ctx_t *i_ctx_p)
495
op_proc_t exec_cont = 0;
498
code = bbox_finish(i_ctx_p, bbox_stroke, &exec_cont);
499
if (code >= 0 && exec_cont != 0)
500
code = exec_cont(i_ctx_p);
505
bbox_finish(i_ctx_t *i_ctx_p, op_proc_t cont, op_proc_t *exec_cont)
506
{ /* Returns exec_cont - a function, which must be called by caller after this function. */
510
gs_text_enum_t *penum = op_show_find(i_ctx_p);
511
gs_type1exec_state cxs; /* stack allocate to avoid sandbars */
512
gs_type1_state *const pcis = &cxs.cis;
520
if (!r_has_type(opc, t_string)) {
522
code = num_params(op, 2, sbxy);
529
check_type(*opc, t_string);
531
code = font_param(opc - 3, &pfont);
534
if (penum == 0 || !font_uses_charstrings(pfont))
535
return_error(e_undefined);
537
gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
538
int lenIV = pfont1->data.lenIV;
540
if (lenIV > 0 && r_size(opc) <= lenIV)
541
return_error(e_invalidfont);
542
check_estack(5); /* in case we need to do a callout */
543
code = type1_exec_init(pcis, penum, igs, pfont1);
547
gs_type1_set_lsb(pcis, psbpt);
551
code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr,
553
op = osp; /* OtherSubrs might have altered it */
555
case 0: /* all done */
556
/* Call the continuation now. */
561
case type1_result_callothersubr: /* unknown OtherSubr */
562
push_op_estack(cont); /* call later */
563
return type1_call_OtherSubr(i_ctx_p, &cxs, bbox_continue,
565
case type1_result_sbw: /* [h]sbw, just continue */
568
default: /* code < 0, error */
574
bbox_continue(i_ctx_t *i_ctx_p)
577
int npop = (r_has_type(op, t_string) ? 4 : 6);
578
int code = type1_callout_dispatch(i_ctx_p, bbox_continue, npop);
581
op = osp; /* OtherSubrs might have altered it */
582
npop -= 4; /* nobbox_fill/stroke handles the rest */
585
op_type1_free(i_ctx_p);
591
* Check the path against FontBBox before drawing. The original operands
592
* of type1execchar are still on the o-stack.
593
* Returns exec_cont - a function, which must be called by caller after this function.
596
bbox_draw(i_ctx_t *i_ctx_p, int (*draw)(gs_state *), op_proc_t *exec_cont)
601
gs_text_enum_t *penum;
602
gs_font_base * pbfont;
603
gs_font_type1 * pfont1;
604
gs_type1exec_state cxs;
607
if (igs->in_cachedevice < 2) /* not caching */
608
return nobbox_draw(i_ctx_p, draw);
609
if ((code = font_param(op - 3, &pfont)) < 0)
611
penum = op_show_find(i_ctx_p);
612
if (penum == 0 || !font_uses_charstrings(pfont))
613
return_error(e_undefined);
614
if ((code = gs_pathbbox(igs, &bbox)) < 0) {
616
* If the matrix is singular, all user coordinates map onto a
617
* straight line. Don't bother rendering the character at all.
619
if (code == e_undefinedresult) {
626
if (draw == gs_stroke) {
627
/* Expand the bounding box by the line width. */
628
float width = gs_currentlinewidth(igs) * 1.41422;
630
bbox.p.x -= width, bbox.p.y -= width;
631
bbox.q.x += width, bbox.q.y += width;
633
pbfont = (gs_font_base *)pfont;
634
if (rect_within(bbox, pbfont->FontBBox)) /* within bounds */
635
return nobbox_draw(i_ctx_p, draw);
636
/* Enlarge the FontBBox to save work in the future. */
637
rect_merge(pbfont->FontBBox, bbox);
638
/* Dismantle everything we've done, and start over. */
639
gs_text_retry(penum);
640
pfont1 = (gs_font_type1 *) pfont;
641
if ((penum->FontBBox_as_Metrics2.x == 0 &&
642
penum->FontBBox_as_Metrics2.y == 0) ||
643
gs_rootfont(igs)->WMode == 0 ) {
644
code = zchar_get_metrics(pbfont, op - 1, cxs.sbw);
648
cxs.use_FontBBox_as_Metrics2 = false;
650
cxs.sbw[0] = penum->FontBBox_as_Metrics2.x / 2;
651
cxs.sbw[1] = penum->FontBBox_as_Metrics2.y;
653
cxs.sbw[3] = -penum->FontBBox_as_Metrics2.x; /* Sic! */
654
cxs.use_FontBBox_as_Metrics2 = true;
655
cxs.present = metricsSideBearingAndWidth;
657
code = type1_exec_init(&cxs.cis, penum, igs, pfont1);
660
cxs.char_bbox = pfont1->FontBBox;
661
code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, exec_cont);
665
bbox_fill(i_ctx_t *i_ctx_p)
667
op_proc_t exec_cont = 0;
670
/* See above re GS_CHAR_FILL. */
671
code = bbox_draw(i_ctx_p, GS_CHAR_FILL, &exec_cont);
672
if (code >= 0 && exec_cont != 0)
673
code = (*exec_cont)(i_ctx_p);
677
bbox_stroke(i_ctx_t *i_ctx_p)
679
op_proc_t exec_cont = 0;
682
code = bbox_draw(i_ctx_p, gs_stroke, &exec_cont);
683
if (code >= 0 && exec_cont != 0)
684
code = (*exec_cont)(i_ctx_p);
688
/* -------- Common code -------- */
690
/* Handle the results of interpreting the CharString. */
691
/* pcref points to a t_string ref. */
693
type1_continue_dispatch(i_ctx_t *i_ctx_p, gs_type1exec_state *pcxs,
694
const ref * pcref, ref *pos, int num_args)
698
gs_glyph_data_t cs_data;
699
gs_glyph_data_t *pcsd;
701
cs_data.memory = imemory;
705
gs_glyph_data_from_string(&cs_data, pcref->value.const_bytes,
706
r_size(pcref), NULL);
710
* Since OtherSubrs may push or pop values on the PostScript operand
711
* stack, remove the arguments of .type1execchar before calling the
712
* Type 1 interpreter, and put them back afterwards unless we're
713
* about to execute an OtherSubr procedure. Also, we must set up
714
* the callback data for pushing OtherSubrs arguments.
716
pcxs->i_ctx_p = i_ctx_p;
717
pcxs->num_args = num_args;
718
memcpy(pcxs->save_args, osp - (num_args - 1), num_args * sizeof(ref));
720
gs_type1_set_callback_data(&pcxs->cis, pcxs);
721
code = pcxs->cis.pfont->data.interpret(&pcxs->cis, pcsd, &value);
723
case type1_result_callothersubr: {
725
* The Type 1 interpreter handles all known OtherSubrs,
726
* so this must be an unknown one.
728
const font_data *pfdata = pfont_data(gs_currentfont(igs));
730
code = array_get(imemory, &pfdata->u.type1.OtherSubrs, (long)value, pos);
732
return type1_result_callothersubr;
735
/* Put back the arguments removed above. */
736
memcpy(osp + 1, pcxs->save_args, num_args * sizeof(ref));
742
* Push a continuation, the arguments removed for the OtherSubr, and
743
* the OtherSubr procedure.
746
type1_push_OtherSubr(i_ctx_t *i_ctx_p, const gs_type1exec_state *pcxs,
747
int (*cont)(i_ctx_t *), const ref *pos)
749
int i, n = pcxs->num_args;
751
push_op_estack(cont);
753
* Push the saved arguments (in reverse order, so they will get put
754
* back on the operand stack in the correct order) on the e-stack.
756
for (i = n; --i >= 0; ) {
757
*++esp = pcxs->save_args[i];
758
r_clear_attrs(esp, a_executable); /* just in case */
762
return o_push_estack;
766
* Do a callout to an OtherSubr implemented in PostScript.
767
* The caller must have done a check_estack(4 + num_args).
770
type1_call_OtherSubr(i_ctx_t *i_ctx_p, const gs_type1exec_state * pcxs,
771
int (*cont) (i_ctx_t *),
774
/* Move the Type 1 interpreter state to the heap. */
775
gs_type1exec_state *hpcxs =
776
ialloc_struct(gs_type1exec_state, &st_gs_type1exec_state,
777
"type1_call_OtherSubr");
780
return_error(e_VMerror);
782
gs_type1_set_callback_data(&hpcxs->cis, hpcxs);
783
push_mark_estack(es_show, op_type1_cleanup);
785
make_istruct(esp, 0, hpcxs);
786
return type1_push_OtherSubr(i_ctx_p, pcxs, cont, pos);
789
/* Continue from an OtherSubr callout while building the path. */
791
type1_callout_dispatch(i_ctx_t *i_ctx_p, int (*cont)(i_ctx_t *),
795
gs_type1exec_state *pcxs = r_ptr(esp, gs_type1exec_state);
799
code = type1_continue_dispatch(i_ctx_p, pcxs, NULL, &other_subr,
802
case 0: /* callout done, cont is on e-stack */
804
default: /* code < 0 or done, error */
805
op_type1_free(i_ctx_p);
806
return ((code < 0 ? code : gs_note_error(e_invalidfont)));
807
case type1_result_callothersubr: /* unknown OtherSubr */
808
return type1_push_OtherSubr(i_ctx_p, pcxs, cont, &other_subr);
809
case type1_result_sbw: /* [h]sbw, just continue */
814
/* Clean up after a Type 1 callout. */
816
op_type1_cleanup(i_ctx_t *i_ctx_p)
818
ifree_object(r_ptr(esp + 2, void), "op_type1_cleanup");
822
op_type1_free(i_ctx_t *i_ctx_p)
824
ifree_object(r_ptr(esp, void), "op_type1_free");
826
* In order to avoid popping from the e-stack and then pushing onto
827
* it, which would violate an interpreter invariant, we simply
828
* overwrite the two e-stack items being discarded (hpcxs and the
829
* cleanup operator) with empty procedures.
831
make_empty_const_array(esp - 1, a_readonly + a_executable);
832
make_empty_const_array(esp, a_readonly + a_executable);
835
/* -------- no-bbox case -------- */
838
nobbox_continue(i_ctx_t *i_ctx_p)
840
int code = type1_callout_dispatch(i_ctx_p, nobbox_continue, 4);
845
gs_type1exec_state *pcxs = r_ptr(esp, gs_type1exec_state);
846
gs_type1exec_state cxs;
849
gs_type1_set_callback_data(&cxs.cis, &cxs);
850
op_type1_free(i_ctx_p);
851
return nobbox_finish(i_ctx_p, &cxs);
855
/* Finish the no-FontBBox case after constructing the path. */
856
/* If we are oversampling for anti-aliasing, we have to go around again. */
857
/* <font> <code|name> <name> <charstring> %nobbox_continue - */
859
nobbox_finish(i_ctx_t *i_ctx_p, gs_type1exec_state * pcxs)
863
gs_text_enum_t *penum = op_show_find(i_ctx_p);
866
if ((code = gs_pathbbox(igs, &pcxs->char_bbox)) < 0 ||
867
(code = font_param(op - 3, &pfont)) < 0
870
if (penum == 0 || !font_uses_charstrings(pfont))
871
return_error(e_undefined);
873
gs_font_base *const pbfont = (gs_font_base *) pfont;
874
gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
875
op_proc_t cont, exec_cont = 0;
877
if (pcxs->present == metricsNone) {
880
if ((code = gs_currentpoint(igs, &endpt)) < 0)
882
pcxs->sbw[2] = endpt.x, pcxs->sbw[3] = endpt.y;
883
pcxs->present = metricsSideBearingAndWidth;
886
* We only need to rebuild the path from scratch if we might
887
* oversample for anti-aliasing.
889
if ((*dev_proc(igs->device, get_alpha_bits))(igs->device, go_text) > 1
892
gs_moveto(igs, 0.0, 0.0);
893
code = type1_exec_init(&pcxs->cis, penum, igs, pfont1);
896
code = type1exec_bbox(i_ctx_p, penum, pcxs, pfont, &exec_cont);
898
cont = (pbfont->PaintType == 0 && penum->orig_font->PaintType == 0
899
? nobbox_fill : nobbox_stroke);
901
code = zchar_set_cache(i_ctx_p, pbfont, op - 1, NULL,
905
(pcxs->use_FontBBox_as_Metrics2 ? pcxs->sbw : NULL));
907
if (code >= 0 && exec_cont != 0)
908
code = (*exec_cont)(i_ctx_p);
912
/* Finish by popping the operands and filling or stroking. */
914
nobbox_draw(i_ctx_t *i_ctx_p, int (*draw)(gs_state *))
916
int code = draw(igs);
923
nobbox_fill(i_ctx_t *i_ctx_p)
925
/* See above re GS_CHAR_FILL. */
926
return nobbox_draw(i_ctx_p, GS_CHAR_FILL);
929
nobbox_stroke(i_ctx_t *i_ctx_p)
931
/* As a compatibility to Adobe, use the exact "StrokeWidth".
932
Reset fill_adjust for that. */
934
gs_fixed_point fa = i_ctx_p->pgs->fill_adjust;
936
i_ctx_p->pgs->fill_adjust.x = i_ctx_p->pgs->fill_adjust.y = 0;
937
code = nobbox_draw(i_ctx_p, gs_stroke);
938
i_ctx_p->pgs->fill_adjust = fa;
942
/* <font> <array> .setweightvector - */
944
zsetweightvector(i_ctx_t *i_ctx_p)
948
int code = font_param(op - 1, &pfont);
949
gs_font_type1 *pfont1;
953
/* The font was not defined yet. Just ignore. See lib/gs_type1.ps . */
957
if (pfont->FontType != ft_encrypted && pfont->FontType != ft_encrypted2)
958
return_error(e_invalidfont);
959
pfont1 = (gs_font_type1 *)pfont;
961
if (size != pfont1->data.WeightVector.count)
962
return_error(e_invalidfont);
963
code = process_float_array(imemory, op, size, pfont1->data.WeightVector.values);
970
/* ------ Initialization procedure ------ */
972
const op_def zchar1_op_defs[] =
974
{"4.type1execchar", ztype1execchar},
975
/* Internal operators */
976
{"4%bbox_getsbw_continue", bbox_getsbw_continue},
977
{"4%bbox_continue", bbox_continue},
978
{"4%bbox_finish_fill", bbox_finish_fill},
979
{"4%bbox_finish_stroke", bbox_finish_stroke},
980
{"4%nobbox_continue", nobbox_continue},
981
{"4%nobbox_fill", nobbox_fill},
982
{"4%nobbox_stroke", nobbox_stroke},
983
{"4.setweightvector", zsetweightvector},
987
/* ------ Auxiliary procedures for type 1 fonts ------ */
990
z1_glyph_data(gs_font_type1 * pfont, gs_glyph glyph, gs_glyph_data_t *pgd)
994
glyph_ref(pfont->memory, glyph, &gref);
995
return zchar_charstring_data((gs_font *)pfont, &gref, pgd);
999
z1_subr_data(gs_font_type1 * pfont, int index, bool global,
1000
gs_glyph_data_t *pgd)
1002
const font_data *pfdata = pfont_data(pfont);
1006
code = array_get(pfont->memory, (global ? &pfdata->u.type1.GlobalSubrs :
1007
&pfdata->u.type1.Subrs),
1011
check_type_only(subr, t_string);
1012
gs_glyph_data_from_string(pgd, subr.value.const_bytes, r_size(&subr),
1018
z1_seac_data(gs_font_type1 *pfont, int ccode, gs_glyph *pglyph,
1019
gs_const_string *gstr, gs_glyph_data_t *pgd)
1021
gs_glyph glyph = gs_c_known_encode((gs_char)ccode,
1022
ENCODING_INDEX_STANDARD);
1026
if (glyph == GS_NO_GLYPH)
1027
return_error(e_rangecheck);
1028
if ((code = gs_c_glyph_name(glyph, gstr)) < 0 ||
1029
(code = name_ref(pfont->memory, gstr->data, gstr->size, &rglyph, 0)) < 0
1033
*pglyph = name_index(pfont->memory, &rglyph);
1035
code = zchar_charstring_data((gs_font *)pfont, &rglyph, pgd);
1040
z1_push(void *callback_data, const fixed * pf, int count)
1042
gs_type1exec_state *pcxs = callback_data;
1043
i_ctx_t *i_ctx_p = pcxs->i_ctx_p;
1044
const fixed *p = pf + count - 1;
1047
check_ostack(count);
1048
for (i = 0; i < count; i++, p--) {
1050
make_real(osp, fixed2float(*p));
1056
z1_pop(void *callback_data, fixed * pf)
1058
gs_type1exec_state *pcxs = callback_data;
1059
i_ctx_t *i_ctx_p = pcxs->i_ctx_p;
1061
int code = real_param(osp, &val);
1065
*pf = float2fixed(val);
1070
/* Define the Type 1 procedure vector. */
1071
const gs_type1_data_procs_t z1_data_procs = {
1072
z1_glyph_data, z1_subr_data, z1_seac_data, z1_push, z1_pop
1075
/* ------ Font procedures for Type 1 fonts ------ */
1078
* Get a Type 1 or Type 2 glyph outline. This is the glyph_outline
1079
* procedure for the font.
1082
zchar1_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
1083
gx_path *ppath, double sbw[4])
1085
gs_font_type1 *const pfont1 = (gs_font_type1 *)font;
1087
gs_glyph_data_t gdata;
1090
glyph_ref(font->memory, glyph, &gref);
1091
gdata.memory = font->memory;
1092
code = zchar_charstring_data(font, &gref, &gdata);
1095
return zcharstring_outline(pfont1, WMode, &gref, &gdata, pmat, ppath, sbw);
1098
* Get a glyph outline given a CharString. The glyph_outline procedure
1099
* for CIDFontType 0 fonts uses this.
1102
zcharstring_outline(gs_font_type1 *pfont1, int WMode, const ref *pgref,
1103
const gs_glyph_data_t *pgd_orig,
1104
const gs_matrix *pmat, gx_path *ppath, double sbw[4])
1106
const gs_glyph_data_t *pgd = pgd_orig;
1108
gs_type1exec_state cxs;
1109
gs_type1_state *const pcis = &cxs.cis;
1110
const gs_type1_data *pdata;
1112
gs_imager_state gis;
1116
pdata = &pfont1->data;
1117
if (pgd->bits.size <= max(pdata->lenIV, 0))
1118
return_error(e_invalidfont);
1119
#if 0 /* Ignore CDevProc for now. */
1120
if (zchar_get_CDevProc((const gs_font_base *)pfont1, &pcdevproc))
1121
return_error(e_rangecheck); /* can't call CDevProc from here */
1125
code = zchar_get_metrics2((gs_font_base *)pfont1, pgref, wv);
1135
code = zchar_get_metrics((gs_font_base *)pfont1, pgref, sbw);
1140
/* Initialize just enough of the imager state. */
1142
gs_matrix_fixed_from_matrix(&gis.ctm, pmat);
1146
gs_make_identity(&imat);
1147
gs_matrix_fixed_from_matrix(&gis.ctm, &imat);
1150
code = gs_type1_interp_init(&cxs.cis, &gis, ppath, NULL, NULL, true, 0,
1154
cxs.cis.no_grid_fitting = true;
1155
gs_type1_set_callback_data(pcis, &cxs);
1156
switch (cxs.present) {
1157
case metricsSideBearingAndWidth:
1158
mpt.x = sbw[0], mpt.y = sbw[1];
1159
gs_type1_set_lsb(pcis, &mpt);
1161
case metricsWidthOnly:
1162
mpt.x = sbw[2], mpt.y = sbw[3];
1163
gs_type1_set_width(pcis, &mpt);
1167
/* Continue interpreting. */
1169
code = pfont1->data.interpret(pcis, pgd, &value);
1171
case 0: /* all done */
1173
default: /* code < 0, error */
1175
case type1_result_callothersubr: /* unknown OtherSubr */
1176
return_error(e_rangecheck); /* can't handle it */
1177
case type1_result_sbw: /* [h]sbw, just continue */
1178
type1_cis_get_metrics(pcis, cxs.sbw);
1179
type1_cis_get_metrics(pcis, sbw);
1186
* Redefine glyph_info to take Metrics[2] and CDevProc into account (unless
1187
* GLYPH_INFO_OUTLINE_WIDTHS is set). If CDevProc is present, return
1188
* e_rangecheck, since we can't call the interpreter from here.
1191
z1_glyph_info_generic(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
1192
int members, gs_glyph_info_t *info, font_proc_glyph_info((*proc)), int wmode)
1196
gs_font_base *const pbfont = (gs_font_base *)font;
1197
int width_members = members & (GLYPH_INFO_WIDTH0 << wmode);
1198
int outline_widths = members & GLYPH_INFO_OUTLINE_WIDTHS;
1199
bool modified_widths = false;
1200
int default_members = members & ~(width_members + outline_widths +
1201
GLYPH_INFO_VVECTOR0 + GLYPH_INFO_VVECTOR1 +
1202
GLYPH_INFO_CDEVPROC);
1203
int done_members = 0;
1207
return (*proc)(font, glyph, pmat, members, info);
1208
if (!outline_widths && zchar_get_CDevProc(pbfont, &pcdevproc)) {
1209
done_members |= GLYPH_INFO_CDEVPROC;
1210
if (members & GLYPH_INFO_CDEVPROC) {
1211
info->members = done_members;
1212
return_error(e_rangecheck);
1214
/* Ignore CDevProc. Used to compure MissingWidth.*/
1217
glyph_ref(pbfont->memory, glyph, &gref);
1218
if (width_members == GLYPH_INFO_WIDTH1) {
1220
code = zchar_get_metrics2(pbfont, &gref, wv);
1222
modified_widths = true;
1223
info->width[1].x = wv[0];
1224
info->width[1].y = wv[1];
1227
done_members = width_members | GLYPH_INFO_VVECTOR1;
1231
if (width_members) {
1233
code = zchar_get_metrics(pbfont, &gref, sbw);
1235
modified_widths = true;
1236
info->width[wmode].x = sbw[2];
1237
info->width[wmode].y = sbw[3];
1238
if (code == metricsSideBearingAndWidth) {
1241
width_members |= GLYPH_INFO_VVECTOR0;
1246
done_members = width_members;
1251
if (outline_widths) {
1252
if (modified_widths || zchar_get_CDevProc(pbfont, &pcdevproc)) {
1253
/* Discard the modified widths, but indicate they exist. */
1254
width_members |= done_members;
1255
done_members = outline_widths;
1258
default_members |= width_members;
1259
if (default_members) {
1260
code = (*proc)(font, glyph, pmat, default_members, info);
1266
info->members |= done_members;
1271
z1_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
1272
int members, gs_glyph_info_t *info)
1274
int wmode = font->WMode;
1276
return z1_glyph_info_generic(font, glyph, pmat, members, info,
1277
&gs_type1_glyph_info, wmode);
1280
/* Get a Type 1 or Type 9 character metrics and set the cache device. */
1282
z1_set_cache(i_ctx_t *i_ctx_p, gs_font_base *pbfont, ref *cnref,
1283
gs_glyph glyph, op_proc_t cont, op_proc_t *exec_cont)
1284
{ /* This function is similar to zchar42_set_cache. */
1286
gs_glyph_info_t info;
1287
int wmode = gs_rootfont(igs)->WMode;
1289
gs_matrix id_matrix = { identity_matrix_body };
1291
code = gs_default_glyph_info((gs_font *)pbfont, glyph, &id_matrix,
1292
((GLYPH_INFO_WIDTH0 | GLYPH_INFO_VVECTOR0) << wmode) | GLYPH_INFO_BBOX,
1298
sbw[2] = info.width[wmode].x;
1299
sbw[3] = info.width[wmode].y;
1300
return zchar_set_cache(i_ctx_p, pbfont, cnref, NULL,
1301
sbw + 2, &info.bbox,
1303
wmode ? sbw : NULL);