~ubuntu-branches/ubuntu/vivid/ghostscript/vivid-security

« back to all changes in this revision

Viewing changes to base/gdevpdtc.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-08-09 20:01:36 UTC
  • mfrom: (1.1.37)
  • Revision ID: package-import@ubuntu.com-20130809200136-amb6zrr7hnjb5jq9
Tags: 9.08~rc1~dfsg-0ubuntu1
* New upstream release
   - Ghostscript 9.08rc1.
   - We are using the system's liblcms2 and libopenjpeg now.
* debian/patches/020130401-852e545-pxl-xl-driver-produced-drawing-commands-without-setting-color-space.patch:
  Removed patch backported from upstream.
* debian/patches/ojdk-8007925+8007926.patch,
  debian/patches/ojdk-8007927.patch,
  debian/patches/ojdk-8007929.patch,
  debian/patches/ojdk-8009654.patch: Removed patches on build in liblcms2, we
  use the system's liblcms2 now.
* debian/patches/2001_docdir_fix_for_debian.patch: Manually updated to new
  upstream source code.
* debian/patches/2003_support_multiarch.patch: Refreshed with quilt.
* debian/control: Added build dependencies on liblcms2-dev and
  libopenjpeg-dev.
* debian/rules: Check for removed lcms2/ and openjpeg/ subdirectories in
  the repackaging check again, also set build options for shared liblcms2
  and libopenjpeg libraries.
* debian/rules: Makefile.in and configure.ac are in the root directory of
  the source now and do not need to get linked from base/. Also there is no
  gstoraster and gstopxl CUPS filter in the package any more and no
  "install-cups" make target any more.
* debian/control, debian/rules, debian/ghostscript-cups.install,
  debian/ghostscript-cups.ppd-updater: Removed the ghostscript-cups binary
  package. The files are now provided by cups-filters.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2012 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,
8
 
   modified or distributed except as expressly authorized under the terms
9
 
   of the license contained in the file LICENSE in this distribution.
10
 
 
11
 
   Refer to licensing information at http://www.artifex.com or contact
12
 
   Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13
 
   CA  94903, U.S.A., +1(415)492-9861, for further information.
14
 
*/
15
 
 
16
 
 
17
 
/* Composite and CID-based text processing for pdfwrite. */
18
 
#include "memory_.h"
19
 
#include "gx.h"
20
 
#include "gserrors.h"
21
 
#include "gxfcmap.h"
22
 
#include "gxfont.h"
23
 
#include "gxfont0.h"
24
 
#include "gxfont0c.h"
25
 
#include "gzpath.h"
26
 
#include "gxchar.h"
27
 
#include "gdevpsf.h"
28
 
#include "gdevpdfx.h"
29
 
#include "gdevpdtx.h"
30
 
#include "gdevpdtd.h"
31
 
#include "gdevpdtf.h"
32
 
#include "gdevpdts.h"
33
 
#include "gdevpdtt.h"
34
 
 
35
 
/* ---------------- Non-CMap-based composite font ---------------- */
36
 
 
37
 
/*
38
 
 * Process a text string in a composite font with FMapType != 9 (CMap).
39
 
 */
40
 
int
41
 
process_composite_text(gs_text_enum_t *pte, void *vbuf, uint bsize)
42
 
