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

« back to all changes in this revision

Viewing changes to psi/zchar.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: zchar.c 9222 2008-11-16 14:47:49Z leonardo $ */
 
15
/* Character operators */
 
16
#include "ghost.h"
 
17
#include "oper.h"
 
18
#include "gsstruct.h"
 
19
#include "gstext.h"
 
20
#include "gxarith.h"
 
21
#include "gxfixed.h"
 
22
#include "gxmatrix.h"           /* for ifont.h */
 
23
#include "gxdevice.h"           /* for gxfont.h */
 
24
#include "gxfont.h"
 
25
#include "gxfont42.h"
 
26
#include "gxfont0.h"
 
27
#include "gzstate.h"
 
28
#include "dstack.h"             /* for stack depth */
 
29
#include "estack.h"
 
30
#include "ialloc.h"
 
31
#include "ichar.h"
 
32
#include "ichar1.h"
 
33
#include "idict.h"
 
34
#include "ifont.h"
 
35
#include "igstate.h"
 
36
#include "ilevel.h"
 
37
#include "iname.h"
 
38
#include "ipacked.h"
 
39
#include "store.h"
 
40
#include "zchar42.h"
 
41
 
 
42
extern bool CPSI_mode;
 
43
 
 
44
/* Forward references */
 
45
static bool map_glyph_to_char(const gs_memory_t *mem, 
 
46
                               const ref *, const ref *, ref *);
 
47
static int finish_show(i_ctx_t *);
 
48
static int op_show_cleanup(i_ctx_t *);
 
49
static int op_show_return_width(i_ctx_t *, uint, double *);
 
50
 
 
51
/* <string> show - */
 
52
static int
 
53
zshow(i_ctx_t *i_ctx_p)
 
54
{
 
55
    os_ptr op = osp;
 
56
    gs_text_enum_t *penum;
 
57
    int code = op_show_setup(i_ctx_p, op);
 
58
 
 
59
    if (code != 0 ||
 
60
        (code = gs_show_begin(igs, op->value.bytes, r_size(op), imemory, &penum)) < 0)
 
61
        return code;
 
62
    *(op_proc_t *)&penum->enum_client_data = zshow;
 
63
    if ((code = op_show_finish_setup(i_ctx_p, penum, 1, finish_show)) < 0) {
 
64
        ifree_object(penum, "op_show_enum_setup");
 
65
        return code;
 
66
    }
 
67
    return op_show_continue_pop(i_ctx_p, 1);
 
68
}
 
69
 
 
70
/* <ax> <ay> <string> ashow - */
 
71
static int
 
72
zashow(i_ctx_t *i_ctx_p)
 
73
{
 
74
    os_ptr op = osp;
 
75
    gs_text_enum_t *penum;
 
76
    double axy[2];
 
77
    int code = num_params(op - 1, 2, axy);
 
78
 
 
79
    if (code < 0 ||
 
80
        (code = op_show_setup(i_ctx_p, op)) != 0 ||
 
81
        (code = gs_ashow_begin(igs, axy[0], axy[1], op->value.bytes, r_size(op), imemory, &penum)) < 0)
 
82
        return code;
 
83
    *(op_proc_t *)&penum->enum_client_data = zashow;
 
84
    if ((code = op_show_finish_setup(i_ctx_p, penum, 3, finish_show)) < 0) {
 
85
        ifree_object(penum, "op_show_enum_setup");
 
86
        return code;
 
87
    }
 
88
    return op_show_continue_pop(i_ctx_p, 3);
 
89
}
 
90
 
 
91
/* <cx> <cy> <char> <string> widthshow - */
 
92
static int
 
93
zwidthshow(i_ctx_t *i_ctx_p)
 
94
{
 
95
    os_ptr op = osp;
 
96
    gs_text_enum_t *penum;
 
97
    double cxy[2];
 
98
    int code;
 
99
 
 
100
    if ((code = op_show_setup(i_ctx_p, op)) != 0 )
 
101
        return code;
 
102
    check_type(op[-1], t_integer);
 
103
    if (gs_currentfont(igs)->FontType == ft_composite) {
 
104
        if ((gs_char) (op[-1].value.intval) != op[-1].value.intval)
 
105
            return_error(e_rangecheck);
 
106
    } else {
 
107
        if (op[-1].value.intval < 0 || op[-1].value.intval > 255)
 
108
            return_error(e_rangecheck); /* per PLRM and CET 13-26 */
 
109
    }
 
110
    if ((code = num_params(op - 2, 2, cxy)) < 0 )
 
111
        return code;
 
112
    if ((code = gs_widthshow_begin(igs, cxy[0], cxy[1],
 
113
                                   (gs_char) op[-1].value.intval,
 
114
                                   op->value.bytes, r_size(op),
 
115
                                   imemory, &penum)) < 0)
 
116
        return code;
 
117
    *(op_proc_t *)&penum->enum_client_data = zwidthshow;
 
118
    if ((code = op_show_finish_setup(i_ctx_p, penum, 4, finish_show)) < 0) {
 
119
        ifree_object(penum, "op_show_enum_setup");
 
120
        return code;
 
121
    }
 
122
    return op_show_continue_pop(i_ctx_p, 4);
 
123
}
 
