~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to psi/zchar1.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
 
2
   All Rights Reserved.
 
3
  
 
4
   This software is provided AS-IS with no warranty, either express or
 
5
   implied.
 
6
 
 
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.
 
12
*/
 
13
 
 
14
/* $Id: zchar1.c 9043 2008-08-28 22:48:19Z giles $ */
 
15
/* Type 1 character display operator */
 
16
#include "memory_.h"
 
17
#include "ghost.h"
 
18
#include "oper.h"
 
19
#include "gsstruct.h"
 
20
#include "gxfixed.h"
 
21
#include "gxmatrix.h"
 
22
#include "gxdevice.h"           /* for gxfont.h */
 
23
#include "gxfont.h"
 
24
#include "gxfont1.h"
 
25
#include "gxtype1.h"
 
26
#include "gxfcid.h"
 
27
#include "gxchar.h"
 
28
#include "gzstate.h"            /* for path for gs_type1_init */
 
29
                                /* (should only be gsstate.h) */
 
30
#include "gscencs.h"
 
31
#include "gspaint.h"            /* for gs_fill, gs_stroke */
 
32
#include "gspath.h"
 
33
#include "gsrect.h"
 
34
#include "estack.h"
 
35
#include "ialloc.h"
 
36
#include "ichar.h"
 
37
#include "ichar1.h"
 
38
#include "icharout.h"
 
39
#include "idict.h"
 
40
#include "ifont.h"
 
41
#include "igstate.h"
 
42
#include "iname.h"
 
43
#include "iutil.h"
 
44
#include "store.h"
 
45
 
 
46
/*
 
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.
 
52
 * 
 
53
 * Properly designed fonts will render correctly with: eofill
 
54
 * (required for Adobe CPSI compliant behavior
 
55
 */
 
56
/*
 
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.
 
65
 */
 
66
 
 
67
/* *********************************************************************
 
68
 * Make this dynamic via a global (somewhat better than a COMPILE option
 
69
 ***********************************************************************/
 
70
#define GS_CHAR_FILL gs_fill
 
71
 
 
72
/* ---------------- Utilities ---------------- */
 
73
 
 
74
/* Test whether a font is a CharString font. */
 
75
static bool
 
76
font_uses_charstrings(const gs_font *pfont)
 
77
{
 
78
    return (pfont->FontType == ft_encrypted ||
 
79
            pfont->FontType == ft_encrypted2 ||
 
80
            pfont->FontType == ft_disk_based);
 
81
}
 
82
 
 
83
/* Initialize a Type 1 interpreter. */
 
84
static int
 
85
type1_exec_init(gs_type1_state *pcis, gs_text_enum_t *penum,
 
86
                gs_state *pgs, gs_font_type1 *pfont1)
 
87
{
 
88
    /*
 
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!
 
92
     */
 
93
 
 
94
    int alpha_bits = 1; 
 
95
    gs_log2_scale_point log2_subpixels;
 
96
    
 
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;
 
102
    } else {
 
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); 
 
106
    }
 
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);
 
112
}
 
113
 
 
114
/* ---------------- .type1execchar ---------------- */
 
115
 
 
116
/*
 
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.
 
120
 */
 
121
 
 
122
/*
 
123
 * Define the state record for this operator, which must save the metrics
 
124
 * separately as well as the Type 1 interpreter state.
 
125
 */
 
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 */
 
129
    double sbw[4];
 
130
    int /*metrics_present */ present;
 
131
    gs_rect char_bbox;
 
132
    bool use_FontBBox_as_Metrics2;
 
133
    /*
 
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
 
136
     * collector.
 
137
     */
 
138
    ref save_args[6];
 
139
    int num_args;
 
140
    bool AlignToPixels;
 
141
} gs_type1exec_state;
 
142
 
 
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,
 
146
                          i_ctx_p);
 
147
 
 
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 *);
 
170
 
 
171
/* <font> <code|name> <name> <charstring> .type1execchar - */
 
172
static int
 
173
ztype1execchar(i_ctx_t *i_ctx_p)
 
174
{
 
175
    return charstring_execchar(i_ctx_p, (1 << (int)ft_encrypted) |
 
176
                               (1 << (int)ft_disk_based));
 
177
}
 
178
static int
 
179
charstring_execchar_aux(i_ctx_t *i_ctx_p, gs_text_enum_t *penum, gs_font *pfont)
 
180
{
 
181
    os_ptr op = osp;
 
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;
 
188
    int code;
 
189
 
 
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;
 
193
 
 
194
            FontBBox = pfcid0->FontBBox;
 
195
        }
 
196
    }
 
197
 
 
198
    pdata = &pfont1->data;
 
199
    /*
 
200
     * Any reasonable implementation would execute something like
 
201
     *    1 setmiterlimit 0 setlinejoin 0 setlinecap
 
202
     * here, but the Adobe implementations don't.
 
203
     *
 
204
     * If this is a stroked font, set the stroke width.
 
205
     */
 
206
    if (pfont->PaintType)
 
207
        gs_setlinewidth(igs, pfont->StrokeWidth);
 