{
43
 
    byte *const buf = vbuf;
44
 
    pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
45
 
    int code = 0;
46
 
    gs_string str;
47
 
    pdf_text_process_state_t text_state;
48
 
    pdf_text_enum_t curr, prev, out;
49
 
    gs_point total_width;
50
 
    const gs_matrix *psmat = 0;
51
 
    gs_font *prev_font = 0;
52
 
    gs_char chr, char_code = 0x0badf00d, space_char = GS_NO_CHAR;
53
 
    int buf_index = 0;
54
 
    bool return_width = (penum->text.operation & TEXT_RETURN_WIDTH);
55
 
 
56
 
    str.data = buf;
57
 
    if (return_width) {
58
 
        code = gx_path_current_point(penum->path, &penum->origin);
59
 
        if (code < 0)
60
 
            return code;
61
 
    }
62
 
    if (pte->text.operation &
63
 
        (TEXT_FROM_ANY - (TEXT_FROM_STRING | TEXT_FROM_BYTES))
64
 
        )
65
 
        return_error(gs_error_rangecheck);
66
 
    if (pte->text.operation & TEXT_INTERVENE) {
67
 
        /* Not implemented. (PostScript doesn't even allow this case.) */
68
 
        return_error(gs_error_rangecheck);
69
 
    }
70
 
    total_width.x = total_width.y = 0;
71
 
    curr = *penum;
72
 
    prev = curr;
73
 
    out = curr;
74
 
    out.current_font = 0;
75
 
    /* Scan runs of characters in the same leaf font. */
76
 
    for ( ; ; ) {
77
 
        int font_code;
78
 
        gs_font *new_font = 0;
79
 
 
80
 
        gs_text_enum_copy_dynamic((gs_text_enum_t *)&out,
81
 
                                  (gs_text_enum_t *)&curr, false);
82
 
        for (;;) {
83
 
            gs_glyph glyph;
84
 
 
85
 
            gs_text_enum_copy_dynamic((gs_text_enum_t *)&prev,
86
 
                                      (gs_text_enum_t *)&curr, false);
87
 
            font_code = pte->orig_font->procs.next_char_glyph
88
 
                ((gs_text_enum_t *)&curr, &chr, &glyph);
89
 
            /*
90
 
             * We check for a font change by comparing the current
91
 
             * font, rather than testing the return code, because
92
 
             * it makes the control structure a little simpler.
93
 
             */
94
 
            switch (font_code) {
95
 
            case 0:             /* no font change */
96
 
            case 1:             /* font change */
97
 
                curr.returned.current_char = chr;
98
 
                char_code = gx_current_char((gs_text_enum_t *)&curr);
99
 
                new_font = curr.fstack.items[curr.fstack.depth].font;
100
 
                if (new_font != prev_font)
101
 
                    break;
102
 
                if (chr != (byte)chr)   /* probably can't happen */
103
 
                    return_error(gs_error_rangecheck);
104
 
                if (buf_index >= bsize)
105
 
                    return_error(gs_error_unregistered); /* Must not happen. */
106
 
                buf[buf_index] = (byte)chr;
107
 
                buf_index++;
108
 
                prev_font = new_font;
109
 
                psmat = &curr.fstack.items[curr.fstack.depth - 1].font->FontMatrix;
110
 
                if ((pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) &&
111
 
                        pte->text.space.s_char == char_code)
112
 
                    space_char = chr;
113
 
                continue;
114
 
            case 2:             /* end of string */
115
 
                break;
116
 
            default:    /* error */
117
 
                return font_code;
118
 
            }
119
 
            break;
120
 
        }
121
 
        str.size = buf_index;
122
 
        if (buf_index) {
123
 
            /* buf_index == 0 is only possible the very first time. */
124
 
            /*
125
 
             * The FontMatrix of leaf descendant fonts is not updated
126
 
             * by scalefont.  Compute the effective FontMatrix now.
127
 
             */
128
 
            gs_matrix fmat;
129
 
 
130
 
            /* set up the base font : */
131
 
            out.fstack.depth = 0;
132
 
            out.fstack.items[out.fstack.depth].font = out.current_font = prev_font;
133
 
            pte->current_font = prev_font;
134
 
 
135
 
            /* Provide the decoded space character : */
136
 
            out.text.space.s_char = space_char;
137
 
 
138
 
            gs_matrix_multiply(&prev_font->FontMatrix, psmat, &fmat);
139
 
            out.index = 0; /* Note : we don't reset out.xy_index here. */
140
 
            code = pdf_process_string_aux(&out, &str, NULL, &fmat, &text_state);
141
 
            if (code < 0)
142
 
                return code;
143
 
            curr.xy_index = out.xy_index; /* pdf_encode_process_string advanced it. */
144
 
            if (out.index < str.size) {
145
 
                gs_glyph glyph;
146
 
 
147
 
                /* Advance *pte exactly for out.index chars,
148
 
                   because above we stored bytes into buf. */
149
 
                while (out.index--)
150
 
                    pte->orig_font->procs.next_char_glyph(pte, &chr, &glyph);
151
 
                font_code = 2; /* force exiting the loop */
152
 
            } else {
153
 
                /* advance *pte past the current substring */
154
 
                gs_text_enum_copy_dynamic(pte, (gs_text_enum_t *)&prev, true);
155
 
            }
156
 
            pte->xy_index = out.xy_index;
157
 
            if (return_width) {
158
 
                /* This is silly, but its a consequence of the way pdf_process_string
159
 
                 * works. When we have TEXT_DO_NONE (stringwidth) we add the width of the
160
 
                 * glyph(s) to the enumerator 'returned.total_width' so we keep track
161
 
                 * of the total width as we go. However when we are returning the width
162
 
                 * but its NOT for a stringwidth, we set the enumerator 'retuerned'
163
 
                 * value to just the width of the glyph(s) processed. So when we are *not*
164
 
                 * handling a stringwidth we need to keep track of the total width
165
 
                 * ourselves. I'd have preferred to alter pdf_process_string, but that
166
 
                 * is used in many other places, and those places rely on this behaviour.
167
 
                 */
168
 
                if (pte->text.operation & TEXT_DO_NONE) {
169
 
                    pte->returned.total_width.x = total_width.x = out.returned.total_width.x;
170
 
                    pte->returned.total_width.y = total_width.y = out.returned.total_width.y;
171
 
                } else {
172
 
                    pte->returned.total_width.x = total_width.x +=
173
 
                        out.returned.total_width.x;
174
 
                    pte->returned.total_width.y = total_width.y +=
175
 
                        out.returned.total_width.y;
176
 
                }
177
 
            }
178
 
            pdf_text_release_cgp(penum);
179
 
        }
180
 
        if (font_code == 2)
181
 
            break;
182
 
        buf[0] = (byte)chr;
183
 
        buf_index = 1;
184
 
        space_char = ((pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) &&
185
 
                      pte->text.space.s_char == char_code ? chr : ~0);
186
 
        psmat = &curr.fstack.items[curr.fstack.depth - 1].font->FontMatrix;
187
 
        prev_font = new_font;
188
 
    }
189
 
    if (!return_width)
190
 
        return 0;
191
 
    return pdf_shift_text_currentpoint(penum, &total_width);
192
 
}
193
 
 
194
 
/* ---------------- CMap-based composite font ---------------- */
195
 
 
196
 
/*
197
 
 * Process a text string in a composite font with FMapType == 9 (CMap).
198
 
 */
199
 