124
 
 
125
/* <cx> <cy> <char> <ax> <ay> <string> awidthshow - */
 
126
static int
 
127
zawidthshow(i_ctx_t *i_ctx_p)
 
128
{
 
129
    os_ptr op = osp;
 
130
    gs_text_enum_t *penum;
 
131
    double cxy[2], axy[2];
 
132
    int code;
 
133
 
 
134
    if ((code = op_show_setup(i_ctx_p, op)) != 0 )
 
135
        return code;
 
136
    if ((code = num_params(op - 1, 2, axy)) < 0 )
 
137
        return code;
 
138
    check_type(op[-3], t_integer);
 
139
    if (gs_currentfont(igs)->FontType == ft_composite) {
 
140
        if ((gs_char) (op[-3].value.intval) != op[-3].value.intval)
 
141
            return_error(e_rangecheck);
 
142
    } else {
 
143
        if (op[-3].value.intval < 0 || op[-3].value.intval > 255)
 
144
            return_error(e_rangecheck); /* per PLRM and CET 13-02 */
 
145
    }
 
146
    if ((code = num_params(op - 4, 2, cxy)) < 0 )
 
147
        return code;
 
148
    if ((code = gs_awidthshow_begin(igs, cxy[0], cxy[1],
 
149
                                    (gs_char) op[-3].value.intval,
 
150
                                    axy[0], axy[1],
 
151
                                    op->value.bytes, r_size(op),
 
152
                                    imemory, &penum)) < 0)
 
153
        return code;
 
154
    *(op_proc_t *)&penum->enum_client_data = zawidthshow;
 
155
    if ((code = op_show_finish_setup(i_ctx_p, penum, 6, finish_show)) < 0) {
 
156
        ifree_object(penum, "op_show_enum_setup");
 
157
        return code;
 
158
    }
 
159
    return op_show_continue_pop(i_ctx_p, 6);
 
160
}
 
161
 
 
162
/* <proc> <string> kshow - */
 
163
static int
 
164
zkshow(i_ctx_t *i_ctx_p)
 
165
{
 
166
    os_ptr op = osp;
 
167
    gs_text_enum_t *penum;
 
168
    int code;
 
169
 
 
170
    check_read_type(*op, t_string);
 
171
    check_proc(op[-1]);
 
172
    /*
 
173
     * Per PLRM Section xx.x, kshow is illegal if the current font is a
 
174
     * composite font.  The graphics library does not have this limitation,
 
175
     * so we check for it here.
 
176
     */
 
177
    if (gs_currentfont(igs)->FontType == ft_composite)
 
178
        return_error(e_invalidfont);
 
179
    if ((code = op_show_setup(i_ctx_p, op)) != 0 ||
 
180
        (code = gs_kshow_begin(igs, op->value.bytes, r_size(op),
 
181
                               imemory, &penum)) < 0)
 
182
        return code;
 
183
    *(op_proc_t *)&penum->enum_client_data = zkshow;
 
184
    if ((code = op_show_finish_setup(i_ctx_p, penum, 2, finish_show)) < 0) {
 
185
        ifree_object(penum, "op_show_enum_setup");
 
186
        return code;
 
187
    }
 
188
    sslot = op[-1];             /* save kerning proc */
 
189
    return op_show_continue_pop(i_ctx_p, 2);
 
190
}
 
191
 
 
192
/* Common finish procedure for all show operations. */
 
193
/* Doesn't have to do anything. */
 
194
static int
 
195
finish_show(i_ctx_t *i_ctx_p)
 
196
{
 
197
    return 0;
 
198
}
 
199
 
 
200
/* <string> stringwidth <wx> <wy> */
 
201
static int
 
202
zstringwidth(i_ctx_t *i_ctx_p)
 
203
{
 
204
    os_ptr op = osp;
 
205
    gs_text_enum_t *penum;
 
206
    int code = op_show_setup(i_ctx_p, op);
 
207
 
 
208
    if (code != 0 ||
 
209
        (code = gs_stringwidth_begin(igs, op->value.bytes, r_size(op),
 
210
                                     imemory, &penum)) < 0)
 
211
        return code;
 
212
    *(op_proc_t *)&penum->enum_client_data = zstringwidth;
 
213
    if ((code = op_show_finish_setup(i_ctx_p, penum, 1, finish_stringwidth)) < 0) {
 
214
        ifree_object(penum, "op_show_enum_setup");
 
215
        return code;
 
216
    }
 
217
    return op_show_continue_pop(i_ctx_p, 1);
 
218
}
 
219
/* Finishing procedure for stringwidth. */
 
220
/* Pushes the accumulated width. */
 
221
/* This is exported for .glyphwidth (in zcharx.c). */
 
222
int
 
223
finish_stringwidth(i_ctx_t *i_ctx_p)
 
224
{
 
225
    os_ptr op = osp;
 
226
    gs_point width;
 
227
 
 
228
    gs_text_total_width(senum, &width);
 
229
    push(2);
 
230
    make_real(op - 1, width.x);
 
231
    make_real(op, width.y);
 
232
    return 0;
 
233
}
 
234
 
 
235
/* Common code for charpath and .charboxpath. */
 
236
static int
 