208
    check_estack(3);            /* for continuations */
 
209
    /*
 
210
     * Execute the definition of the character.
 
211
     */
 
212
    if (r_is_proc(op))
 
213
        return zchar_exec_char_proc(i_ctx_p);
 
214
    /*
 
215
     * The definition must be a Type 1 CharString.
 
216
     * Note that we do not require read access: this is deliberate.
 
217
     */
 
218
    check_type(*op, t_string);
 
219
    if (r_size(op) <= max(pdata->lenIV, 0))
 
220
        return_error(e_invalidfont);
 
221
    /*
 
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.
 
227
     */
 
228
 
 
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);
 
233
        if (code < 0)
 
234
            return code;
 
235
        cxs.present = code;
 
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;
 
240
        cxs.sbw[2] = 0;
 
241
        cxs.sbw[3] = -penum->FontBBox_as_Metrics2.x; /* Sic! */
 
242
        cxs.use_FontBBox_as_Metrics2 = true;
 
243
        cxs.present = metricsNone;
 
244
    }
 
245
    /* Establish a current point. */
 
246
    code = gs_moveto(igs, 0.0, 0.0);
 
247
    if (code < 0)
 
248
        return code;
 
249
    code = type1_exec_init(pcis, penum, igs, pfont1);
 
250
    if (code < 0)
 
251
        return code;
 
252
    gs_type1_set_callback_data(pcis, &cxs);
 
253
    if (FontBBox.q.x > FontBBox.p.x &&
 
254
        FontBBox.q.y > FontBBox.p.y
 
255
        ) {
 
256
        /* The FontBBox appears to be valid. */
 
257
        op_proc_t exec_cont = 0;
 
258
 
 
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);
 
263
        return code;
 
264
    } else {
 
265
        /* The FontBBox is not valid */
 
266
        const ref *opstr = op;
 
267
        ref other_subr;
 
268
        const gs_matrix * pctm = &ctm_only(igs);
 
269
 
 
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.
 
274
            */
 
275
            op_proc_t exec_cont = 0;
 
276
 
 
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);
 
284
            return code;
 
285
        }
 
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.
 
291
         */
 
292
        switch (cxs.present) {
 
293
            case metricsSideBearingAndWidth: { 
 
294
                gs_point pt;
 
295
 
 
296
                pt.x = cxs.sbw[0], pt.y = cxs.sbw[1];
 
297
                gs_type1_set_lsb(pcis, &pt);
 
298
            }
 
299
            /* fall through */
 
300
            case metricsWidthOnly: {
 
301
                gs_point pt;
 
302
 
 
303
                pt.x = cxs.sbw[2], pt.y = cxs.sbw[3];
 
304
                gs_type1_set_width(pcis, &pt);
 
305
            }
 
306
        }
 
307
 
 
308
        /* Continue interpreting. */
 
309
      icont:
 
310
        code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr, 4);
 
311
        op = osp;               /* OtherSubrs might change it */
 
312
        switch (code) {
 
313
            case 0:             /* all done */
 
314
                return nobbox_finish(i_ctx_p, &cxs);
 
315
            default:            /* code < 0, error */
 
316
                return code;
 
317
            case type1_result_callothersubr:    /* unknown OtherSubr */
 
318
                return type1_call_OtherSubr(i_ctx_p, &cxs, nobbox_continue,
 
319
                                            &other_subr);
 
320
            case type1_result_sbw:      /* [h]sbw, just continue */
 
321
                switch (cxs.present) {
 
322
                    case metricsNone:
 
323
                        cxs.sbw[0] = fixed2float(pcis->lsb.x);
 
324
                        cxs.sbw[1] = fixed2float(pcis->lsb.y);
 
325
                    /* fall through */
 
326
                    case metricsWidthOnly:
 
327
                        cxs.sbw[2] = fixed2float(pcis->width.x);
 
328
                        cxs.sbw[3] = fixed2float(pcis->width.y);
 
329
                }
 
330
                opstr = 0;
 
331
                goto icont;
 
332
        }
 
333
    }
 
334
}
 
335
 
 
336
int
 
337
charstring_execchar(i_ctx_t *i_ctx_p, int font_type_mask)
 
338
{
 
339
    gs_text_enum_t *penum = op_show_find(i_ctx_p);
 
340
    gs_font *pfont;
 
341
    os_ptr op = osp;
 
342
    int code = font_param(op - 3, &pfont);
 
343
 
 
344
    if (code < 0)
 
345
        return code;
 
346
    if (penum == 0 ||
 
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.
 
356
         */
 
357
        gs_show_enum *const penum_s = (gs_show_enum *)penum;
 
358
 
 
359
        if (penum_s->cc != NULL) {
 
360
            gx_free_cached_char(pfont->dir, penum_s->cc);
 
361
            penum_s->cc = NULL;
 
362
        }
 
363
    }
 
364
    return code;
 
365
}
 
366
 
 
367
/* -------- bbox case -------- */
 
368
 
 
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. */
 
371
static int
 
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)
 
374
{
 
375
    os_ptr op = osp;
 
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);
 