static const char *const standard_cmap_names[] = {
200
 
    /* The following were added in PDF 1.5. */
201
 
 
202
 
    "UniGB-UTF16-H", "UniGB-UTF16-V",
203
 
 
204
 
    "GBKp-EUC-H", "GBKp-EUC-V",
205
 
    "HKscs-B5-H", "HKscs-B5-V",
206
 
    "UniCNS-UTF16-H", "UniCNS-UTF16-V",
207
 
    "UniJIS-UTF16-H", "UniJIS-UTF16-V",
208
 
    "UniKS-UTF16-H", "UniKS-UTF16-V",
209
 
#define END_PDF15_CMAP_NAMES_INDEX 12
210
 
    /* The following were added in PDF 1.4. */
211
 
    "GBKp-EUC-H", "GBKp-EUC-V",
212
 
    "GBK2K-H", "GBK2K-V",
213
 
    "HKscs-B5-H", "HKscs-B5-V",
214
 
#define END_PDF14_CMAP_NAMES_INDEX 18
215
 
    /* The following were added in PDF 1.3. */
216
 
 
217
 
    "GBpc-EUC-V",
218
 
    "GBK-EUC-H", "GBK-EUC-V",
219
 
    "UniGB-UCS2-H", "UniGB-UCS2-V",
220
 
 
221
 
    "ETenms-B5-H", "ETenms-B5-V",
222
 
 
223
 
    "UniCNS-UCS2-H", "UniCNS-UCS2-V",
224
 
 
225
 
    "90msp-RKSJ-H", "90msp-RKSJ-V",
226
 
    "EUC-H", "EUC-V",
227
 
    "UniJIS-UCS2-H", "UniJIS-UCS2-V",
228
 
    "UniJIS-UCS2-HW-H", "UniJIS-UCS2-HW-V",
229
 
 
230
 
    "KSCms-UHC-HW-H", "KSCms-UHC-HW-V",
231
 
    "UniKS-UCS2-H", "UniKS-UCS2-V",
232
 
 
233
 
#define END_PDF13_CMAP_NAMES_INDEX 39
234
 
    /* The following were added in PDF 1.2. */
235
 
 
236
 
    "GB-EUC-H", "GB-EUC-V",
237
 
    "GBpc-EUC-H"
238
 
 
239
 
    "B5pc-H", "B5pc-V",
240
 
    "ETen-B5-H", "ETen-B5-V",
241
 
    "CNS-EUC-H", "CNS-EUC-V",
242
 
 
243
 
    "83pv-RKSJ-H",
244
 
    "90ms-RKSJ-H", "90ms-RKSJ-V",
245
 
    "90pv-RKSJ-H",
246
 
    "Add-RKSJ-H", "Add-RKSJ-V",
247
 
    "Ext-RKSJ-H", "Ext-RKSJ-V",
248
 
    "H", "V",
249
 
 
250
 
    "KSC-EUC-H", "KSC-EUC-V",
251
 
    "KSCms-UHC-H", "KSCms-UHC-V",
252
 
    "KSCpc-EUC-H",
253
 
 
254
 
    "Identity-H", "Identity-V",
255
 
 
256
 
    0
257
 
};
258
 
 
259
 
static int
260
 
attach_cmap_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
261
 
                const gs_cmap_t *pcmap, int font_index_only)
262
 
{
263
 
    const char *const *pcmn =
264
 
        standard_cmap_names +
265
 
        (pdev->CompatibilityLevel < 1.3 ? END_PDF13_CMAP_NAMES_INDEX :
266
 
         pdev->CompatibilityLevel < 1.4 ? END_PDF14_CMAP_NAMES_INDEX :
267
 
         pdev->CompatibilityLevel < 1.5 ? END_PDF15_CMAP_NAMES_INDEX : 0);
268
 
    bool is_identity = false;
269
 
    pdf_resource_t *pcmres = 0; /* CMap */
270
 
    int code;
271
 
 
272
 
    /* Make sure cmap names is properly initialised. Silences Coverity warning */
273
 
    if (!pcmn)
274
 
        return_error(gs_error_unknownerror);
275
 
 
276
 
    /*
277
 
     * If the CMap isn't standard, write it out if necessary.
278
 
     */
279
 
    for (; *pcmn != 0; ++pcmn)
280
 
        if (pcmap->CMapName.size == strlen(*pcmn) &&
281
 
            !memcmp(*pcmn, pcmap->CMapName.data, pcmap->CMapName.size))
282
 
            break;
283
 
    if (*pcmn == 0) {
284
 
        /*
285
 
         * PScript5.dll Version 5.2 creates identity CMaps with
286
 
         * instandard name. Check this specially here
287
 
         * and later replace with a standard name.
288
 
         * This is a temporary fix for SF bug #615994 "CMAP is corrupt".
289
 
         */
290
 
        is_identity = gs_cmap_is_identity(pcmap, font_index_only);
291
 
    }
292
 
    if (*pcmn == 0 && !is_identity) {           /* not standard */
293
 
        pcmres = pdf_find_resource_by_gs_id(pdev, resourceCMap, pcmap->id + font_index_only);
294
 
        if (pcmres == 0) {
295
 
            /* Create and write the CMap object. */
296
 
            code = pdf_cmap_alloc(pdev, pcmap, &pcmres, font_index_only);
297
 
            if (code < 0)
298
 
                return code;
299
 
        }
300
 
    }
301
 
    if (pcmap->from_Unicode) {
302
 
        gs_cmap_ranges_enum_t renum;
303
 
 
304
 
        gs_cmap_ranges_enum_init(pcmap, &renum);
305
 
        if (gs_cmap_enum_next_range(&renum) == 0 && renum.range.size == 2 &&
306
 
            gs_cmap_enum_next_range(&renum) == 1) {
307
 
            /*
308
 
             * Exactly one code space range, of size 2.  Add an identity
309
 
             * ToUnicode CMap.
310
 
             */
311
 
            if (!pdev->Identity_ToUnicode_CMaps[pcmap->WMode]) {
312
 
                /* Create and write an identity ToUnicode CMap now. */
313
 
                gs_cmap_t *pidcmap;
314
 
 
315
 
                code = gs_cmap_create_char_identity(&pidcmap, 2, pcmap->WMode,
316
 
                                                    pdev->memory);
317
 
                if (code < 0)
318
 
                    return code;
319
 
                pidcmap->CMapType = 2;  /* per PDF Reference */
320
 
                pidcmap->ToUnicode = true;
321
 
                code = pdf_cmap_alloc(pdev, pidcmap,
322
 
                                &pdev->Identity_ToUnicode_CMaps[pcmap->WMode], -1);
323
 
                if (code < 0)
324
 
                    return code;
325
 
            }
326
 
            pdfont->res_ToUnicode = pdev->Identity_ToUnicode_CMaps[pcmap->WMode];
327
 
        }
328
 
    }
329
 
    if (pcmres || is_identity) {
330
 
        uint size = pcmap->CMapName.size;
331
 
        byte *chars = gs_alloc_string(pdev->pdf_memory, size,
332
 
                                      "pdf_font_resource_t(CMapName)");
333
 
 
334
 
        if (chars == 0)
335
 
            return_error(gs_error_VMerror);
336
 
        memcpy(chars, pcmap->CMapName.data, size);
337
 
        if (is_identity)
338
 
            strcpy(pdfont->u.type0.Encoding_name,
339
 
                    (pcmap->WMode ? "/Identity-V" : "/Identity-H"));
340
 
        else
341
 
            sprintf(pdfont->u.type0.Encoding_name, "%ld 0 R",
342
 
                    pdf_resource_id(pcmres));
343
 
        pdfont->u.type0.CMapName.data = chars;
344
 
        pdfont->u.type0.CMapName.size = size;
345
 
    } else {
346
 
        if (!*pcmn)
347
 
            /* Should not be possible, if *pcmn is NULL then either
348
 
             * is_identity is true or we create pcmres.
349
 
             */
350
 
            return_error(gs_error_invalidfont);
351
 
 
352
 
        sprintf(pdfont->u.type0.Encoding_name, "/%s", *pcmn);
353
 
        pdfont->u.type0.CMapName.data = (const byte *)*pcmn;
354
 
        pdfont->u.type0.CMapName.size = strlen(*pcmn);
355
 
        pdfont->u.type0.cmap_is_standard = true;
356
 
    }
357
 
    pdfont->u.type0.WMode = pcmap->WMode;
358
 
    return 0;
359
 
}
360
 
 
361
 