237
zchar_path(i_ctx_t *i_ctx_p, op_proc_t proc, 
 
238
           int (*begin)(gs_state *, const byte *, uint,
 
239
                        bool, gs_memory_t *, gs_text_enum_t **))
 
240
{
 
241
    os_ptr op = osp;
 
242
    gs_text_enum_t *penum;
 
243
    int code;
 
244
 
 
245
    check_type(*op, t_boolean);
 
246
    code = op_show_setup(i_ctx_p, op - 1);
 
247
    if (code != 0 ||
 
248
        (code = begin(igs, op[-1].value.bytes, r_size(op - 1),
 
249
                      op->value.boolval, imemory, &penum)) < 0)
 
250
        return code;
 
251
    *(op_proc_t *)&penum->enum_client_data = proc;
 
252
    if ((code = op_show_finish_setup(i_ctx_p, penum, 2, finish_show)) < 0) {
 
253
        ifree_object(penum, "op_show_enum_setup");
 
254
        return code;
 
255
    }
 
256
    return op_show_continue_pop(i_ctx_p, 2);
 
257
}
 
258
/* <string> <outline_bool> charpath - */
 
259
static int
 
260
zcharpath(i_ctx_t *i_ctx_p)
 
261
{
 
262
    return zchar_path(i_ctx_p, zcharpath, gs_charpath_begin);
 
263
}
 
264
/* <string> <box_bool> .charboxpath - */
 
265
static int
 
266
zcharboxpath(i_ctx_t *i_ctx_p)
 
267
{
 
268
    return zchar_path(i_ctx_p, zcharboxpath, gs_charboxpath_begin);
 
269
}
 
270
 
 
271
/* <wx> <wy> <llx> <lly> <urx> <ury> setcachedevice - */
 
272
int
 
273
zsetcachedevice(i_ctx_t *i_ctx_p)
 
274
{
 
275
    os_ptr op = osp;
 
276
    double wbox[6];
 
277
    gs_text_enum_t *penum = op_show_find(i_ctx_p);
 
278
    int code = num_params(op, 6, wbox);
 
279
 
 
280
    if (penum == 0)
 
281
        return_error(e_undefined);
 
282
    if (code < 0)
 
283
        return code;
 
284
    if (zchar_show_width_only(penum))
 
285
        return op_show_return_width(i_ctx_p, 6, &wbox[0]);
 
286
    code = gs_text_setcachedevice(penum, wbox);
 
287
    if (code < 0)
 
288
        return code;
 
289
    pop(6);
 
290
    if (code == 1)
 
291
        clear_pagedevice(istate);
 
292
    return 0;
 
293
}
 
294
 
 
295
/* <w0x> <w0y> <llx> <lly> <urx> <ury> <w1x> <w1y> <vx> <vy> setcachedevice2 - */
 
296
int
 
297
zsetcachedevice2(i_ctx_t *i_ctx_p)
 
298
{
 
299
    os_ptr op = osp;
 
300
    double wbox[10];
 
301
    gs_text_enum_t *penum = op_show_find(i_ctx_p);
 
302
    int code = num_params(op, 10, wbox);
 
303
 
 
304
    if (penum == 0)
 
305
        return_error(e_undefined);
 
306
    if (code < 0)
 
307
        return code;
 
308
    if (zchar_show_width_only(penum))
 
309
        return op_show_return_width(i_ctx_p, 10,
 
310
                                    (gs_rootfont(igs)->WMode ?
 
311
                                     &wbox[6] : &wbox[0]));
 
312
    code = gs_text_setcachedevice2(penum, wbox);
 
313
    if (code < 0)
 
314
        return code;
 
315
    pop(10);
 
316
    if (code == 1)
 
317
        clear_pagedevice(istate);
 
318
    return 0;
 
319
}
 
320
 
 
321
/* <wx> <wy> setcharwidth - */
 
322
static int
 
323
zsetcharwidth(i_ctx_t *i_ctx_p)
 
324
{
 
325
    os_ptr op = osp;
 
326
    double width[2];
 
327
    gs_text_enum_t *penum = op_show_find(i_ctx_p);
 
328
    int code = num_params(op, 2, width);
 
329
 
 
330
    if (penum == 0)
 
331
        return_error(e_undefined);
 
332
    if (code < 0)
 
333
        return code;
 
334
    if (zchar_show_width_only(penum))
 
335
        return op_show_return_width(i_ctx_p, 2, &width[0]);
 
336
    code = gs_text_setcharwidth(penum, width);
 
337
    if (code < 0)
 
338
        return code;
 
339
    pop(2);
 
340
    return 0;
 
341
}
 
342
 
 
343
/* <dict> .fontbbox <llx> <lly> <urx> <ury> -true- */
 
344
/* <dict> .fontbbox -false- */
 
345
static int
 
346
zfontbbox(i_ctx_t *i_ctx_p)
 