380
    ref *pcdevproc;
 
381
 
 
382
 
 
383
    /*
 
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.
 
387
     */
 
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. */
 
400
        ref cnref;
 
401
        ref other_subr;
 
402
        int code;
 
403
 
 
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 */
 
409
        switch (code) {
 
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,
 
416
                                            &other_subr);
 
417
            case type1_result_sbw:      /* [h]sbw, done */
 
418
                break;
 
419
        }
 
420
        type1_cis_get_metrics(pcis, pcxs->sbw);
 
421
        return zchar_set_cache(i_ctx_p, pbfont, &cnref,
 
422
                               NULL, pcxs->sbw + 2,
 
423
                               &pcxs->char_bbox,
 
424
                               cont, exec_cont, NULL);
 
425
    } else {
 
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 ?
 
431
                                pcxs->sbw : NULL),
 
432
                               pcxs->sbw + 2,
 
433
                               &pcxs->char_bbox,
 
434
                               cont, exec_cont, 
 
435
                               (pcxs->use_FontBBox_as_Metrics2 ? pcxs->sbw : NULL));
 
436
    }
 
437
}
 
438
 
 
439
/* Continue from an OtherSubr callout while getting metrics. */
 
440
static int
 
441
bbox_getsbw_continue(i_ctx_t *i_ctx_p)
 
442
{
 
443
    os_ptr op = osp;
 
444
    ref other_subr;
 
445
    gs_type1exec_state *pcxs = r_ptr(esp, gs_type1exec_state);
 
446
    gs_type1_state *const pcis = &pcxs->cis;
 
447
    int code;
 
448
 
 
449
    code = type1_continue_dispatch(i_ctx_p, pcxs, NULL, &other_subr, 4);
 
450
    op = osp;                   /* in case z1_push/pop_proc was called */
 
451
    switch (code) {
 
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,
 
457
                                        &other_subr);
 
458
        case type1_result_sbw: {        /* [h]sbw, done */
 
459
            double sbw[4];
 
460
            const gs_font_base *const pbfont =
 
461
                (const gs_font_base *)pcis->pfont;
 
462
            gs_rect bbox;
 
463
            op_proc_t cont = (pbfont->PaintType == 0 ? bbox_finish_fill : bbox_finish_stroke), exec_cont = 0;
 
464
 
 
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);
 
473
            return code;
 
474
        }
 
475
    }
 
476
}
 
477
 
 
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);
 
481
static int
 
482
bbox_finish_fill(i_ctx_t *i_ctx_p)
 
483
{
 
484
    op_proc_t exec_cont = 0;
 
485
    int code;
 
486
 
 
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);
 
490
    return code;
 
491
}
 
492
static int
 
493
bbox_finish_stroke(i_ctx_t *i_ctx_p)
 
494
{
 
495
    op_proc_t exec_cont = 0;
 
496
    int code;
 
497
 
 
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);
 
501
    return code;
 
502
}
 
503
 
 
504
static int
 
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. */
 
507
    os_ptr op = osp;
 
508
    gs_font *pfont;
 
509
    int code;
 
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;
 
513
    double sbxy[2];
 
514
    gs_point sbpt;
 
515
    gs_point *psbpt = 0;
 
516
    os_ptr opc = op;
 
517
    const ref *opstr;
 
518
    ref other_subr;
 
519
 
 
520
    if (!r_has_type(opc, t_string)) {
 
521
        check_op(3);
 
522
        code = num_params(op, 2, sbxy);
 
523
        if (code < 0)
 
524
            return code;
 
525
        sbpt.x = sbxy[0];
 
526
        sbpt.y = sbxy[1];
 
527
        psbpt = &sbpt;
 
528
        opc -= 2;
 
529
        check_type(*opc, t_string);
 
530
    }
 
531
    code = font_param(opc - 3, &pfont);
 
532
    if (code < 0)
 
533
        return code;
 
534
    if (penum == 0 || !font_uses_charstrings(pfont))
 
535
        return_error(e_undefined);
 
536
    {
 
537
        gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
 
538
        int lenIV = pfont1->data.lenIV;
 
539
 
 
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);
 
544
        if (code < 0)
 
545
            return code;
 
546
        if (psbpt)
 
547
            gs_type1_set_lsb(pcis, psbpt);
 
548
    }
 
549
    opstr = opc;
 
550
  icont:
 
551
    code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr,
 
552
                                   (psbpt ? 6 : 4));
 
553
    op = osp;           /* OtherSubrs might have altered it */
 
554
    switch (code) {
 
555
        case 0:         /* all done */
 
556
            /* Call the continuation now. */
 
557
            if (psbpt)
 
558
                pop(2);
 
559
            *exec_cont = cont;
 
560
            return 0;
 
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,
 
564
                                        &other_subr);
 
565
        case type1_result_sbw:  /* [h]sbw, just continue */
 
566
            opstr = 0;
 
567
            goto icont;
 
568
        default:                /* code < 0, error */
 
569
            return code;
 
570
    }
 
571
}
 
572
 
 
573
static int
 