/* Record widths and CID => GID mappings. */
362
 
static int
363
 
scan_cmap_text(pdf_text_enum_t *pte, void *vbuf)
364
 
{
365
 
    gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
366
 
    /* gs_font_type0 *const font = (gs_font_type0 *)pte->current_font;*/ /* Type 0, fmap_CMap */
367
 
    gs_font_type0 *const font = (gs_font_type0 *)pte->orig_font; /* Type 0, fmap_CMap */
368
 
    /* Not sure. Changed for CDevProc callout. Was pte->current_font */
369
 
    gs_text_enum_t scan = *(gs_text_enum_t *)pte;
370
 
    int wmode = font->WMode, code, rcode = 0;
371
 
    pdf_font_resource_t *pdsubf0 = NULL;
372
 
    gs_font *subfont0 = NULL, *saved_subfont = NULL;
373
 
    uint index = scan.index, xy_index = scan.xy_index, start_index = index;
374
 
    uint font_index0 = 0x7badf00d;
375
 
    bool done = false;
376
 
    pdf_char_glyph_pairs_t p;
377
 
    gs_glyph *type1_glyphs = (gs_glyph *)vbuf;
378
 
    int num_type1_glyphs = 0;
379
 
 
380
 
    p.num_all_chars = 1;
381
 
    p.num_unused_chars = 1;
382
 
    p.unused_offset = 0;
383
 
    pte->returned.total_width.x = pte->returned.total_width.y = 0;;
384
 
    for (;;) {
385
 
        uint break_index, break_xy_index;
386
 
        uint font_index = 0x7badf00d;
387
 
        gs_const_string str;
388
 
        pdf_text_process_state_t text_state;
389
 
        pdf_font_resource_t *pdsubf;
390
 
        gs_font *subfont = NULL;
391
 
        gs_point wxy;
392
 
        bool font_change = 0;
393
 
 
394
 
        code = gx_path_current_point(pte->path, &pte->origin);
395
 
        if (code < 0)
396
 
            return code;
397
 
        do {
398
 
            gs_char chr;
399
 
            gs_glyph glyph;
400
 
            pdf_font_descriptor_t *pfd;
401
 
            byte *glyph_usage;
402
 
            double *real_widths, *w, *v, *w0;
403
 
            int char_cache_size, width_cache_size;
404
 
            gs_char cid;
405
 
 
406
 
            break_index = scan.index;
407
 
            break_xy_index = scan.xy_index;
408
 
            code = font->procs.next_char_glyph(&scan, &chr, &glyph);
409
 
            if (code == 2) {            /* end of string */
410
 
                done = true;
411
 
                break;
412
 
            }
413
 
            if (code < 0)
414
 
                return code;
415
 
            subfont = scan.fstack.items[scan.fstack.depth].font;
416
 
            font_index = scan.fstack.items[scan.fstack.depth - 1].index;
417
 
            scan.xy_index++;
418
 
            if (glyph == GS_NO_GLYPH)
419
 
                glyph = GS_MIN_CID_GLYPH;
420
 
            cid = glyph - GS_MIN_CID_GLYPH;
421
 
            switch (subfont->FontType) {
422
 
                case ft_encrypted:
423
 
                case ft_encrypted2:{
424
 
                    if (glyph == GS_MIN_CID_GLYPH) {
425
 
                        glyph = subfont->procs.encode_char(subfont, chr, GLYPH_SPACE_NAME);
426
 
                    }
427
 
                    type1_glyphs[num_type1_glyphs] = glyph;
428
 
                    num_type1_glyphs++;
429
 
                    break;
430
 
                }
431
 
                case ft_CID_encrypted:
432
 
                case ft_CID_TrueType: {
433
 
                    p.s[0].glyph = glyph;
434
 
                    p.s[0].chr = cid;
435
 
                    code = pdf_obtain_cidfont_resource(pdev, subfont, &pdsubf, &p);
436
 
                    if (code < 0)
437
 
                        return code;
438
 
                    break;
439
 
                }
440
 
                case ft_user_defined: {
441
 
                    gs_string str1;
442
 
 
443
 
                    str1.data = NULL;
444
 
                    str1.size = 0;
445
 
                    pte->current_font = subfont;
446
 
                    code = pdf_obtain_font_resource(pte, &str1, &pdsubf);
447
 
                    if (code < 0)
448
 
                        return code;
449
 
                    cid = pdf_find_glyph(pdsubf, glyph);
450
 
                    if (cid == GS_NO_CHAR) {
451
 
                        code = pdf_make_font3_resource(pdev, subfont, &pdsubf);
452
 
                        if (code < 0)
453
 
                            return code;
454
 
                        code = pdf_attach_font_resource(pdev, subfont, pdsubf);
455
 
                        if (code < 0)
456
 
                            return code;
457
 
                        cid = 0;
458
 
                    }
459
 
                    break;
460
 
                }
461
 
                default:
462
 
                    /* An unsupported case, fall back to default implementation. */
463
 
                    return_error(gs_error_rangecheck);
464
 
            }
465
 
            code = pdf_attached_font_resource(pdev, (gs_font *)subfont, &pdsubf,
466
 
                                       &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
467
 
            if (code < 0)
468
 
                return code;
469
 
            if (break_index > start_index && pdev->charproc_just_accumulated)
470
 
                break;
471
 
            if (subfont->FontType == ft_user_defined &&
472
 
                (break_index > start_index || !pdev->charproc_just_accumulated) &&
473
 
                !(pdsubf->u.simple.s.type3.cached[cid >> 3] & (0x80 >> (cid & 7)))) {
474
 
                pte->current_font = subfont;
475
 
                return gs_error_undefined;
476
 
            }
477
 
            if (subfont->FontType == ft_encrypted || subfont->FontType == ft_encrypted2) {
478
 
                font_change = (subfont != subfont0 && subfont0 != NULL);
479
 
                if (font_change) {
480
 
                    saved_subfont = subfont;
481
 
                    subfont = subfont0;
482
 
                    num_type1_glyphs--;
483
 
                }
484
 
            } else
485
 
                font_change = (pdsubf != pdsubf0 && pdsubf0 != NULL);
486
 
            if (!font_change) {
487
 
                pdsubf0 = pdsubf;
488
 
                font_index0 = font_index;
489
 
                subfont0 = subfont;
490
 
            }
491
 
            if (subfont->FontType != ft_encrypted && subfont->FontType != ft_encrypted2) {
492
 
                pfd = pdsubf->FontDescriptor;
493
 
                code = pdf_resize_resource_arrays(pdev, pdsubf, cid + 1);
494
 
                if (code < 0)
495
 
                    return code;
496
 
                if (subfont->FontType == ft_CID_encrypted || subfont->FontType == ft_CID_TrueType) {
497
 
                    if (cid >=width_cache_size) {
498
 
                        /* fixme: we add the CID=0 glyph as CID=cid glyph to the output font.
499
 
                           Really it must not add and leave the CID undefined. */
500
 
                        cid = 0; /* notdef. */
501
 
                    }
502
 
                }
503
 
                if (cid >= char_cache_size || cid >= width_cache_size)
504
 
                    return_error(gs_error_unregistered); /* Must not happen */
505
 
                if (pdsubf->FontType == ft_user_defined  || pdsubf->FontType == ft_encrypted ||
506
 
                                pdsubf->FontType == ft_encrypted2) {
507
 
                } else {
508
 
                    pdf_font_resource_t *pdfont;
509
 
                    bool notdef_subst = false;
510
 
 
511
 
                    code = pdf_obtain_cidfont_widths_arrays(pdev, pdsubf, wmode, &w, &w0, &v);
512
 
                    if (code < 0)
513
 
                        return code;
514
 
                    code = pdf_obtain_parent_type0_font_resource(pdev, pdsubf, font_index,
515
 
                        &font->data.CMap->CMapName, &pdfont);
516
 
                    if (code < 0)
517
 
                        return code;
518
 
                    if (pdf_is_CID_font(subfont)) {
519
 
                        if (subfont->procs.decode_glyph((gs_font *)subfont, glyph, -1) != GS_NO_CHAR) {
520
 
                            /* Since PScript5.dll creates GlyphNames2Unicode with character codes
521
 
                               instead CIDs, and with the WinCharSetFFFF-H2 CMap
522
 
                               character codes appears different than CIDs (Bug 687954),
523
 
                               pass the character code intead the CID. */
524
 
                            code = pdf_add_ToUnicode(pdev, subfont, pdfont,
525
 
                                chr + GS_MIN_CID_GLYPH, chr, NULL);
526
 
                        } else {
527
 
                            /* If we interpret a PDF document, ToUnicode
528
 
                               CMap may be attached to the Type 0 font. */
529
 
                            code = pdf_add_ToUnicode(pdev, pte->orig_font, pdfont,
530
 
                                chr + GS_MIN_CID_GLYPH, chr, NULL);
531
 
                        }
532
 
                    } else
533
 
                        code = pdf_add_ToUnicode(pdev, subfont, pdfont, glyph, cid, NULL);
534
 
                    if (code < 0)
535
 
                        return code;
536
 
                    /*  We can't check pdsubf->used[cid >> 3] here,
537
 
                        because it mixed data for different values of WMode.
538
 
                        Perhaps pdf_font_used_glyph returns fast with reused glyphs.
539
 
                     */
540
 
                    code = pdf_font_used_glyph(pfd, glyph, (gs_font_base *)subfont);
541
 
                    if (code == gs_error_rangecheck) {
542
 
                        if (!(pdsubf->used[cid >> 3] & (0x80 >> (cid & 7)))) {
543
 
                            char buf[gs_font_name_max + 1];
544
 
                            int l = min(sizeof(buf) - 1, subfont->font_name.size);
545
 
 
546
 
                            memcpy(buf, subfont->font_name.chars, l);
547
 
                            buf[l] = 0;
548
 
                            emprintf3(pdev->memory,
549
 
                                      "Missing glyph CID=%d, glyph=%04x in the font %s . The output PDF may fail with some viewers.\n",
550
 
                                      (int)cid,
551
 
                                      (unsigned int)(glyph - GS_MIN_CID_GLYPH),
552
 
                                      buf);
553
 
                            pdsubf->used[cid >> 3] |= 0x80 >> (cid & 7);
554
 
                        }
555
 
                        cid = 0, code = 1;  /* undefined glyph. */
556
 
                        notdef_subst = true;
557
 
                        /* If this is the first use of CID=0, get its width */
558
 
                        if (pdsubf->Widths[cid] == 0) {
559
 
                            pdf_glyph_widths_t widths;
560
 
 
561
 
                            code = pdf_glyph_widths(pdsubf, wmode, glyph, (gs_font *)subfont, &widths,
562
 
                                pte->cdevproc_callout ? pte->cdevproc_result : NULL);
563
 
                        }
564
 
                    } else if (code < 0)
565
 
                        return code;
566
 
                    if ((code == 0 /* just copied */ || pdsubf->Widths[cid] == 0) && !notdef_subst) {
567
 
                        pdf_glyph_widths_t widths;
568
 
 
569
 
                    code = pdf_glyph_widths(pdsubf, wmode, glyph, (gs_font *)subfont, &widths,
570
 
                        pte->cdevproc_callout ? pte->cdevproc_result : NULL);
571
 
                    if (code < 0)
572
 
                        return code;
573
 
                    if (code == TEXT_PROCESS_CDEVPROC) {
574
 
                        pte->returned.current_glyph = glyph;
575
 
                        pte->current_font = subfont;
576
 
                        rcode = TEXT_PROCESS_CDEVPROC;
577
 
                        break;
578
 
                    }
579
 
                    if (code >= 0) {
580
 
                        if (cid > pdsubf->count)
581
 
                            return_error(gs_error_unregistered); /* Must not happen. */
582
 
                        w[cid] = widths.Width.w;
583
 
                        if (v != NULL) {
584
 
                            v[cid * 2 + 0] = widths.Width.v.x;
585
 
                            v[cid * 2 + 1] = widths.Width.v.y;
586
 
                        }
587
 
                        real_widths[cid] = widths.real_width.w;
588
 
                    }
589
 
                    if (wmode) {
590
 
                        /* Since AR5 use W or DW to compute the x-coordinate of
591
 
                           v-vector, comupte and store the glyph width for WMode 0. */
592
 
                        /* fixme : skip computing real_width here. */
593
 
                        code = pdf_glyph_widths(pdsubf, 0, glyph, (gs_font *)subfont, &widths,
594
 
                            pte->cdevproc_callout ? pte->cdevproc_result : NULL);
595
 
                        if (code < 0)
596
 
                            return code;
597
 
                        w0[cid] = widths.Width.w;
598
 
                    }
599
 
                    if (pdsubf->u.cidfont.CIDToGIDMap != 0) {
600
 
                        gs_font_cid2 *subfont2 = (gs_font_cid2 *)subfont;
601
 
 
602
 
                        pdsubf->u.cidfont.CIDToGIDMap[cid] =
603
 
                        subfont2->cidata.CIDMap_proc(subfont2, glyph);
604
 
                    }
605
 
                }
606
 
                if (wmode)
607
 
                    pdsubf->u.cidfont.used2[cid >> 3] |= 0x80 >> (cid & 7);
608
 
                }
609
 
                pdsubf->used[cid >> 3] |= 0x80 >> (cid & 7);
610
 
            }
611
 
            if (pte->cdevproc_callout) {
612
 
                /* Only handle a single character because its width is stored
613
 
                  into pte->cdevproc_result, and process_text_modify_width neds it.
614
 
                  fixme: next time take from w, v, real_widths. */
615
 
                break_index = scan.index;
616
 
                break_xy_index = scan.xy_index;
617
 
                break;
618
 
            }
619
 
        } while (!font_change);
620
 
        if (break_index > index) {
621
 
            pdf_font_resource_t *pdfont;
622
 
            gs_matrix m3;
623
 
            int xy_index_step = (!(pte->text.operation & TEXT_REPLACE_WIDTHS) ? 0 :
624
 
                                 pte->text.x_widths == pte->text.y_widths ? 2 : 1);
625
 
            gs_text_params_t save_text;
626
 
 
627
 
            if (!subfont && num_type1_glyphs != 0)
628
 
                subfont = subfont0;
629
 
            if (subfont && (subfont->FontType == ft_encrypted || subfont->FontType == ft_encrypted2)) {
630
 
                int save_op = pte->text.operation;
631
 
                gs_font *save_font = pte->current_font;
632
 
                const gs_glyph *save_data = pte->text.data.glyphs;
633
 
 
634
 
                pte->current_font = subfont;
635
 
                pte->text.operation |= TEXT_FROM_GLYPHS;
636
 
                pte->text.data.glyphs = type1_glyphs;
637
 
                str.data = ((const byte *)vbuf) + ((pte->text.size - pte->index) * sizeof(gs_glyph));
638
 
                str.size = num_type1_glyphs;
639
 
                code = pdf_obtain_font_resource_unencoded(pte, (const gs_string *)&str, &pdsubf0,
640
 
                    type1_glyphs);
641
 
                if (code < 0) {
642
 
                    /* Replace the modified values, fall back to default implementation
643
 
                     * (type 3 bitmap image font)
644
 
                     */
645
 
                    pte->current_font = save_font;
646
 
                    pte->text.operation |= save_op;
647
 
                    pte->text.data.glyphs = save_data;
648
 
                    return(code);
649
 
                }
650
 
                memcpy((void *)scan.text.data.bytes, (void *)str.data, str.size);
651
 
                str.data = scan.text.data.bytes;
652
 
                pdsubf = pdsubf0;
653
 
                pte->text.operation = save_op;
654
 
            }
655
 
            pte->current_font = subfont0;
656
 
            if (!subfont0 || !pdsubf0)
657
 
                /* This should be impossible */
658
 
                return_error(gs_error_invalidfont);
659
 
 
660
 
            code = gs_matrix_multiply(&subfont0->FontMatrix, &font->FontMatrix, &m3);
661
 
            /* We thought that it should be gs_matrix_multiply(&font->FontMatrix, &subfont0->FontMatrix, &m3); */
662
 
            if (code < 0)
663
 
                return code;
664
 
            if (pdsubf0->FontType == ft_user_defined  || pdsubf->FontType == ft_encrypted ||
665
 
                pdsubf->FontType == ft_encrypted2)
666
 
                    pdfont = pdsubf0;
667
 
            else {
668
 
                code = pdf_obtain_parent_type0_font_resource(pdev, pdsubf0, font_index0,
669
 
                            &font->data.CMap->CMapName, &pdfont);
670
 
                if (code < 0)
671
 
                    return code;
672
 
                if (!pdfont->u.type0.Encoding_name[0]) {
673
 
                    /*
674
 
                    * If pdfont->u.type0.Encoding_name is set,
675
 
                    * a CMap resource is already attached.
676
 
                    * See attach_cmap_resource.
677
 
                    */
678
 
                    code = attach_cmap_resource(pdev, pdfont, font->data.CMap, font_index0);
679
 
                    if (code < 0)
680
 
                        return code;
681
 
                }
682
 
            }
683
 
            pdf_set_text_wmode(pdev, font->WMode);
684
 
            code = pdf_update_text_state(&text_state, (pdf_text_enum_t *)pte, pdfont, &m3);
685
 
            if (code < 0)
686
 
                return code;
687
 
            /* process_text_modify_width breaks text parameters.
688
 
               We would like to improve it someday.
689
 
               Now save them locally and restore after the call. */
690
 
            save_text = pte->text;
691
 
            if (subfont && (subfont->FontType != ft_encrypted &&
692
 
                subfont->FontType != ft_encrypted2)) {
693
 
                /* If we are a type 1 descendant, we already sorted this out above */
694
 
                str.data = scan.text.data.bytes + index;
695
 
                str.size = break_index - index;
696
 
            }
697
 
            if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
698
 
                if (pte->text.x_widths != NULL)
699
 
                    pte->text.x_widths += xy_index * xy_index_step;
700
 
                if (pte->text.y_widths != NULL)
701
 
                    pte->text.y_widths += xy_index * xy_index_step;
702
 
            }
703
 
            pte->xy_index = 0;
704
 
            if (subfont && (subfont->FontType == ft_encrypted ||
705
 
                subfont->FontType == ft_encrypted2)) {
706
 
                gs_font *f = pte->orig_font;
707
 
 
708
 
                adjust_first_last_char(pdfont, (byte *)str.data, str.size);
709
 
 
710
 
                /* Make sure we use the descendant font, not the original type 0 ! */
711
 
                pte->orig_font = subfont;
712
 
                code = process_text_modify_width((pdf_text_enum_t *)pte,
713
 
                    (gs_font *)subfont, &text_state, &str, &wxy, type1_glyphs, false);
714
 
                if (code < 0)
715
 
                    return(code);
716
 
                if(font_change) {
717
 
                    type1_glyphs[0] = type1_glyphs[num_type1_glyphs];
718
 
                    num_type1_glyphs = 1;
719
 
                    subfont = saved_subfont;
720
 
                } else {
721
 
                    num_type1_glyphs = 0;
722
 
                }
723
 
                pte->orig_font = f;
724
 
            } else {
725
 
                code = process_text_modify_width((pdf_text_enum_t *)pte, (gs_font *)font,
726
 
                    &text_state, &str, &wxy, NULL, true);
727
 
            }
728
 
            if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
729
 
                if (pte->text.x_widths != NULL)
730
 
                    pte->text.x_widths -= xy_index * xy_index_step;
731
 
                if (pte->text.y_widths != NULL)
732
 
                    pte->text.y_widths -= xy_index * xy_index_step;
733
 
            }
734
 
            pte->text = save_text;
735
 
            pte->cdevproc_callout = false;
736
 
            if (code < 0) {
737
 
                pte->index = index;
738
 
                pte->xy_index = xy_index;
739
 
                return code;
740
 
            }
741
 
            pte->index = break_index;
742
 
            pte->xy_index = break_xy_index;
743
 
            code = pdf_shift_text_currentpoint(pte, &wxy);
744
 
            if (code < 0)
745
 
                return code;
746
 
        }
747
 
        pdf_text_release_cgp(pte);
748
 
        index = break_index;
749
 
        xy_index = break_xy_index;
750
 
        if (done || rcode != 0)
751
 
            break;
752
 
        pdsubf0 = pdsubf;
753
 
        font_index0 = font_index;
754
 
        subfont0 = subfont;
755
 
    }