347
{
 
348
    os_ptr op = osp;
 
349
    double bbox[4];
 
350
    int code;
 
351
 
 
352
    check_type(*op, t_dictionary);
 
353
    check_dict_read(*op);
 
354
    code = font_bbox_param(imemory, op, bbox);
 
355
    if (code < 0)
 
356
        return code;
 
357
    if (bbox[0] < bbox[2] && bbox[1] < bbox[3]) {
 
358
        push(4);
 
359
        make_reals(op - 4, bbox, 4);
 
360
        make_true(op);
 
361
    } else {                    /* No bbox, or an empty one. */
 
362
        make_false(op);
 
363
    }
 
364
    return 0;
 
365
}
 
366
 
 
367
/* Export in_cachedevice flag for PDF interpreter, which, unlike
 
368
 * PS unterpreter, ignores color operations in the inappropriate context.
 
369
 */
 
370
/* - .incachedevice <bool> */
 
371
static int
 
372
zincachedevice(i_ctx_t *i_ctx_p)
 
373
{
 
374
    os_ptr op = osp;
 
375
 
 
376
    push(1);
 
377
    make_bool(op, !!igs->in_cachedevice);
 
378
    return 0;
 
379
}
 
380
 
 
381
 
 
382
/* ------ Initialization procedure ------ */
 
383
 
 
384
const op_def zchar_a_op_defs[] =
 
385
{
 
386
    {"3ashow", zashow},
 
387
    {"6awidthshow", zawidthshow},
 
388
    {"2charpath", zcharpath},
 
389
    {"2.charboxpath", zcharboxpath},
 
390
    {"2kshow", zkshow},
 
391
    {"6setcachedevice", zsetcachedevice},
 
392
    {":setcachedevice2", zsetcachedevice2},
 
393
    {"2setcharwidth", zsetcharwidth},
 
394
    {"1show", zshow},
 
395
    {"1stringwidth", zstringwidth},
 
396
    {"4widthshow", zwidthshow},
 
397
                /* Extensions */
 
398
    {"1.fontbbox", zfontbbox},
 
399
                /* Internal operators */
 
400
    {"0%finish_show", finish_show},
 
401
    {"0%finish_stringwidth", finish_stringwidth},
 
402
    {"0%op_show_continue", op_show_continue},
 
403
    op_def_end(0)
 
404
};
 
405
 
 
406
const op_def zchar_b_op_defs[] =
 
407
{
 
408
    {"0.incachedevice", zincachedevice},
 
409
    op_def_end(0)
 
410
};
 
411
 
 
412
/* ------ Subroutines ------ */
 
413
 
 
414
/* Most of these are exported for zchar2.c. */
 
415
 
 
416
/* Convert a glyph to a ref. */
 
417
void
 
418
glyph_ref(const gs_memory_t *mem, gs_glyph glyph, ref * gref)
 
419
{
 
420
    if (glyph < gs_min_cid_glyph)
 
421
        name_index_ref(mem, glyph, gref);
 
422
    else
 
423
        make_int(gref, glyph - gs_min_cid_glyph);
 
424
}
 
425
 
 
426
/* Prepare to set up for a text operator. */
 
427
/* Don't change any state yet. */
 
428
int
 
429
op_show_setup(i_ctx_t *i_ctx_p, os_ptr op)
 
430
{
 
431
    check_read_type(*op, t_string);
 
432
    return op_show_enum_setup(i_ctx_p);
 
433
}
 
434
int
 
435
op_show_enum_setup(i_ctx_t *i_ctx_p)
 
436
{
 
437
    check_estack(snumpush + 2);
 
438
    return 0;
 
439
}
 
440
 
 
441
/* Finish setting up a text operator. */
 
442
int
 
443
op_show_finish_setup(i_ctx_t *i_ctx_p, gs_text_enum_t * penum, int npop,
 
444
                     op_proc_t endproc /* end procedure */ )
 
445
{
 
446
    gs_text_enum_t *osenum = op_show_find(i_ctx_p);
 
447
    es_ptr ep = esp + snumpush;
 
448
    gs_glyph glyph;
 
449
    extern bool CPSI_mode;
 
450
 
 
451
    if (CPSI_mode) {
 
452
        /* CET 14-03.PS page 2 emits rangecheck before rendering a character.
 
453
           Early check the text to font compatibility 
 
454
           with decomposing the text into characters.*/
 
455
        int code = gs_text_count_chars(igs, gs_get_text_params(penum), imemory);
 
456
 
 
457
        if (code < 0)
 
458
            return code;
 
459
    }
 
460
    /*
 
461
     * If we are in the procedure of a cshow for a CID font and this is
 
462
     * a show operator, do something special, per the Red Book.
 
463
     */
 
464
    if (osenum &&
 
465
        SHOW_IS_ALL_OF(osenum,
 
466
                       TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_INTERVENE) &&
 
467
        SHOW_IS_ALL_OF(penum, TEXT_FROM_STRING | TEXT_RETURN_WIDTH) &&
 
468
        (glyph = gs_text_current_glyph(osenum)) != gs_no_glyph &&
 
469
        glyph >= gs_min_cid_glyph &&
 
470
 
 
471
        /* According to PLRM, we don't need to raise a rangecheck error,
 
472
           if currentfont is changed in the proc of the operator 'cshow'. */
 
473
        gs_default_same_font (gs_text_current_font(osenum), 
 
474
                              gs_text_current_font(penum), true)
 
475
        ) {
 
476
        gs_text_params_t text;
 
477
 
 
478
        if (!(penum->text.size == 1 &&
 
479
              penum->text.data.bytes[0] ==
 
480
                (gs_text_current_char(osenum) & 0xff))
 
481
            )
 
482
            return_error(e_rangecheck);
 
483
        text = penum->text;
 
484
        text.operation =
 
485
            (text.operation &
 
486
             ~(TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS |
 
487
               TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_CHAR)) |
 
488
            TEXT_FROM_SINGLE_GLYPH;
 
489
        text.data.d_glyph = glyph;
 
490
        text.size = 1;
 
491
        gs_text_restart(penum, &text);
 
492
    }
 
493
    if (osenum && osenum->current_font->FontType == ft_user_defined &&
 
494
        osenum->orig_font->FontType == ft_composite &&
 
495
        ((const gs_font_type0 *)osenum->orig_font)->data.FMapType == fmap_CMap) {
 
496
        /* A special behavior defined in PLRM3 section 5.11 page 389. */
 
497
        penum->outer_CID = osenum->returned.current_glyph;
 
498
    }
 
499
    if (osenum == NULL && !(penum->text.operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH))) {
 
500
        int ft = igs->root_font->FontType;
 
501
 
 
502
        if ((ft >= ft_CID_encrypted && ft <= ft_CID_TrueType) || ft == ft_CID_bitmap)
 
503
            return_error(e_typecheck);
 
504
    }
 