574
bbox_continue(i_ctx_t *i_ctx_p)
 
575
{
 
576
    os_ptr op = osp;
 
577
    int npop = (r_has_type(op, t_string) ? 4 : 6);
 
578
    int code = type1_callout_dispatch(i_ctx_p, bbox_continue, npop);
 
579
 
 
580
    if (code == 0) {
 
581
        op = osp;               /* OtherSubrs might have altered it */
 
582
        npop -= 4;              /* nobbox_fill/stroke handles the rest */
 
583
        pop(npop);
 
584
        op -= npop;
 
585
        op_type1_free(i_ctx_p);
 
586
    }
 
587
    return code;
 
588
}
 
589
 
 
590
/*
 
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.
 
594
 */
 
595
static int
 
596
bbox_draw(i_ctx_t *i_ctx_p, int (*draw)(gs_state *), op_proc_t *exec_cont)
 
597
{
 
598
    os_ptr op = osp;
 
599
    gs_rect bbox;
 
600
    gs_font *pfont;
 
601
    gs_text_enum_t *penum;
 
602
    gs_font_base * pbfont;
 
603
    gs_font_type1 * pfont1;
 
604
    gs_type1exec_state cxs;
 
605
    int code;
 
606
 
 
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)
 
610
        return code;
 
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) {
 
615
        /*
 
616
         * If the matrix is singular, all user coordinates map onto a
 
617
         * straight line.  Don't bother rendering the character at all.
 
618
         */
 
619
        if (code == e_undefinedresult) {
 
620
            pop(4);
 
621
            gs_newpath(igs);
 
622
            return 0;
 
623
        }
 
624
        return code;
 
625
    }
 
626
    if (draw == gs_stroke) {
 
627
        /* Expand the bounding box by the line width. */
 
628
        float width = gs_currentlinewidth(igs) * 1.41422;
 
629
 
 
630
        bbox.p.x -= width, bbox.p.y -= width;
 
631
        bbox.q.x += width, bbox.q.y += width;
 
632
    }
 
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);
 
645
        if (code < 0)
 
646
            return code;
 
647
        cxs.present = code;
 
648
        cxs.use_FontBBox_as_Metrics2 = false;
 
649
    }  else {
 
650
        cxs.sbw[0] = penum->FontBBox_as_Metrics2.x / 2;
 
651
        cxs.sbw[1] = penum->FontBBox_as_Metrics2.y;
 
652
        cxs.sbw[2] = 0;
 
653
        cxs.sbw[3] = -penum->FontBBox_as_Metrics2.x; /* Sic! */
 
654
        cxs.use_FontBBox_as_Metrics2 = true;
 
655
        cxs.present = metricsSideBearingAndWidth;
 
656
    }
 
657
    code = type1_exec_init(&cxs.cis, penum, igs, pfont1);
 
658
    if (code < 0)
 
659
        return code;
 
660
    cxs.char_bbox = pfont1->FontBBox;
 
661
    code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, exec_cont);
 
662
    return code;
 
663
}
 
664
static int
 
665
bbox_fill(i_ctx_t *i_ctx_p)
 
666
{
 
667
    op_proc_t exec_cont = 0;
 
668
    int code;
 
669
 
 
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);
 
674
    return code;
 
675
}
 
676
static int
 
677
bbox_stroke(i_ctx_t *i_ctx_p)
 
678
{
 
679
    op_proc_t exec_cont = 0;
 
680
    int code;
 
681
 
 
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);
 
685
    return code;
 
686
}
 
687
 
 
688
/* -------- Common code -------- */
 
689
 
 
690
/* Handle the results of interpreting the CharString. */
 
691
/* pcref points to a t_string ref. */
 
692
static int
 
693
type1_continue_dispatch(i_ctx_t *i_ctx_p, gs_type1exec_state *pcxs,
 
694
                        const ref * pcref, ref *pos, int num_args)
 
695
{
 
696
    int value;
 
697
    int code;
 
698
    gs_glyph_data_t cs_data;
 
699
    gs_glyph_data_t *pcsd;
 
700
 
 
701
    cs_data.memory = imemory;
 
702
    if (pcref == 0) {
 
703
        pcsd = 0;
 
704
    } else {
 
705
        gs_glyph_data_from_string(&cs_data, pcref->value.const_bytes,
 
706
                                  r_size(pcref), NULL);
 
707
        pcsd = &cs_data;
 
708
    }
 
709
    /*
 
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.
 
715
     */
 
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));
 
719
    osp -= num_args;
 
720
    gs_type1_set_callback_data(&pcxs->cis, pcxs);
 
721
    code = pcxs->cis.pfont->data.interpret(&pcxs->cis, pcsd, &value);
 
722
    switch (code) {
 
723
        case type1_result_callothersubr: {
 
724
            /*
 
725
             * The Type 1 interpreter handles all known OtherSubrs,
 
726
             * so this must be an unknown one.
 
727
             */
 
728
            const font_data *pfdata = pfont_data(gs_currentfont(igs));
 
729
 
 
730
            code = array_get(imemory, &pfdata->u.type1.OtherSubrs, (long)value, pos);
 
731
            if (code >= 0)
 
732
                return type1_result_callothersubr;
 
733
        }
 
734
    }
 