756
 
    pte->index = index;
757
 
    pte->xy_index = xy_index;
758
 
    return rcode;
759
 
}
760
 
 
761
 
int
762
 
process_cmap_text(gs_text_enum_t *penum, void *vbuf, uint bsize)
763
 
{
764
 
    int code;
765
 
    pdf_text_enum_t *pte = (pdf_text_enum_t *)penum;
766
 
 
767
 
    if (pte->text.operation &
768
 
        (TEXT_FROM_ANY - (TEXT_FROM_STRING | TEXT_FROM_BYTES))
769
 
        )
770
 
        return_error(gs_error_rangecheck);
771
 
    if (pte->text.operation & TEXT_INTERVENE) {
772
 
        /* Not implemented.  (PostScript doesn't allow TEXT_INTERVENE.) */
773
 
        return_error(gs_error_rangecheck);
774
 
    }
775
 
    code = scan_cmap_text(pte, vbuf);
776
 
    if (code == TEXT_PROCESS_CDEVPROC)
777
 
        pte->cdevproc_callout = true;
778
 
    else
779
 
        pte->cdevproc_callout = false;
780
 
    return code;
781
 
}
782
 
 
783
 
/* ---------------- CIDFont ---------------- */
784
 
 
785
 
/*
786
 
 * Process a text string in a CIDFont.  (Only glyphshow is supported.)
787
 
 */