505
    make_mark_estack(ep - (snumpush - 1), es_show, op_show_cleanup);
 
506
    if (endproc == NULL)
 
507
        endproc = finish_show;
 
508
    make_null(&esslot(ep));
 
509
    make_int(&esodepth(ep), ref_stack_count_inline(&o_stack) - npop); /* Save stack depth for */
 
510
    make_int(&esddepth(ep), ref_stack_count_inline(&d_stack));        /* correct interrupt processing */
 
511
    make_int(&esgslevel(ep), igs->level);
 
512
    make_null(&essfont(ep));
 
513
    make_null(&esrfont(ep));
 
514
    make_op_estack(&eseproc(ep), endproc);
 
515
    make_istruct(ep, 0, penum);
 
516
    esp = ep;
 
517
    return 0;
 
518
}
 
519
 
 
520
/* Continuation operator for character rendering. */
 
521
int
 
522
op_show_continue(i_ctx_t *i_ctx_p)
 
523
{
 
524
    int code = gs_text_update_dev_color(igs, senum);
 
525
 
 
526
    if (code >= 0)
 
527
        code = op_show_continue_dispatch(i_ctx_p, 0, gs_text_process(senum));
 
528
    return code;
 
529
}
 
530
int
 
531
op_show_continue_pop(i_ctx_t *i_ctx_p, int npop)
 
532
{
 
533
    return op_show_continue_dispatch(i_ctx_p, npop, gs_text_process(senum));
 
534
}
 
535
/*
 
536
 * Note that op_show_continue_dispatch sets osp = op explicitly iff the
 
537
 * dispatch succeeds.  This is so that the show operators don't pop anything
 
538
 * from the o-stack if they don't succeed.  Note also that if it returns an
 
539
 * error, it has freed the enumerator.
 
540
 */
 
541
int
 
542
op_show_continue_dispatch(i_ctx_t *i_ctx_p, int npop, int code)
 