735
    /* Put back the arguments removed above. */
 
736
    memcpy(osp + 1, pcxs->save_args, num_args * sizeof(ref));
 
737
    osp += num_args;
 
738
    return code;
 
739
}
 
740
 
 
741
/*
 
742
 * Push a continuation, the arguments removed for the OtherSubr, and
 
743
 * the OtherSubr procedure.
 
744
 */
 
745
static int
 
746
type1_push_OtherSubr(i_ctx_t *i_ctx_p, const gs_type1exec_state *pcxs,
 
747
                     int (*cont)(i_ctx_t *), const ref *pos)
 
748
{
 
749
    int i, n = pcxs->num_args;
 
750
 
 
751
    push_op_estack(cont);
 
752
    /*
 
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.
 
755
     */
 
756
    for (i = n; --i >= 0; ) {
 
757
        *++esp = pcxs->save_args[i];
 
758
        r_clear_attrs(esp, a_executable);  /* just in case */
 
759
    }
 
760
    ++esp;
 
761
    *esp = *pos;
 
762
    return o_push_estack;
 
763
}
 
764
 
 
765
/*
 
766
 * Do a callout to an OtherSubr implemented in PostScript.
 
767
 * The caller must have done a check_estack(4 + num_args).
 
768
 */
 
769
static int
 
770
type1_call_OtherSubr(i_ctx_t *i_ctx_p, const gs_type1exec_state * pcxs,
 
771
                     int (*cont) (i_ctx_t *),
 
772
                     const ref * pos)
 
773
{
 
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");
 
778
 
 
779
    if (hpcxs == 0)
 
780
        return_error(e_VMerror);
 
781
    *hpcxs = *pcxs;
 
782
    gs_type1_set_callback_data(&hpcxs->cis, hpcxs);
 
783
    push_mark_estack(es_show, op_type1_cleanup);
 
784
    ++esp;
 
785
    make_istruct(esp, 0, hpcxs);
 
786
    return type1_push_OtherSubr(i_ctx_p, pcxs, cont, pos);
 
787
}
 
788
 
 
789
/* Continue from an OtherSubr callout while building the path. */
 
790
static int
 
791
type1_callout_dispatch(i_ctx_t *i_ctx_p, int (*cont)(i_ctx_t *),
 
792
                       int num_args)
 
793
{
 
794
    ref other_subr;
 
795
    gs_type1exec_state *pcxs = r_ptr(esp, gs_type1exec_state);
 
796
    int code;
 
797
 
 
798
  icont:
 
799
    code = type1_continue_dispatch(i_ctx_p, pcxs, NULL, &other_subr,
 
800
                                   num_args);
 
801
    switch (code) {
 
802
        case 0:         /* callout done, cont is on e-stack */
 
803
            return 0;
 
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 */
 
810
            goto icont;
 
811
    }
 
812
}
 
813
 
 
814
/* Clean up after a Type 1 callout. */
 
815
static int
 
816
op_type1_cleanup(i_ctx_t *i_ctx_p)
 
817
{
 
818
    ifree_object(r_ptr(esp + 2, void), "op_type1_cleanup");
 
819
    return 0;
 
820
}
 
821
static void
 
822
op_type1_free(i_ctx_t *i_ctx_p)
 
823
{
 
824
    ifree_object(r_ptr(esp, void), "op_type1_free");
 
825
    /*
 
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.
 
830
     */
 
831
    make_empty_const_array(esp - 1, a_readonly + a_executable);
 
832
    make_empty_const_array(esp, a_readonly + a_executable);
 
833
}
 
834
 
 
835
/* -------- no-bbox case -------- */
 
836
 
 
837
static int
 
838
nobbox_continue(i_ctx_t *i_ctx_p)
 
839
{
 
840
    int code = type1_callout_dispatch(i_ctx_p, nobbox_continue, 4);
 
841
 
 
842
    if (code)
 
843
        return code;
 
844
    {
 
845
        gs_type1exec_state *pcxs = r_ptr(esp, gs_type1exec_state);
 
846
        gs_type1exec_state cxs;
 
847
 
 
848
        cxs = *pcxs;
 
849
        gs_type1_set_callback_data(&cxs.cis, &cxs);
 
850
        op_type1_free(i_ctx_p);
 
851
        return nobbox_finish(i_ctx_p, &cxs);
 
852
    }
 
853
}
 
854
 
 
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 - */
 
858
static int
 
859
nobbox_finish(i_ctx_t *i_ctx_p, gs_type1exec_state * pcxs)
 