788
 
int
789
 
process_cid_text(gs_text_enum_t *pte, void *vbuf, uint bsize)
790
 
{
791
 
    pdf_text_enum_t *penum = (pdf_text_enum_t *)pte;
792
 
    uint operation = pte->text.operation;
793
 
    gs_text_enum_t save;
794
 
    gs_font *scaled_font = pte->current_font; /* CIDFont */
795
 
    gs_font *font;              /* unscaled font (CIDFont) */
796
 
    const gs_glyph *glyphs;
797
 
    gs_matrix scale_matrix;
798
 
    pdf_font_resource_t *pdsubf; /* CIDFont */
799
 
    gs_font_type0 *font0 = NULL;
800
 
    uint size;
801
 
    int code;
802
 
 
803
 
    if (operation & TEXT_FROM_GLYPHS) {
804
 
        glyphs = pte->text.data.glyphs;
805
 
        size = pte->text.size - pte->index;
806
 
    } else if (operation & TEXT_FROM_SINGLE_GLYPH) {
807
 
        glyphs = &pte->text.data.d_glyph;
808
 
        size = 1;
809
 
    } else if (operation & TEXT_FROM_STRING) {
810
 
        glyphs = &pte->outer_CID;
811
 
        size = 1;
812
 
    } else
813
 
        return_error(gs_error_rangecheck);
814
 
 
815
 
    /*
816
 
     * PDF doesn't support glyphshow directly: we need to create a Type 0
817
 
     * font with an Identity CMap.  Make sure all the glyph numbers fit
818
 
     * into 16 bits.  (Eventually we should support wider glyphs too,
819
 
     * but this would require a different CMap.)
820
 
     */
821
 
    if (bsize < size * 2)
822
 
        return_error(gs_error_unregistered); /* Must not happen. */
823
 
    {
824
 
        int i;
825
 
        byte *pchars = vbuf;
826
 
 
827
 
        for (i = 0; i < size; ++i) {
828
 
            ulong gnum = glyphs[i] - GS_MIN_CID_GLYPH;
829
 
 
830
 
            if (gnum & ~0xffffL)
831
 
                return_error(gs_error_rangecheck);
832
 
            *pchars++ = (byte)(gnum >> 8);
833
 
            *pchars++ = (byte)gnum;
834
 
        }
835
 
    }
836
 
 
837
 
    /* Find the original (unscaled) version of this font. */
838
 
 
839
 
    for (font = scaled_font; font->base != font; )
840
 
        font = font->base;
841
 
    /* Compute the scaling matrix. */
842
 
    gs_matrix_invert(&font->FontMatrix, &scale_matrix);
843
 
    gs_matrix_multiply(&scale_matrix, &scaled_font->FontMatrix, &scale_matrix);
844
 
 
845
 
    /* Find or create the CIDFont resource. */
846
 
 
847
 
    code = pdf_obtain_font_resource(penum, NULL, &pdsubf);
848
 
    if (code < 0)
849
 
        return code;
850
 
 
851
 
    /* Create the CMap and Type 0 font if they don't exist already. */
852
 
 
853
 
    if (pdsubf->u.cidfont.glyphshow_font_id != 0)
854
 
        font0 = (gs_font_type0 *)gs_find_font_by_id(font->dir,
855
 
                    pdsubf->u.cidfont.glyphshow_font_id, &scaled_font->FontMatrix);
856
 
    if (font0 == NULL) {
857
 
        code = gs_font_type0_from_cidfont(&font0, font, font->WMode,
858
 
                                          &scale_matrix, font->memory);
859
 
        if (code < 0)
860
 
            return code;
861
 
        pdsubf->u.cidfont.glyphshow_font_id = font0->id;
862
 
    }
863
 
 
864
 
    /* Now handle the glyphshow as a show in the Type 0 font. */
865
 
 
866
 
    save = *pte;
867
 
    pte->current_font = pte->orig_font = (gs_font *)font0;
868
 
    /* Patch the operation temporarily for init_fstack. */
869
 
    pte->text.operation = (operation & ~TEXT_FROM_ANY) | TEXT_FROM_BYTES;
870
 
    /* Patch the data for process_cmap_text. */
871
 
    pte->text.data.bytes = vbuf;
872
 
    pte->text.size = size * 2;
873
 
    pte->index = 0;
874
 
    gs_type0_init_fstack(pte, pte->current_font);
875
 
    code = process_cmap_text(pte, vbuf, bsize);
876
 
    pte->current_font = scaled_font;
877
 
    pte->orig_font = save.orig_font;
878
 
    pte->text = save.text;
879
 
    pte->index = save.index + pte->index / 2;
880
 
    pte->fstack = save.fstack;
881
 
    return code;
882
 
}