543
{
 
544
    os_ptr op = osp - npop;
 
545
    gs_text_enum_t *penum = senum;
 
546
 
 
547
    switch (code) {
 
548
        case 0: {               /* all done */
 
549
            os_ptr save_osp = osp;
 
550
 
 
551
            osp = op;
 
552
            code = (*real_opproc(&seproc)) (i_ctx_p);
 
553
            op_show_free(i_ctx_p, code);
 
554
            if (code < 0) {
 
555
                osp = save_osp;
 
556
                return code;
 
557
            }
 
558
            return o_pop_estack;
 
559
        }
 
560
        case TEXT_PROCESS_INTERVENE: {
 
561
            ref *pslot = &sslot; /* only used for kshow */
 
562
 
 
563
            push(2);
 
564
            make_int(op - 1, gs_text_current_char(penum)); /* previous char */
 
565
            make_int(op, gs_text_next_char(penum));
 
566
            push_op_estack(op_show_continue);   /* continue after kerning */
 
567
            *++esp = *pslot;    /* kerning procedure */
 
568
            return o_push_estack;
 
569
        }
 
570
        case TEXT_PROCESS_RENDER: {
 
571
            gs_font *pfont = gs_currentfont(igs);
 
572
            font_data *pfdata = pfont_data(pfont);
 
573
            gs_char chr = gs_text_current_char(penum);
 
574
            gs_glyph glyph = gs_text_current_glyph(penum);
 
575
 
 
576
            push(2);
 
577
            op[-1] = pfdata->dict;      /* push the font */
 
578
            /*
 
579
             * For Type 1 and Type 4 fonts, prefer BuildChar to BuildGlyph
 
580
             * if there is no glyph, or if there is both a character and a
 
581
             * glyph and the glyph is the one that corresponds to the
 
582
             * character in the Encoding, so that PostScript procedures
 
583
             * appearing in the CharStrings dictionary will receive the
 
584
             * character code rather than the character name; for Type 3
 
585
             * fonts, prefer BuildGlyph to BuildChar.  For other font types
 
586
             * (such as CID fonts), only BuildGlyph will be present.
 
587
             */
 
588
            if (pfont->FontType == ft_user_defined) {
 
589
                /* Type 3 font, prefer BuildGlyph. */
 
590
                if (level2_enabled &&
 
591
                    !r_has_type(&pfdata->BuildGlyph, t_null) &&
 
592
                    glyph != gs_no_glyph
 
593
                    ) {
 
594
                    glyph_ref(imemory, glyph, op);
 
595
                    esp[2] = pfdata->BuildGlyph;
 
596
                } else if (r_has_type(&pfdata->BuildChar, t_null))
 
597
                    goto err;
 
598
                else if (chr == gs_no_char) {
 
599
                    /* glyphshow, reverse map the character */
 
600
                    /* through the Encoding */
 
601
                    ref gref;
 
602
                    const ref *pencoding = &pfdata->Encoding;
 
603
 
 
604
                    glyph_ref(imemory, glyph, &gref);
 
605
                    if (!map_glyph_to_char(imemory, &gref, pencoding,
 
606
                                           (ref *) op)
 
607
                        ) {     /* Not found, try .notdef */
 
608
                        name_enter_string(imemory, ".notdef", &gref);
 
609
                        if (!map_glyph_to_char(imemory, &gref,
 
610
                                               pencoding,
 
611
                                               (ref *) op)
 
612
                            )
 
613
                            goto err;
 
614
                    }
 
615
                    esp[2] = pfdata->BuildChar;
 
616
                } else {
 
617
                    make_int(op, chr & 0xff);
 
618
                    esp[2] = pfdata->BuildChar;
 
619
                }
 
620
            } else {
 
621
                /*
 
622
                 * For a Type 1 or Type 4 font, prefer BuildChar or
 
623
                 * BuildGlyph as described above: we know that both
 
624
                 * BuildChar and BuildGlyph are present.  For other font
 
625
                 * types, only BuildGlyph is available.
 
626
                 */
 
627
                ref eref, gref;
 
628
 
 
629
                if (chr != gs_no_char &&
 
630
                    !r_has_type(&pfdata->BuildChar, t_null) &&
 
631
                    (glyph == gs_no_glyph ||
 
632
                     (array_get(imemory, &pfdata->Encoding, (long)(chr & 0xff), &eref) >= 0 &&
 
633
                      (glyph_ref(imemory, glyph, &gref), obj_eq(imemory, &gref, &eref))))
 
634
                    ) {
 
635
                    make_int(op, chr & 0xff);
 
636
                    esp[2] = pfdata->BuildChar;
 
637
                } else {
 
638
                    /* We might not have a glyph: substitute 0. **HACK** */
 
639
                    if (glyph == gs_no_glyph)
 
640
                        make_int(op, 0);
 
641
                    else
 
642
                        glyph_ref(imemory, glyph, op);
 
643
                    esp[2] = pfdata->BuildGlyph;
 
644
                }
 
645
            }
 
646
            /* Save the stack depths in case we bail out. */
 
647
            sodepth.value.intval = ref_stack_count(&o_stack) - 2;
 
648
            sddepth.value.intval = ref_stack_count(&d_stack);
 
649
            push_op_estack(op_show_continue);
 
650
            ++esp;              /* skip BuildChar or BuildGlyph proc */
 
651
            return o_push_estack;
 
652
        }
 
653
        case TEXT_PROCESS_CDEVPROC:
 
654
            {   gs_font *pfont = penum->current_font;
 
655
                ref cnref;
 
656
                op_proc_t cont = op_show_continue, exec_cont = 0;
 
657
                gs_glyph glyph = penum->returned.current_glyph;
 
658
                int code;
 
659
    
 
660
                pop(npop);
 
661
                op = osp;
 
662
                glyph_ref(imemory, glyph, &cnref);
 
663
                if (pfont->FontType == ft_CID_TrueType) {
 
664
                    gs_font_type42 *pfont42 = (gs_font_type42 *)pfont;
 
665
                    uint glyph_index = pfont42->data.get_glyph_index(pfont42, glyph);
 
666
 
 
667
                    code = zchar42_set_cache(i_ctx_p, (gs_font_base *)pfont42, 
 
668
                                    &cnref, glyph_index, cont, &exec_cont);
 
669
                } else if (pfont->FontType == ft_CID_encrypted)
 
670
                    code = z1_set_cache(i_ctx_p, (gs_font_base *)pfont, 
 
671
                                    &cnref, glyph, cont, &exec_cont);
 
672
                else
 
673
                    return_error(e_unregistered); /* Unimplemented. */
 
674
                if (exec_cont != 0)
 
675
                    return_error(e_unregistered); /* Must not happen. */
 
676
                return code;
 
677
            }
 
678
        default:                /* error */
 
679
err:
 
680
            if (code >= 0)
 
681
                code = gs_note_error(e_invalidfont);
 
682
            return op_show_free(i_ctx_p, code);
 
683
    }
 
684
}
 
685
/* Reverse-map a glyph name to a character code for glyphshow. */
 
686
static bool
 