860
{
 
861
    os_ptr op = osp;
 
862
    int code;
 
863
    gs_text_enum_t *penum = op_show_find(i_ctx_p);
 
864
    gs_font *pfont;
 
865
 
 
866
    if ((code = gs_pathbbox(igs, &pcxs->char_bbox)) < 0 ||
 
867
        (code = font_param(op - 3, &pfont)) < 0
 
868
        )
 
869
        return code;
 
870
    if (penum == 0 || !font_uses_charstrings(pfont))
 
871
        return_error(e_undefined);
 
872
    {
 
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;
 
876
 
 
877
        if (pcxs->present == metricsNone) {
 
878
            gs_point endpt;
 
879
 
 
880
            if ((code = gs_currentpoint(igs, &endpt)) < 0)
 
881
                return code;
 
882
            pcxs->sbw[2] = endpt.x, pcxs->sbw[3] = endpt.y;
 
883
            pcxs->present = metricsSideBearingAndWidth;
 
884
        }
 
885
        /*
 
886
         * We only need to rebuild the path from scratch if we might
 
887
         * oversample for anti-aliasing.
 
888
         */
 
889
        if ((*dev_proc(igs->device, get_alpha_bits))(igs->device, go_text) > 1
 
890
            ) {
 
891
            gs_newpath(igs);
 
892
            gs_moveto(igs, 0.0, 0.0);
 
893
            code = type1_exec_init(&pcxs->cis, penum, igs, pfont1);
 
894
            if (code < 0)
 
895
                return code;
 
896
            code = type1exec_bbox(i_ctx_p, penum, pcxs, pfont, &exec_cont);
 
897
        } else {
 
898
            cont = (pbfont->PaintType == 0 && penum->orig_font->PaintType == 0
 
899
                        ? nobbox_fill : nobbox_stroke);
 
900
            exec_cont = 0;
 
901
            code = zchar_set_cache(i_ctx_p, pbfont, op - 1, NULL,
 
902
                                   pcxs->sbw + 2,
 
903
                                   &pcxs->char_bbox,
 
904
                                   cont, &exec_cont,
 
905
                                   (pcxs->use_FontBBox_as_Metrics2 ? pcxs->sbw : NULL));
 
906
        }
 
907
        if (code >= 0 && exec_cont != 0)
 
908
            code = (*exec_cont)(i_ctx_p);
 
909
        return code;
 
910
    }
 
911
}
 
912
/* Finish by popping the operands and filling or stroking. */
 
913
static int
 
914
nobbox_draw(i_ctx_t *i_ctx_p, int (*draw)(gs_state *))
 
915
{
 
916
    int code = draw(igs);
 
917
 
 
918
    if (code >= 0)
 
919
        pop(4);
 
920
    return code;
 
921
}
 
922
static int
 
923
nobbox_fill(i_ctx_t *i_ctx_p)
 
924
{
 
925
    /* See above re GS_CHAR_FILL. */
 
926
    return nobbox_draw(i_ctx_p, GS_CHAR_FILL);
 
927
}
 
928
static int
 
929
nobbox_stroke(i_ctx_t *i_ctx_p)
 
930
{
 
931
    /* As a compatibility to Adobe, use the exact "StrokeWidth".
 
932
       Reset fill_adjust for that. */
 
933
    int code;
 
934
    gs_fixed_point fa = i_ctx_p->pgs->fill_adjust;
 
935
 
 
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;
 
939
    return code;
 
940
}
 
941
 
 
942
/* <font> <array> .setweightvector - */
 
943
static int
 
944
zsetweightvector(i_ctx_t *i_ctx_p)
 
945
{
 
946
    os_ptr op = osp;
 
947
    gs_font *pfont;
 
948
    int code = font_param(op - 1, &pfont);
 
949
    gs_font_type1 *pfont1;
 
950
    int size;
 
951
 
 
952
    if (code < 0) {
 
953
        /* The font was not defined yet. Just ignore. See lib/gs_type1.ps . */
 
954
        pop(2);
 
955
        return 0;
 
956
    }
 
957
    if (pfont->FontType != ft_encrypted && pfont->FontType != ft_encrypted2)
 
958
        return_error(e_invalidfont);
 
959
    pfont1 = (gs_font_type1 *)pfont;
 
960
    size = r_size(op);
 
961
    if (size != pfont1->data.WeightVector.count)
 
962
        return_error(e_invalidfont);
 
963
    code = process_float_array(imemory, op, size, pfont1->data.WeightVector.values);
 
964
    if (code < 0)
 
965
        return code;
 
966
    pop(2);
 
967
    return 0;
 
968
}
 
969
 
 
970
/* ------ Initialization procedure ------ */
 
971
 
 
972
const op_def zchar1_op_defs[] =
 
973
{
 
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},
 
984
    op_def_end(0)
 
985
};
 
986
 
 
987
/* ------ Auxiliary procedures for type 1 fonts ------ */
 
988
 
 
989
static int
 
990
z1_glyph_data(gs_font_type1 * pfont, gs_glyph glyph, gs_glyph_data_t *pgd)
 
991
{
 
992
    ref gref;
 
993
 
 
994
    glyph_ref(pfont->memory, glyph, &gref);
 
995
    return zchar_charstring_data((gs_font *)pfont, &gref, pgd);
 
996
}
 
997
 
 
998
static int
 
999
z1_subr_data(gs_font_type1 * pfont, int index, bool global,
 
1000
             gs_glyph_data_t *pgd)
 