687
map_glyph_to_char(const gs_memory_t *mem, const ref * pgref, const ref * pencoding, ref * pch)
 
688
{
 
689
    uint esize = r_size(pencoding);
 
690
    uint ch;
 
691
    ref eref;
 
692
 
 
693
    for (ch = 0; ch < esize; ch++) {
 
694
        array_get(mem, pencoding, (long)ch, &eref);
 
695
        if (obj_eq(mem, pgref, &eref)) {
 
696
            make_int(pch, ch);
 
697
            return true;
 
698
        }
 
699
    }
 
700
    return false;
 
701
}
 
702
 
 
703
/* Find the index of the e-stack mark for the current show enumerator. */
 
704
/* Return 0 if we can't find the mark. */
 
705
static uint
 
706
op_show_find_index(i_ctx_t *i_ctx_p)
 
707
{
 
708
    ref_stack_enum_t rsenum;
 
709
    uint count = 0;
 
710
 
 
711
    ref_stack_enum_begin(&rsenum, &e_stack);
 
712
    do {
 
713
        es_ptr ep = rsenum.ptr;
 
714
        uint size = rsenum.size;
 
715
 
 
716
        for (ep += size - 1; size != 0; size--, ep--, count++)
 
717
            if (r_is_estack_mark(ep) && estack_mark_index(ep) == es_show)
 
718
                return count;
 
719
    } while (ref_stack_enum_next(&rsenum));
 
720
    return 0;           /* no mark */
 
721
}
 
722
 
 
723
/* Find the current show enumerator on the e-stack. */
 
724
gs_text_enum_t *
 
725
op_show_find(i_ctx_t *i_ctx_p)
 
726
{
 
727
    uint index = op_show_find_index(i_ctx_p);
 
728
 
 
729
    if (index == 0)
 
730
        return 0;               /* no mark */
 
731
    return r_ptr(ref_stack_index(&e_stack, index - (snumpush - 1)),
 
732
                 gs_text_enum_t);
 
733
}
 
734
 
 
735
/*
 
736
 * Return true if we only need the width from the rasterizer
 
737
 * and can short-circuit the full rendering of the character,
 
738
 * false if we need the actual character bits.  This is only safe if
 
739
 * we know the character is well-behaved, i.e., is not defined by an
 
740
 * arbitrary PostScript procedure.
 
741
 */
 
742
bool
 
743
zchar_show_width_only(const gs_text_enum_t * penum)
 
744
{
 
745
    if (!gs_text_is_width_only(penum))
 
746
        return false;
 
747
    switch (penum->orig_font->FontType) {
 
748
    case ft_encrypted:
 
749
    case ft_encrypted2:
 
750
    case ft_CID_encrypted:
 
751
    case ft_CID_TrueType:
 
752
    case ft_CID_bitmap:
 
753
    case ft_TrueType:
 
754
        return true;
 
755
    default:
 
756
        return false;
 
757
    }
 
758
}
 
759
 
 
760
/* Shortcut the BuildChar or BuildGlyph procedure at the point */
 
761
/* of the setcharwidth or the setcachedevice[2] if we are in */
 
762
/* a stringwidth or cshow, or if we are only collecting the scalable */
 
763
/* width for an xfont character. */
 
764
static int
 
765
op_show_return_width(i_ctx_t *i_ctx_p, uint npop, double *pwidth)
 
766
{
 
767
    uint index = op_show_find_index(i_ctx_p);
 
768
    es_ptr ep = (es_ptr) ref_stack_index(&e_stack, index - (snumpush - 1));
 
769
    int code = gs_text_setcharwidth(esenum(ep), pwidth);
 
770
    uint ocount, dsaved, dcount;
 
771
 
 
772
    if (code < 0)
 
773
        return code;
 
774
    /* Restore the operand and dictionary stacks. */
 
775
    ocount = ref_stack_count(&o_stack) - (uint) esodepth(ep).value.intval;
 
776
    if (ocount < npop)
 
777
        return_error(e_stackunderflow);
 
778
    dsaved = (uint) esddepth(ep).value.intval;
 
779
    dcount = ref_stack_count(&d_stack);
 
780
    if (dcount < dsaved)
 
781
        return_error(e_dictstackunderflow);
 
782
    while (dcount > dsaved) {
 
783
        code = zend(i_ctx_p);
 
784
        if (code < 0)
 
785
            return code;
 
786
        dcount--;
 
787
    }
 
788
    ref_stack_pop(&o_stack, ocount);
 
789
    /* We don't want to pop the mark or the continuation */
 
790
    /* procedure (op_show_continue or cshow_continue). */
 
791
    pop_estack(i_ctx_p, index - snumpush);
 
792
    return o_pop_estack;
 
793
}
 
794
 
 
795
/*
 
796
 * Restore state after finishing, or unwinding from an error within, a show
 
797
 * operation.  Note that we assume op == osp, and may reset osp.
 
798
 */
 
799
static int
 
800
op_show_restore(i_ctx_t *i_ctx_p, bool for_error)
 