1001
{
 
1002
    const font_data *pfdata = pfont_data(pfont);
 
1003
    ref subr;
 
1004
    int code;
 
1005
 
 
1006
    code = array_get(pfont->memory, (global ? &pfdata->u.type1.GlobalSubrs :
 
1007
                      &pfdata->u.type1.Subrs),
 
1008
                     index, &subr);
 
1009
    if (code < 0)
 
1010
        return code;
 
1011
    check_type_only(subr, t_string);
 
1012
    gs_glyph_data_from_string(pgd, subr.value.const_bytes, r_size(&subr),
 
1013
                              NULL);
 
1014
    return 0;
 
1015
}
 
1016
 
 
1017
static int
 
1018
z1_seac_data(gs_font_type1 *pfont, int ccode, gs_glyph *pglyph,
 
1019
             gs_const_string *gstr, gs_glyph_data_t *pgd)
 
1020
{
 
1021
    gs_glyph glyph = gs_c_known_encode((gs_char)ccode,
 
1022
                                       ENCODING_INDEX_STANDARD);
 
1023
    int code;
 
1024
    ref rglyph;
 
1025
 
 
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
 
1030
        )
 
1031
        return code;
 
1032
    if (pglyph)
 
1033
        *pglyph = name_index(pfont->memory, &rglyph);
 
1034
    if (pgd)
 
1035
        code = zchar_charstring_data((gs_font *)pfont, &rglyph, pgd);
 
1036
    return code;
 
1037
}
 
1038
 
 
1039
static int
 
1040
z1_push(void *callback_data, const fixed * pf, int count)
 
1041
{
 
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;
 
1045
    int i;
 
1046
 
 
1047
    check_ostack(count);
 
1048
    for (i = 0; i < count; i++, p--) {
 
1049
        osp++;
 
1050
        make_real(osp, fixed2float(*p));
 
1051
    }
 
1052
    return 0;
 
1053
}
 
1054
 
 
1055
static int
 
1056
z1_pop(void *callback_data, fixed * pf)
 
1057
{
 
1058
    gs_type1exec_state *pcxs = callback_data;
 
1059
    i_ctx_t *i_ctx_p = pcxs->i_ctx_p;
 
1060
    double val;
 
1061
    int code = real_param(osp, &val);
 
1062
 
 
1063
    if (code < 0)
 
1064
        return code;
 
1065
    *pf = float2fixed(val);
 
1066
    osp--;
 
1067
    return 0;
 
1068
}
 
1069
 
 
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
 
1073
};
 
1074
 
 
1075
/* ------ Font procedures for Type 1 fonts ------ */
 
1076
 
 
1077
/*
 
1078
 * Get a Type 1 or Type 2 glyph outline.  This is the glyph_outline
 
1079
 * procedure for the font.
 
1080
 */
 
1081
int
 
1082
zchar1_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
 
1083
                     gx_path *ppath, double sbw[4])
 
1084
{
 
1085
    gs_font_type1 *const pfont1 = (gs_font_type1 *)font;
 
1086
    ref gref;
 
1087
    gs_glyph_data_t gdata;
 
1088
    int code;
 
1089
 
 
1090
    glyph_ref(font->memory, glyph, &gref);
 
1091
    gdata.memory = font->memory;
 
1092
    code = zchar_charstring_data(font, &gref, &gdata);
 
1093
    if (code < 0)
 
1094
        return code;
 
1095
    return zcharstring_outline(pfont1, WMode, &gref, &gdata, pmat, ppath, sbw);
 
1096
}
 
1097
/*
 
1098
 * Get a glyph outline given a CharString.  The glyph_outline procedure
 
1099
 * for CIDFontType 0 fonts uses this.
 
1100
 */
 
1101
int
 
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])
 
1105
{
 
1106
    const gs_glyph_data_t *pgd = pgd_orig;
 
1107
    int code;
 
1108
    gs_type1exec_state cxs;
 
1109
    gs_type1_state *const pcis = &cxs.cis;
 
1110
    const gs_type1_data *pdata;
 
1111
    int value;
 
1112
    gs_imager_state gis;
 
1113
    double wv[4];
 
1114
    gs_point mpt;
 
1115
 
 
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 */
 
1122
#endif
 
1123
    switch (WMode) {
 
1124
    default:
 
1125
        code = zchar_get_metrics2((gs_font_base *)pfont1, pgref, wv);
 
1126
        if (code) {
 
1127
            sbw[0] = wv[2];
 
1128
            sbw[1] = wv[3];
 
1129
            sbw[2] = wv[0];
 
1130
            sbw[3] = wv[1];
 
1131
            break;
 
1132
        }
 
1133
        /* falls through */
 
1134
    case 0:
 
1135
        code = zchar_get_metrics((gs_font_base *)pfont1, pgref, sbw);
 
1136
    }
 
1137
    if (code < 0)
 
1138
        return code;
 
1139
    cxs.present = code;
 
1140
    /* Initialize just enough of the imager state. */
 
1141
    if (pmat)
 
1142
        gs_matrix_fixed_from_matrix(&gis.ctm, pmat);
 
1143
    else {
 
1144
        gs_matrix imat;
 
1145
 
 
1146
        gs_make_identity(&imat);
 
1147
        gs_matrix_fixed_from_matrix(&gis.ctm, &imat);
 
1148
    }
 
1149
    gis.flatness = 0;
 
1150
    code = gs_type1_interp_init(&cxs.cis, &gis, ppath, NULL, NULL, true, 0,
 
1151
                                pfont1);
 
1152
    if (code < 0)
 
1153
        return code;
 
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);
 
1160
        /* falls through */
 
1161
    case metricsWidthOnly:
 
1162
        mpt.x = sbw[2], mpt.y = sbw[3];
 
1163
        gs_type1_set_width(pcis, &mpt);
 
1164
    case metricsNone:
 
1165
        ;
 
1166
    }
 
1167
    /* Continue interpreting. */
 
1168
icont:
 
1169
    code = pfont1->data.interpret(pcis, pgd, &value);
 
1170
    switch (code) {
 
1171
    case 0:             /* all done */
 
1172
        /* falls through */
 
1173
    default:            /* code < 0, error */
 
1174
        return code;
 
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);
 
1180
        pgd = 0;
 
1181
        goto icont;
 
1182
    }
 
1183
}
 
1184
 
 
1185
/*
 
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.
 
1189
 */
 
1190
int
 
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)
 
1193
{
 
1194
    ref gref;
 
1195
    ref *pcdevproc;
 
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;
 
1204
    int code;
 
1205
 
 
1206
    if (!width_members)
 
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);
 
1213
        } else {
 
1214
            /* Ignore CDevProc. Used to compure MissingWidth.*/
 
1215
        }
 
1216
    }
 
1217
    glyph_ref(pbfont->memory, glyph, &gref);
 
1218
    if (width_members == GLYPH_INFO_WIDTH1) {
 
1219
        double wv[4];
 
1220
        code = zchar_get_metrics2(pbfont, &gref, wv);
 
1221
        if (code > 0) {
 
1222
            modified_widths = true;
 
1223
            info->width[1].x = wv[0];
 
1224
            info->width[1].y = wv[1];
 
1225
            info->v.x = wv[2];
 
1226
            info->v.y = wv[3];
 
1227
            done_members = width_members | GLYPH_INFO_VVECTOR1;
 
1228
            width_members = 0;
 
1229
        }
 
1230
    }
 
1231
    if (width_members) {
 
1232
        double sbw[4];
 
1233
        code = zchar_get_metrics(pbfont, &gref, sbw);
 
1234
        if (code > 0) {
 
1235
            modified_widths = true;
 
1236
            info->width[wmode].x = sbw[2];
 
1237
            info->width[wmode].y = sbw[3];
 
1238
            if (code == metricsSideBearingAndWidth) {
 
1239
                info->v.x = sbw[0];
 
1240
                info->v.y = sbw[1];
 
1241
                width_members |= GLYPH_INFO_VVECTOR0;
 
1242
            } else {
 
1243
                info->v.x = 0;
 
1244
                info->v.y = 0;
 
1245
            }
 
1246
            done_members = width_members;
 
1247
            width_members = 0;
 
1248
        }
 
1249
    }
 
1250
 
 
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;
 
1256
        }
 
1257
    }
 
1258
    default_members |= width_members;
 
1259
    if (default_members) {
 
1260
        code = (*proc)(font, glyph, pmat, default_members, info);
 
1261
 
 
1262
        if (code < 0)
 
1263
            return code;
 
1264
    } else
 
1265
        info->members = 0;
 
1266
    info->members |= done_members;
 
1267
    return 0;
 
1268
}
 
1269
 
 
1270
int
 
1271
z1_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
 
1272
              int members, gs_glyph_info_t *info)
 
1273
{
 
1274
    int wmode = font->WMode;
 
1275
 
 
1276
    return z1_glyph_info_generic(font, glyph, pmat, members, info, 
 
1277
                                    &gs_type1_glyph_info, wmode);
 
1278
}
 
1279
 
 
1280
/* Get a Type 1 or Type 9 character metrics and set the cache device. */
 
1281
int
 
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. */
 
1285
    double sbw[4];
 
1286
    gs_glyph_info_t info;
 
1287
    int wmode = gs_rootfont(igs)->WMode;
 
1288
    int code;
 
1289
    gs_matrix id_matrix = { identity_matrix_body };
 
1290
 
 
1291
    code = gs_default_glyph_info((gs_font *)pbfont, glyph, &id_matrix,
 
1292
                ((GLYPH_INFO_WIDTH0 | GLYPH_INFO_VVECTOR0) << wmode) | GLYPH_INFO_BBOX,
 
1293
                &info);
 
1294
    if (code < 0)
 
1295
        return code;
 
1296
    sbw[0] = info.v.x;
 
1297
    sbw[1] = info.v.y;
 
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,
 
1302
                           cont, exec_cont,
 
1303
                           wmode ? sbw : NULL);
 
1304
}