801
{
 
802
    register es_ptr ep = esp + snumpush;
 
803
    gs_text_enum_t *penum = esenum(ep);
 
804
    int saved_level = esgslevel(ep).value.intval;
 
805
    int code = 0;
 
806
 
 
807
    if (for_error) {
 
808
#if 0 /* Disabled for CPSI compatibility for 13-12-4. 
 
809
         CPSI doesn't remove cshow, kshow proc operands. */
 
810
        uint saved_count = esodepth(ep).value.intval;
 
811
        uint count = ref_stack_count(&o_stack);
 
812
 
 
813
        if (count > saved_count)        /* if <, we're in trouble */
 
814
            ref_stack_pop(&o_stack, count - saved_count);
 
815
#endif
 
816
        if (ep[1].value.opproc == op_show_continue && penum->enum_client_data != NULL) {
 
817
            /* Replace the continuation operaton on estack with the right operator : */
 
818
            op_proc_t proc;
 
819
 
 
820
            *(void **)&proc = penum->enum_client_data;
 
821
            make_op_estack(ep + 1, proc);
 
822
        }
 
823
    }
 
824
    if (SHOW_IS_STRINGWIDTH(penum) && igs->text_rendering_mode != 3) {  
 
825
        /* stringwidth does an extra gsave */
 
826
        --saved_level;
 
827
    }
 
828
    if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
 
829
        gs_free_const_object(penum->memory, penum->text.y_widths, "y_widths");
 
830
        if (penum->text.x_widths != penum->text.y_widths)
 
831
            gs_free_const_object(penum->memory, penum->text.x_widths, "x_widths");
 
832
    }
 
833
    /*
 
834
     * We might have been inside a cshow, in which case currentfont was
 
835
     * reset temporarily, as though we were inside a BuildChar/ BuildGlyph
 
836
     * procedure.  To handle this case, set currentfont back to its original
 
837
     * state.  NOTE: this code previously used fstack[0] in the enumerator
 
838
     * for the root font: we aren't sure that this change is correct.
 
839
     */
 
840
    gs_set_currentfont(igs, penum->orig_font);
 
841
    while (igs->level > saved_level && code >= 0) {
 
842
        if (igs->saved == 0 || igs->saved->saved == 0) {
 
843
            /*
 
844
             * Bad news: we got an error inside a save inside a BuildChar or
 
845
             * BuildGlyph.  Don't attempt to recover.
 
846
             */
 
847
            code = gs_note_error(e_Fatal);
 
848
        } else
 
849
            code = gs_grestore(igs);
 
850
    }
 
851
    gs_text_release(penum, "op_show_restore");
 
852
    return code;
 
853
}
 
854
/* Clean up after an error. */
 
855
static int
 
856
op_show_cleanup(i_ctx_t *i_ctx_p)
 
857
{
 
858
    return op_show_restore(i_ctx_p, true);
 
859
}
 
860
/* Clean up after termination of a show operation. */
 
861
int
 
862
op_show_free(i_ctx_t *i_ctx_p, int code)
 
863
{
 
864
    int rcode;
 
865
 
 
866
    esp -= snumpush;
 
867
    rcode = op_show_restore(i_ctx_p, code < 0);
 
868
    return (rcode < 0 ? rcode : code);
 
869
}
 
870
 
 
871
/* Get a FontBBox parameter from a font dictionary. */
 
872
int
 
873
font_bbox_param(const gs_memory_t *mem, const ref * pfdict, double bbox[4])
 
874
{
 
875
    ref *pbbox;
 
876
 
 
877
    /*
 
878
     * Pre-clear the bbox in case it's invalid.  The Red Books say that
 
879
     * FontBBox is required, but old Adobe interpreters don't require
 
880
     * it, and a few user-written fonts don't supply it, or supply one
 
881
     * of the wrong size (!); also, PageMaker 5.0 (an Adobe product!)
 
882
     * sometimes emits an absurd bbox for Type 1 fonts converted from
 
883
     * TrueType.
 
884
     */
 
885
    bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0;
 
886
    if (dict_find_string(pfdict, "FontBBox", &pbbox) > 0) {
 
887
        if (!r_is_array(pbbox))
 
888
            return_error(e_typecheck);
 
889
        if (r_size(pbbox) == 4) {
 
890
            const ref_packed *pbe = pbbox->value.packed;
 
891
            ref rbe[4];
 
892
            int i;
 
893
            int code;
 
894
            float dx, dy, ratio;
 
895
            const float max_ratio = 12; /* From the bug 687594. */
 
896
 
 
897
            for (i = 0; i < 4; i++) {
 
898
                packed_get(mem, pbe, rbe + i);
 
899
                pbe = packed_next(pbe);
 
900
            }
 
901
            if ((code = num_params(rbe + 3, 4, bbox)) < 0)
 
902
                return code;
 
903
            /* Require "reasonable" values. */
 
904
            dx = bbox[2] - bbox[0];
 
905
            dy = bbox[3] - bbox[1];
 
906
            if (dx <= 0 || dy <= 0 ||
 
907
                (ratio = dy / dx) < 1 / max_ratio || ratio > max_ratio
 
908
                )
 
909
                bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0;
 
910
        }
 
911
    } else if (CPSI_mode) {
 
912
        return_error(e_invalidfont); /* CPSI requires FontBBox */
 
913
    }
 
914
    return 0;
 
915
}