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

« back to all changes in this revision

Viewing changes to base/gdevpdti.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
 
/* Bitmap font implementation for pdfwrite */
18
 
#include "memory_.h"
19
 
#include "gx.h"
20
 
#include "gxpath.h"
21
 
#include "gserrors.h"
22
 
#include "gsutil.h"
23
 
#include "gdevpdfx.h"
24
 
#include "gdevpdfg.h"
25
 
#include "gdevpdtf.h"
26
 
#include "gdevpdti.h"
27
 
#include "gdevpdts.h"
28
 
#include "gdevpdtw.h"
29
 
#include "gdevpdtt.h"
30
 
#include "gdevpdfo.h"
31
 
#include "gxchar.h"        /* For gs_show_enum */
32
 
 
33
 
/* ---------------- Private ---------------- */
34
 
 
35
 
/* Define the structure for a CharProc pseudo-resource. */
36
 
/*typedef struct pdf_char_proc_s pdf_char_proc_t;*/  /* gdevpdfx.h */
37
 
struct pdf_char_proc_s {
38
 
    pdf_resource_common(pdf_char_proc_t);
39
 
    pdf_char_proc_ownership_t *owner_fonts; /* fonts using this charproc. */
40
 
    int y_offset;                /* of character (0,0) */
41
 
    int x_offset;                /* of character (0,0) */
42
 
    gs_point real_width;        /* Not used with synthesised bitmap fonts. */
43
 
    gs_point v;                        /* Not used with synthesised bitmap fonts. */
44
 
};
45
 
 
46
 
/* The descriptor is public for pdf_resource_type_structs. */
47
 
gs_public_st_suffix_add1(st_pdf_char_proc, pdf_char_proc_t,
48
 
  "pdf_char_proc_t", pdf_char_proc_enum_ptrs, pdf_char_proc_reloc_ptrs,
49
 
  st_pdf_resource, owner_fonts);
50
 
 
51
 
struct pdf_char_proc_ownership_s {
52
 
    pdf_char_proc_t *char_proc;
53
 
    pdf_char_proc_ownership_t *font_next;        /* next char_proc for same font */
54
 
    pdf_char_proc_ownership_t *char_next;        /* next char_proc for same charproc */
55
 
    pdf_font_resource_t *font;
56
 
    gs_char char_code;                /* Character code in PDF font. */
57
 
    gs_glyph glyph;                /* Glyph id in Postscript font. */
58
 
    gs_const_string char_name;
59
 
    bool duplicate_char_name;
60
 
};
61
 
gs_private_st_strings1_ptrs4(st_pdf_char_proc_ownership, pdf_char_proc_ownership_t,
62
 
  "pdf_char_proc_ownership_t", pdf_char_proc_ownership_enum_ptrs,
63
 
  pdf_char_proc_ownership_reloc_ptrs, char_name, char_proc, char_next, font_next, font);
64
 
 
65
 
gs_private_st_ptrs1(st_pdf_bitmap_fonts, pdf_bitmap_fonts_t,
66
 
  "pdf_bitmap_fonts_t", pdf_bitmap_fonts_enum_ptrs,
67
 
  pdf_bitmap_fonts_reloc_ptrs, open_font);
68
 
 
69
 
static inline long
70
 
pdf_char_proc_id(const pdf_char_proc_t *pcp)
71
 
{
72
 
    return pdf_resource_id((const pdf_resource_t *)pcp);
73
 
}
74
 
 
75
 
/* Assign a code for a char_proc. */
76
 
static int
77
 
assign_char_code(gx_device_pdf * pdev, gs_text_enum_t *pte)
78
 
{
79
 
    pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
80
 
    pdf_font_resource_t *pdfont = pbfs->open_font; /* Type 3 */
81
 
    int i, c = 0, code;
82
 
    uint operation = pte->text.operation;
83
 
 
84
 
    if (pbfs->bitmap_encoding_id == 0)
85
 
        pbfs->bitmap_encoding_id = pdf_obj_ref(pdev);
86
 
    if (pdfont == 0 || pdfont->u.simple.LastChar == 255 ||
87
 
        !pbfs->use_open_font
88
 
        ) {
89
 
        /* Start a new synthesized font. */
90
 
        char *pc;
91
 
 
92
 
        code = pdf_font_type3_alloc(pdev, &pdfont, pdf_write_contents_bitmap);
93
 
        if (code < 0)
94
 
            return code;
95
 
        pdfont->u.simple.s.type3.bitmap_font = true;
96
 
        if (pbfs->open_font == 0)
97
 
            pdfont->rname[0] = 0;
98
 
        else
99
 
            strcpy(pdfont->rname, pbfs->open_font->rname);
100
 
        pdfont->u.simple.s.type3.FontBBox.p.x = 0;
101
 
        pdfont->u.simple.s.type3.FontBBox.p.y = 0;
102
 
        pdfont->u.simple.s.type3.FontBBox.q.x = 0;
103
 
        pdfont->u.simple.s.type3.FontBBox.q.y = 0;
104
 
        pdfont->mark_glyph = NULL;
105
 
        gs_make_identity(&pdfont->u.simple.s.type3.FontMatrix);
106
 
        /*
107
 
         * We "increment" the font name as a radix-26 "number".
108
 
         * This cannot possibly overflow.
109
 
         */
110
 
        for (pc = pdfont->rname; *pc == 'Z'; ++pc)
111
 
            *pc = '@';
112
 
        if ((*pc)++ == 0)
113
 
            *pc = 'A', pc[1] = 0;
114
 
        pbfs->open_font = pdfont;
115
 
        pbfs->use_open_font = true;
116
 
        pdfont->u.simple.FirstChar = 255;
117
 
    }
118
 
    if ((operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) ||
119
 
        (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR))) {
120
 
        unsigned char p = *pte->text.data.bytes;
121
 
        unsigned char index = p / 8, bit = 0x01 << (p % 8);
122
 
 
123
 
        if (pdfont->used[index] & bit) {
124
 
            for (i = 0;i < 256;i++) {
125
 
                index = i / 8;
126
 
                bit = 0x01 << (i % 8);
127
 
                if (!(pdfont->used[index] & bit)) {
128
 
                    c = i;
129
 
                    break;
130
 
                }
131
 
            }
132
 
        } else
133
 
            c = p;
134
 
        pdfont->used[index] |= bit;
135
 
        if (c > pdfont->u.simple.LastChar)
136
 
            pdfont->u.simple.LastChar = c;
137
 
 
138
 
    } else {
139
 
        unsigned char index, bit;
140
 
        c = ++(pdfont->u.simple.LastChar);
141
 
        index = c / 8;
142
 
        bit = 0x01 << (c % 8);
143
 
        pdfont->used[index] |= bit;
144
 
    }
145
 
    if (c < pdfont->u.simple.FirstChar)
146
 
        pdfont->u.simple.FirstChar = c;
147
 
 
148
 
    pdfont->Widths[c] = psdf_round(pdev->char_width.x, 100, 10); /* See
149
 
                        pdf_write_Widths about rounding. We need to provide
150
 
                        a compatible data for Tj. */
151
 
    if (c > pbfs->max_embedded_code)
152
 
        pbfs->max_embedded_code = c;
153
 
 
154
 
    return c;
155
 
}
156
 
 
157
 
/* Write the contents of a Type 3 bitmap or vector font resource. */
158
 
int
159
 
pdf_write_contents_bitmap(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
160
 
{
161
 
    stream *s = pdev->strm;
162
 
    const pdf_char_proc_ownership_t *pcpo;
163
 
    long diff_id = 0;
164
 
    int code;
165
 
 
166
 
    if (pdfont->u.simple.s.type3.bitmap_font)
167
 
        diff_id = pdev->text->bitmap_fonts->bitmap_encoding_id;
168
 
    else {
169
 
        /* See comment in pdf_write_encoding. */
170
 
        diff_id = pdf_obj_ref(pdev);
171
 
    }
172
 
    code = pdf_write_encoding_ref(pdev, pdfont, diff_id);
173
 
    if (code < 0)
174
 
        return code;
175
 
    stream_puts(s, "/CharProcs <<");
176
 
    /* Write real characters. */
177
 
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo;
178
 
         pcpo = pcpo->char_next
179
 
         ) {
180
 
        if (pdfont->u.simple.s.type3.bitmap_font)
181
 
            pprintld2(s, "/a%ld %ld 0 R\n", (long)pcpo->char_code,
182
 
                      pdf_char_proc_id(pcpo->char_proc));
183
 
        else if (!pcpo-> duplicate_char_name) {
184
 
            pdf_put_name(pdev, pcpo->char_name.data, pcpo->char_name.size);
185
 
            pprintld1(s, " %ld 0 R\n", pdf_char_proc_id(pcpo->char_proc));
186
 
        }
187
 
        pdf_record_usage_by_parent(pdev, pdf_char_proc_id(pcpo->char_proc), pdfont->object->id);
188
 
    }
189
 
    stream_puts(s, ">>");
190
 
    pprintg6(s, "/FontMatrix[%g %g %g %g %g %g]",
191
 
            (float)pdfont->u.simple.s.type3.FontMatrix.xx,
192
 
            (float)pdfont->u.simple.s.type3.FontMatrix.xy,
193
 
            (float)pdfont->u.simple.s.type3.FontMatrix.yx,
194
 
            (float)pdfont->u.simple.s.type3.FontMatrix.yy,
195
 
            (float)pdfont->u.simple.s.type3.FontMatrix.tx,
196
 
            (float)pdfont->u.simple.s.type3.FontMatrix.ty);
197
 
    code = pdf_finish_write_contents_type3(pdev, pdfont);
198
 
    if (code < 0)
199
 
        return code;
200
 
    if (!pdfont->u.simple.s.type3.bitmap_font && diff_id > 0) {
201
 
        code = pdf_write_encoding(pdev, pdfont, diff_id, 0);
202
 
        if (code < 0)
203
 
            return code;
204
 
    }
205
 
    return 0;
206
 
}
207
 
 
208
 
/* ---------------- Public ---------------- */
209
 
 
210
 
/*
211
 
 * Allocate and initialize bookkeeping for bitmap fonts.
212
 
 */
213
 
pdf_bitmap_fonts_t *
214
 
pdf_bitmap_fonts_alloc(gs_memory_t *mem)
215
 
{
216
 
    pdf_bitmap_fonts_t *pbfs =
217
 
        gs_alloc_struct(mem, pdf_bitmap_fonts_t, &st_pdf_bitmap_fonts,
218
 
                        "pdf_bitmap_fonts_alloc");
219
 
 
220
 
    if (pbfs == 0)
221
 
        return 0;
222
 
    memset(pbfs, 0, sizeof(*pbfs));
223
 
    pbfs->max_embedded_code = -1;
224
 
    return pbfs;
225
 
}
226
 
 
227
 
/*
228
 
 * Update text state at the end of a page.
229
 
 */
230
 
void
231
 
pdf_close_text_page(gx_device_pdf *pdev)
232
 
{
233
 
    /*
234
 
     * When Acrobat Reader 3 prints a file containing a Type 3 font with a
235
 
     * non-standard Encoding, it apparently only emits the subset of the
236
 
     * font actually used on the page.  Thus, if the "Download Fonts Once"
237
 
     * option is selected, characters not used on the page where the font
238
 
     * first appears will not be defined, and hence will print as blank if
239
 
     * used on subsequent pages.  Thus, we can't allow a Type 3 font to
240
 
     * add additional characters on subsequent pages.
241
 
     */
242
 
    if (pdev->CompatibilityLevel <= 1.2)
243
 
        pdev->text->bitmap_fonts->use_open_font = false;
244
 
}
245
 
 
246
 
int
247
 
pdf_charproc_y_offset(pdf_char_proc_t *pcp)
248
 
{
249
 
    return pcp->y_offset;
250
 
}
251
 
 
252
 
int
253
 
pdf_charproc_x_offset(pdf_char_proc_t *pcp)
254
 
{
255
 
    return pcp->x_offset;
256
 
}
257
 
 
258
 
/* Attach a CharProc to a font. */
259
 
static int
260
 
pdf_attach_charproc(gx_device_pdf * pdev, pdf_font_resource_t *pdfont, pdf_char_proc_t *pcp,
261
 
                    gs_glyph glyph, gs_char char_code, const gs_const_string *gnstr)
262
 
{
263
 
    pdf_char_proc_ownership_t *pcpo;
264
 
    bool duplicate_char_name = false;
265
 
 
266
 
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
267
 
        if (pcpo->glyph == glyph && pcpo->char_code == char_code)
268
 
            return 0;
269
 
    }
270
 
    if (!pdfont->u.simple.s.type3.bitmap_font) {
271
 
        for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
272
 
            if (!bytes_compare(pcpo->char_name.data, pcpo->char_name.size, gnstr->data, gnstr->size)) {
273
 
                duplicate_char_name = true;
274
 
                break;
275
 
            }
276
 
        }
277
 
    }
278
 
    pcpo = gs_alloc_struct(pdev->pdf_memory,
279
 
            pdf_char_proc_ownership_t, &st_pdf_char_proc_ownership, "pdf_attach_charproc");
280
 
 
281
 
    if (pcpo == NULL)
282
 
        return_error(gs_error_VMerror);
283
 
    pcpo->font = pdfont;
284
 
    pcpo->char_next = pdfont->u.simple.s.type3.char_procs;
285
 
    pdfont->u.simple.s.type3.char_procs = pcpo;
286
 
    pcpo->char_proc = pcp;
287
 
    pcpo->font_next = pcp->owner_fonts;
288
 
    pcp->owner_fonts = pcpo;
289
 
    pcpo->char_code = char_code;
290
 
    pcpo->glyph = glyph;
291
 
    if (gnstr == NULL) {
292
 
        pcpo->char_name.data = 0;
293
 
        pcpo->char_name.size = 0;
294
 
    } else
295
 
        pcpo->char_name = *gnstr;
296
 
    pcpo->duplicate_char_name = duplicate_char_name;
297
 
    return 0;
298
 
}
299
 
 
300
 
int
301
 
pdf_free_charproc_ownership(gx_device_pdf * pdev, pdf_resource_t *pres)
302
 
{
303
 
    pdf_char_proc_ownership_t *next, *pcpo = (pdf_char_proc_ownership_t *)pres;
304
 
 
305
 
    while (pcpo) {
306
 
        next = pcpo->char_next;
307
 
        if(pcpo->char_name.size != 0 && pcpo->char_name.data) {
308
 
            /* This causes PCL some trouble, don't know why yet FIXME-MEMORY
309
 
            gs_free_string(pdev->pdf_memory, (byte *)pcpo->char_name.data, pcpo->char_name.size, "Free CharProc name");*/
310
 
            pcpo->char_name.data = (byte *)0L;
311
 
            pcpo->char_name.size = 0;
312
 
        }
313
 
        gs_free_object(pdev->pdf_memory, pcpo, "Free CharProc");
314
 
        pcpo = next;
315
 
    }
316
 
    return 0;
317
 
}
318
 
 
319
 
/* Begin a CharProc for a synthesized (bitmap) font. */
320
 
int
321
 
pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
322
 
                    int y_offset, int x_offset, gs_id id, pdf_char_proc_t ** ppcp,
323
 
                    pdf_stream_position_t * ppos)
324
 
{
325
 
    gs_char char_code = 0;
326
 
    pdf_bitmap_fonts_t *const pbfs = pdev->text->bitmap_fonts;
327
 
    pdf_font_resource_t *font;
328
 
    pdf_resource_t *pres;
329
 
    pdf_char_proc_t *pcp;
330
 
    int code;
331
 
    /* This code added to store PCL bitmap glyphs in type 3 fonts where possible */
332
 
    gs_glyph glyph = GS_NO_GLYPH;
333
 
    gs_const_string *str = NULL;
334
 
    gs_show_enum *show_enum = (gs_show_enum *)pdev->pte;
335
 
    pdf_encoding_element_t *pet = 0;
336
 
    /* Since this is for text searching, its only useful if the character code
337
 
     * lies in an ASCII range, so we only handle some kinds of text layout.
338
 
     */
339
 
    int allowed_op = (show_enum->text.operation &
340
 
        (TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR));
341
 
 
342
 
    /* Check to see the current font is a type 3. We can get here if pdfwrite decides
343
 
     * it can't handle a font type, and renders to a bitmap instead. If that's the
344
 
     * case then we can't add the bitmap to the existing font (its not a type 3 font)
345
 
     * and must fall back to holding it in our fallback type 3 font 'collection'.
346
 
     */
347
 
    /* Because the bitmaps are stored directly in the cache they already have any
348
 
     * effects caused by non-identity FontMatrix entries applied. So if the type 3
349
 
     * font we created has a non-identity FontMatrix we can't use it and must
350
 
     * go back to collecting the bitmap into our fallback font.
351
 
     */
352
 
    if ((show_enum->current_font->FontType == ft_user_defined ||
353
 
        show_enum->current_font->FontType == ft_PCL_user_defined ||
354
 
        show_enum->current_font->FontType == ft_GL2_stick_user_defined ||
355
 
        show_enum->current_font->FontType == ft_GL2_531) && allowed_op &&
356
 
        show_enum->current_font->FontMatrix.xx == 1 && show_enum->current_font->FontMatrix.xy == 0 &&
357
 
        show_enum->current_font->FontMatrix.yx == 0 && show_enum->current_font->FontMatrix.yy == 1) {
358
 
        pdf_char_proc_ownership_t *pcpo;
359
 
 
360
 
        gs_font_base *base = (gs_font_base *)show_enum->current_font;
361
 
        code = pdf_attached_font_resource(pdev, show_enum->current_font, &font, NULL, NULL, NULL, NULL);
362
 
        if (code < 0)
363
 
            return code;
364
 
        /* The text processing will have run past the glyph, so we need to 'back up'
365
 
         * by one and get it again in order to get the character code and glyph, and update
366
 
         * the pointer correctly.
367
 
         */
368
 
        show_enum->index--;
369
 
        code = gs_default_next_char_glyph((gs_text_enum_t *)show_enum, (gs_char *)&char_code, &glyph);
370
 
        if (code < 0)
371
 
            return code;
372
 
 
373
 
        /* If the returned character code is outside the possible Encoding for
374
 
         * a type 3 font, then set pet to NULL, this means we will fall back to
375
 
         * the 'collection' font, as pet is checked below.
376
 
         */
377
 
        if (char_code >= 0 && char_code <= 255) {
378
 
            pet = &font->u.simple.Encoding[char_code];
379
 
            if (pet) {
380
 
                /* Check to see if we *already* have this glyph in this font. If
381
 
                 * we do then we can't add it to this font. Setting pet to 0
382
 
                 * falls back to the collection method.
383
 
                 */
384
 
                for (pcpo = font->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
385
 
                    if (pcpo->glyph == pet->glyph && pcpo->char_code == char_code) {
386
 
                        pet = 0x00;
387
 
                        break;
388
 
                    }
389
 
                }
390
 
            }
391
 
        }
392
 
        else
393
 
            pet = 0x00;
394
 
 
395
 
        /* We need a glyph name for the type 3 font's Encoding, if we haven't got one
396
 
         * then we need to give up, something about the font or text is not acceptable
397
 
         * (see various comments above).
398
 
         */
399
 
        if (pet && pet->glyph != GS_NO_GLYPH && !(pet->str.size == 7 &&
400
 
            !strncmp((const char *)pet->str.data, ".notdef", 7))) {
401
 
            if (char_code < font->u.simple.FirstChar)
402
 
                font->u.simple.FirstChar = char_code;
403
 
            if ((int)char_code > font->u.simple.LastChar)
404
 
                font->u.simple.LastChar = char_code;
405
 
            base->FontBBox.q.x = max(base->FontBBox.q.x, w);
406
 
            base->FontBBox.q.y = max(base->FontBBox.q.y, y_offset + h);
407
 
            str = &pet->str;
408
 
            glyph = pet->glyph;
409
 
            /* This is to work around a weird Acrobat bug. If the Encoding of a type 3
410
 
             * (possibly other types) is simply a standard encoding (eg WinAnsiEncoding)
411
 
             * then Acrobat 4 & 8 just ignore the glyphs altogether. This forces us to write
412
 
             * all the used glyphs as /Differencess, and that makes it work <sigh>
413
 
             */
414
 
            pet->is_difference = 1;
415
 
            font->Widths[char_code] = psdf_round(pdev->char_width.x, 100, 10); /* See
416
 
                        pdf_write_Widths about rounding. We need to provide
417
 
                        a compatible data for Tj. */
418
 
        } else {
419
 
            char_code = assign_char_code(pdev, pdev->pte);
420
 
            font = pbfs->open_font; /* Type 3 */
421
 
        }
422
 
    } else {
423
 
        char_code = assign_char_code(pdev, pdev->pte);
424
 
        font = pbfs->open_font; /* Type 3 */
425
 
    }
426
 
 
427
 
    code = pdf_begin_resource(pdev, resourceCharProc, id, &pres);
428
 
    if (code < 0)
429
 
        return code;
430
 
    pcp = (pdf_char_proc_t *) pres;
431
 
    code = pdf_attach_charproc(pdev, font, pcp, glyph, char_code, str);
432
 
    if (code < 0)
433
 
        return code;
434
 
    pres->object->written = true;
435
 
    {
436
 
        stream *s = pdev->strm;
437
 
 
438
 
        /*
439
 
         * The resource file is positionable, so rather than use an
440
 
         * object reference for the length, we'll go back and fill it in
441
 
         * at the end of the definition.  Take 1M as the longest
442
 
         * definition we can handle.  (This used to be 10K, but there was
443
 
         * a real file that exceeded this limit.)
444
 
         */
445
 
        stream_puts(s, "<</Length       >>stream\n");
446
 
        ppos->start_pos = stell(s);
447
 
    }
448
 
    code = pdf_begin_encrypt(pdev, &pdev->strm, pres->object->id);
449
 
    if (code < 0)
450
 
        return code;
451
 
    pcp->y_offset = y_offset;
452
 
    pcp->x_offset = x_offset;
453
 
    font->u.simple.s.type3.FontBBox.q.x =
454
 
        max(font->u.simple.s.type3.FontBBox.q.x, w);
455
 
    font->u.simple.s.type3.FontBBox.q.y =
456
 
        max(font->u.simple.s.type3.FontBBox.q.y, y_offset + h);
457
 
    font->u.simple.s.type3.max_y_offset =
458
 
        max(font->u.simple.s.type3.max_y_offset, h + (h >> 2));
459
 
    *ppcp = pcp;
460
 
    return 0;
461
 
}
462
 
 
463
 
/* End a CharProc. */
464
 
int
465
 
pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos)
466
 
{
467
 
    stream *s;
468
 
    gs_offset_t start_pos, end_pos, length;
469
 
 
470
 
    pdf_end_encrypt(pdev);
471
 
    s = pdev->strm;
472
 
    start_pos = ppos->start_pos;
473
 
    end_pos = stell(s);
474
 
    length = end_pos - start_pos;
475
 
    if (length > 999999)
476
 
        return_error(gs_error_limitcheck);
477
 
    sseek(s, start_pos - 15);
478
 
    pprintd1(s, "%d", length);
479
 
    sseek(s, end_pos);
480
 
    if (pdev->PDFA != 0)
481
 
        stream_puts(s, "\n");
482
 
    stream_puts(s, "endstream\n");
483
 
    pdf_end_separate(pdev, resourceCharProc);
484
 
    return 0;
485
 
}
486
 
 
487
 
/* Mark glyph names for garbager. */
488
 
void
489
 
pdf_mark_glyph_names(const pdf_font_resource_t *pdfont, const gs_memory_t *memory)
490
 
{
491
 
    if (pdfont->mark_glyph == NULL) {
492
 
        /* Synthesised bitmap fonts pass here. */
493
 
        return;
494
 
    }
495
 
    if (pdfont->u.simple.Encoding != NULL) {
496
 
         int i;
497
 
 
498
 
         for (i = 0; i < 256; i++)
499
 
             if (pdfont->u.simple.Encoding[i].glyph != GS_NO_GLYPH)
500
 
                pdfont->mark_glyph(memory, pdfont->u.simple.Encoding[i].glyph, pdfont->mark_glyph_data);
501
 
     }
502
 
    if (pdfont->FontType == ft_user_defined ||
503
 
        pdfont->FontType == ft_PCL_user_defined ||
504
 
        pdfont->FontType == ft_GL2_stick_user_defined ||
505
 
        pdfont->FontType == ft_GL2_531) {
506
 
        const pdf_char_proc_ownership_t *pcpo = pdfont->u.simple.s.type3.char_procs;
507
 
 
508
 
        for (; pcpo != NULL; pcpo = pcpo->font_next)
509
 
            pdfont->mark_glyph(memory, pcpo->glyph, pdfont->mark_glyph_data);
510
 
    }
511
 
}
512
 
 
513
 
/* Put out a reference to an image as a character in a synthesized font. */
514
 
int
515
 
pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
516
 
                  const gs_matrix * pimat)
517
 
{
518
 
    /* We need to choose a font, which use the charproc.
519
 
       In most cases it is the last font, which the charproc is attached to.
520
 
       If the charproc is substituted, it causes a font change. */
521
 
    const pdf_char_proc_ownership_t * pcpo = pcp->owner_fonts;
522
 
    pdf_font_resource_t *pdfont = pcpo->font;
523
 
    byte ch = pcpo->char_code;
524
 
    pdf_text_state_values_t values;
525
 
 
526
 
    values.character_spacing = 0;
527
 
    values.pdfont = pdfont;
528
 
    values.size = 1;
529
 
    values.matrix = *pimat;
530
 
    values.render_mode = 0;
531
 
    values.word_spacing = 0;
532
 
    pdf_set_text_state_values(pdev, &values);
533
 
    pdf_append_chars(pdev, &ch, 1, pdfont->Widths[ch] * pimat->xx, 0.0, false);
534
 
    return 0;
535
 
}
536
 
 
537
 
/*
538
 
 * Write the Encoding for bitmap fonts, if needed.
539
 
 */
540
 
int
541
 
pdf_write_bitmap_fonts_Encoding(gx_device_pdf *pdev)
542
 
{
543
 
    pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
544
 
 
545
 
    if (pbfs->bitmap_encoding_id) {
546
 
        stream *s;
547
 
        int i;
548
 
 
549
 
        pdf_open_separate(pdev, pbfs->bitmap_encoding_id, resourceEncoding);
550
 
        s = pdev->strm;
551
 
        /*
552
 
         * Even though the PDF reference documentation says that a
553
 
         * BaseEncoding key is required unless the encoding is
554
 
         * "based on the base font's encoding" (and there is no base
555
 
         * font in this case), Acrobat 2.1 gives an error if the
556
 
         * BaseEncoding key is present.
557
 
         */
558
 
        stream_puts(s, "<</Type/Encoding/Differences[0");
559
 
        for (i = 0; i <= pbfs->max_embedded_code; ++i) {
560
 
            if (!(i & 15))
561
 
                stream_puts(s, "\n");
562
 
            pprintd1(s, "/a%d", i);
563
 
        }
564
 
        stream_puts(s, "\n] >>\n");
565
 
        pdf_end_separate(pdev, resourceEncoding);
566
 
        pbfs->bitmap_encoding_id = 0;
567
 
    }
568
 
    return 0;
569
 
}
570
 
 
571
 
/*
572
 
 * Start charproc accumulation for a Type 3 font.
573
 
 */
574
 
int
575
 
pdf_start_charproc_accum(gx_device_pdf *pdev)
576
 
{
577
 
    pdf_char_proc_t *pcp;
578
 
    pdf_resource_t *pres;
579
 
    int code = pdf_enter_substream(pdev, resourceCharProc, gs_next_ids(pdev->memory, 1),
580
 
                                   &pres, false, pdev->CompressFonts);
581
 
 
582
 
    if (code < 0)
583
 
       return code;
584
 
    pcp = (pdf_char_proc_t *)pres;
585
 
    pcp->owner_fonts = NULL;
586
 
    return 0;
587
 
}
588
 
 
589
 
/*
590
 
 * Install charproc accumulator for a Type 3 font.
591
 
 */
592
 
int
593
 
pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, double *pw, int narg,
594
 
                gs_text_cache_control_t control, gs_char ch, bool scale_100)
595
 
{
596
 
    pdf_font_resource_t *pdfont;
597
 
    pdf_resource_t *pres = pdev->accumulating_substream_resource;
598
 
    pdf_char_proc_t *pcp;
599
 
    int code;
600
 
 
601
 
    code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
602
 
    if (code < 0)
603
 
        return code;
604
 
    pcp = (pdf_char_proc_t *)pres;
605
 
    pcp->owner_fonts = NULL;
606
 
    pcp->real_width.x = pw[font->WMode && narg > 6 ? 6 : 0];
607
 
    pcp->real_width.y = pw[font->WMode && narg > 6 ? 7 : 1];
608
 
    pcp->v.x = (narg > 8 ? pw[8] : 0);
609
 
    pcp->v.y = (narg > 8 ? pw[9] : 0);
610
 
    if (control == TEXT_SET_CHAR_WIDTH) {
611
 
        /* PLRM 5.7.1 "BuildGlyph" reads : "Normally, it is unnecessary and
612
 
        undesirable to initialize the current color parameter, because show
613
 
        is defined to paint glyphs with the current color."
614
 
        However comparefiles/Bug687044.ps doesn't follow that. */
615
 
        pdev->skip_colors = false;
616
 
        pprintg1(pdev->strm, "%g 0 d0\n", (float)pw[0]);
617
 
        /* The colour change described above can't affect PCL fonts and we need
618
 
         * all glyphs to be noted as cached in order for the bitmap font cache
619
 
         * probing to work properly.
620
 
         */
621
 
        if (font->FontType == ft_PCL_user_defined || font->FontType == ft_GL2_stick_user_defined
622
 
            || font->FontType == ft_GL2_531)
623
 
            pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
624
 
    } else {
625
 
        double d;
626
 
        pdev->skip_colors = true;
627
 
        if (pw[4] < pw[2]) {
628
 
            d = pw[2];
629
 
            pw[2] = pw[4];
630
 
            pw[4] = d;
631
 
        }
632
 
        if (pw[5] < pw[3]) {
633
 
            d = pw[5];
634
 
            pw[5] = pw[3];
635
 
            pw[3] = d;
636
 
        }
637
 
        pprintg6(pdev->strm, "%g %g %g %g %g %g d1\n",
638
 
            (float)pw[0], (float)0.0, (float)pw[2],
639
 
            (float)pw[3], (float)pw[4], (float)pw[5]);
640
 
        pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
641
 
    }
642
 
    /* See comments in pdf_text_process regarding type 3 CharProc accumulation
643
 
     * Initially this matrix was emitted there, at the start of the accumulator
644
 
     * but if we do that then GS incorrectly applied the matrix to the 'd1'
645
 
     * operator. We write the scale matrix here because this is *after* the
646
 
     * 'd1' has been emitted above, and so does not affect it.
647
 
     */
648
 
    if (scale_100) {
649
 
    code = stream_puts(pdev->strm, "0.01 0 0 0.01 0 0 cm\n");
650
 
    if (code < 0)
651
 
        return code;
652
 
    }
653
 
    return 0;
654
 
}
655
 
 
656
 
/*
657
 
 * Open a stream object in the temporary file.
658
 
 */
659
 
 
660
 
int
661
 
pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype,
662
 
        gs_id id, pdf_resource_t **ppres, bool reserve_object_id, int options)
663
 
{
664
 
    int code;
665
 
    pdf_resource_t *pres;
666
 
    stream *s, *save_strm = pdev->strm;
667
 
    pdf_data_writer_t writer;
668
 
    static const pdf_filter_names_t fnames = {
669
 
        PDF_FILTER_NAMES
670
 
    };
671
 
 
672
 
    pdev->streams.save_strm = pdev->strm;
673
 
 
674
 
    if (rtype > NUM_RESOURCE_TYPES)
675
 
        rtype = resourceOther;
676
 
    code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, id),
677
 
                pdf_resource_type_structs[rtype], &pres, reserve_object_id ? 0 : -1);
678
 
    if (code < 0)
679
 
        return code;
680
 
    cos_become(pres->object, cos_type_stream);
681
 
    s = cos_write_stream_alloc((cos_stream_t *)pres->object, pdev, "pdf_enter_substream");
682
 
    if (s == 0)
683
 
        return_error(gs_error_VMerror);
684
 
    pdev->strm = s;
685
 
    code = pdf_append_data_stream_filters(pdev, &writer,
686
 
                             options | DATA_STREAM_NOLENGTH, pres->object->id);
687
 
    if (code < 0) {
688
 
        pdev->strm = save_strm;
689
 
        return code;
690
 
    }
691
 
    code = pdf_put_filters((cos_dict_t *)pres->object, pdev, writer.binary.strm, &fnames);
692
 
    if (code < 0) {
693
 
        pdev->strm = save_strm;
694
 
        return code;
695
 
    }
696
 
    pdev->strm = writer.binary.strm;
697
 
    *ppres = pres;
698
 
    return 0;
699
 
}
700
 
 
701
 
/*
702
 
 * Close a stream object in the temporary file.
703
 
 */
704
 
int
705
 
pdf_close_aside(gx_device_pdf *pdev)
706
 
{
707
 
    /* We should call pdf_end_data here, but we don't want to put pdf_data_writer_t
708
 
       into pdf_substream_save stack to simplify garbager descriptors.
709
 
       Use a lower level functions instead that. */
710
 
    stream *s = pdev->strm;
711
 
    cos_stream_t *pcs = cos_stream_from_pipeline(s);
712
 
    int status = s_close_filters(&s, NULL);
713
 
 
714
 
    pdev->strm = pdev->streams.save_strm;
715
 
    if (status < 0)
716
 
         return(gs_note_error(gs_error_ioerror));
717
 
 
718
 
    pcs->is_open = false;
719
 
    return 0;
720
 
}
721
 
 
722
 
/*
723
 
 * Enter the substream accumulation mode.
724
 
 */
725
 
int
726
 
pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype,
727
 
        gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress)
728
 
{
729
 
    int sbstack_ptr = pdev->sbstack_depth;
730
 
    pdf_resource_t *pres;
731
 
    stream *save_strm = pdev->strm;
732
 
    int code;
733
 
 
734
 
    if (pdev->sbstack_depth >= pdev->sbstack_size)
735
 
        return_error(gs_error_unregistered); /* Must not happen. */
736
 
    if (pdev->sbstack[sbstack_ptr].text_state == 0) {
737
 
        pdev->sbstack[sbstack_ptr].text_state = pdf_text_state_alloc(pdev->pdf_memory);
738
 
        if (pdev->sbstack[sbstack_ptr].text_state == 0)
739
 
            return_error(gs_error_VMerror);
740
 
    }
741
 
    code = pdf_open_aside(pdev, rtype, id, &pres, reserve_object_id,
742
 
                    (compress ? DATA_STREAM_COMPRESS : 0));
743
 
    if (code < 0)
744
 
        return code;
745
 
    code = pdf_save_viewer_state(pdev, NULL);
746
 
    if (code < 0) {
747
 
        pdev->strm = save_strm;
748
 
        return code;
749
 
    }
750
 
    pdev->sbstack[sbstack_ptr].context = pdev->context;
751
 
    pdf_text_state_copy(pdev->sbstack[sbstack_ptr].text_state, pdev->text->text_state);
752
 
    pdf_set_text_state_default(pdev->text->text_state);
753
 
    pdev->sbstack[sbstack_ptr].clip_path = pdev->clip_path;
754
 
    pdev->clip_path = 0;
755
 
    pdev->sbstack[sbstack_ptr].clip_path_id = pdev->clip_path_id;
756
 
    pdev->clip_path_id = pdev->no_clip_path_id;
757
 
    pdev->sbstack[sbstack_ptr].vgstack_bottom = pdev->vgstack_bottom;
758
 
    pdev->vgstack_bottom = pdev->vgstack_depth;
759
 
    pdev->sbstack[sbstack_ptr].strm = save_strm;
760
 
    pdev->sbstack[sbstack_ptr].procsets = pdev->procsets;
761
 
    pdev->sbstack[sbstack_ptr].substream_Resources = pdev->substream_Resources;
762
 
    pdev->sbstack[sbstack_ptr].skip_colors = pdev->skip_colors;
763
 
    pdev->sbstack[sbstack_ptr].font3 = pdev->font3;
764
 
    pdev->sbstack[sbstack_ptr].accumulating_substream_resource = pdev->accumulating_substream_resource;
765
 
    pdev->sbstack[sbstack_ptr].charproc_just_accumulated = pdev->charproc_just_accumulated;
766
 
    pdev->sbstack[sbstack_ptr].accumulating_a_global_object = pdev->accumulating_a_global_object;
767
 
    pdev->sbstack[sbstack_ptr].pres_soft_mask_dict = pdev->pres_soft_mask_dict;
768
 
    pdev->sbstack[sbstack_ptr].objname = pdev->objname;
769
 
    pdev->sbstack[sbstack_ptr].last_charpath_op = pdev->last_charpath_op;
770
 
    pdev->skip_colors = false;
771
 
    pdev->charproc_just_accumulated = false;
772
 
    pdev->pres_soft_mask_dict = NULL;
773
 
    pdev->objname.data = NULL;
774
 
    pdev->objname.size = 0;
775
 
    /* Do not reset pdev->accumulating_a_global_object - it inherits. */
776
 
    pdev->sbstack_depth++;
777
 
    pdev->procsets = 0;
778
 
    pdev->font3 = 0;
779
 
    pdev->context = PDF_IN_STREAM;
780
 
    pdev->accumulating_substream_resource = pres;
781
 
    pdev->last_charpath_op = 0;
782
 
    /* Do not alter type3charpath, inherit the current value. We need to know if */
783
 
    /* we are inside a charpath operation, and only reset this when the charpath */
784
 
    /* is complete */
785
 
    pdf_reset_graphics(pdev);
786
 
    *ppres = pres;
787
 
    return 0;
788
 
}
789
 
 
790
 
/*
791
 
 * Exit the substream accumulation mode.
792
 
 */
793
 
int
794
 
pdf_exit_substream(gx_device_pdf *pdev)
795
 
{
796
 
    int code, code1;
797
 
    int sbstack_ptr;
798
 
 
799
 
    if (pdev->sbstack_depth <= 0)
800
 
        return_error(gs_error_unregistered); /* Must not happen. */
801
 
    code = pdf_open_contents(pdev, PDF_IN_STREAM);
802
 
    sbstack_ptr = pdev->sbstack_depth - 1;
803
 
    while (pdev->vgstack_depth > pdev->vgstack_bottom) {
804
 
        code1 = pdf_restore_viewer_state(pdev, pdev->strm);
805
 
        if (code >= 0)
806
 
            code = code1;
807
 
    }
808
 
    if (pdev->clip_path != 0)
809
 
        gx_path_free(pdev->clip_path, "pdf_end_charproc_accum");
810
 
    code1 = pdf_close_aside(pdev);
811
 
    if (code1 < 0 && code >= 0)
812
 
        code = code1;
813
 
    pdev->context = pdev->sbstack[sbstack_ptr].context;
814
 
    pdf_text_state_copy(pdev->text->text_state, pdev->sbstack[sbstack_ptr].text_state);
815
 
    pdev->clip_path = pdev->sbstack[sbstack_ptr].clip_path;
816
 
    pdev->sbstack[sbstack_ptr].clip_path = 0;
817
 
    pdev->clip_path_id = pdev->sbstack[sbstack_ptr].clip_path_id;
818
 
    pdev->vgstack_bottom = pdev->sbstack[sbstack_ptr].vgstack_bottom;
819
 
    pdev->strm = pdev->sbstack[sbstack_ptr].strm;
820
 
    pdev->sbstack[sbstack_ptr].strm = 0;
821
 
    pdev->procsets = pdev->sbstack[sbstack_ptr].procsets;
822
 
    pdev->substream_Resources = pdev->sbstack[sbstack_ptr].substream_Resources;
823
 
    pdev->sbstack[sbstack_ptr].substream_Resources = 0;
824
 
    pdev->skip_colors = pdev->sbstack[sbstack_ptr].skip_colors;
825
 
    pdev->font3 = pdev->sbstack[sbstack_ptr].font3;
826
 
    pdev->sbstack[sbstack_ptr].font3 = 0;
827
 
    pdev->accumulating_substream_resource = pdev->sbstack[sbstack_ptr].accumulating_substream_resource;
828
 
    pdev->sbstack[sbstack_ptr].accumulating_substream_resource = 0;
829
 
    pdev->charproc_just_accumulated = pdev->sbstack[sbstack_ptr].charproc_just_accumulated;
830
 
    pdev->accumulating_a_global_object = pdev->sbstack[sbstack_ptr].accumulating_a_global_object;
831
 
    pdev->pres_soft_mask_dict = pdev->sbstack[sbstack_ptr].pres_soft_mask_dict;
832
 
    pdev->objname = pdev->sbstack[sbstack_ptr].objname;
833
 
    pdev->last_charpath_op = pdev->sbstack[sbstack_ptr].last_charpath_op;
834
 
    pdev->sbstack_depth = sbstack_ptr;
835
 
    code1 = pdf_restore_viewer_state(pdev, NULL);
836
 
    if (code1 < 0 && code >= 0)
837
 
        code = code1;
838
 
    return code;
839
 
}
840
 
 
841
 
static bool
842
 
pdf_is_same_charproc_attrs1(gx_device_pdf *pdev, pdf_char_proc_t *pcp0, pdf_char_proc_t *pcp1)
843
 
{
844
 
    if (pcp0->real_width.x != pcp1->real_width.x)
845
 
        return false;
846
 
    if (pcp0->real_width.y != pcp1->real_width.y)
847
 
        return false;
848
 
    if (pcp0->v.x != pcp1->v.x)
849
 
        return false;
850
 
    if (pcp0->v.y != pcp1->v.y)
851
 
        return false;
852
 
    return true;
853
 
}
854
 
 
855
 
typedef struct charproc_compatibility_data_s {
856
 
    const pdf_char_glyph_pairs_t *cgp;
857
 
    pdf_font_resource_t *pdfont;
858
 
    gs_char char_code;
859
 
    gs_glyph glyph;
860
 
    gs_font *font;
861
 
} charproc_compatibility_data_t;
862
 
 
863
 
static bool
864
 
is_char_code_used(pdf_font_resource_t *pdfont, gs_char char_code)
865
 
{
866
 
    pdf_char_proc_ownership_t *pcpo;
867
 
 
868
 
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
869
 
        if (pcpo->char_code == char_code) {
870
 
            return true;
871
 
        }
872
 
    }
873
 
    return false;
874
 
}
875
 
 
876
 
static int
877
 
pdf_is_charproc_compatible(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
878
 
{
879
 
    charproc_compatibility_data_t *data = (charproc_compatibility_data_t *)pdev->find_resource_param;
880
 
    pdf_char_proc_t *pcp0 = (pdf_char_proc_t *)pres0;
881
 
    pdf_char_proc_t *pcp1 = (pdf_char_proc_t *)pres1;
882
 
    pdf_font_resource_t *pdfont = data->pdfont;
883
 
    pdf_char_proc_ownership_t *pcpo;
884
 
    pdf_font_cache_elem_t **e;
885
 
    bool can_add_to_current_font = false, computed_can_add_to_current_font = false;
886
 
 
887
 
    /* Does it have same attributes ? */
888
 
    if (!pdf_is_same_charproc_attrs1(pdev, pcp0, pcp1))
889
 
        return 0;
890
 
    /* Is it from same font ? */
891
 
    for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
892
 
        if (pdfont == pcpo->font) {
893
 
            /* Check for encoding conflict. */
894
 
            if (pcpo->char_code == data->char_code && pcpo->glyph == data->glyph)
895
 
                return 1; /* Same char code. */
896
 
            if (!computed_can_add_to_current_font) {
897
 
                can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
898
 
                computed_can_add_to_current_font = true;
899
 
            }
900
 
            if (can_add_to_current_font)
901
 
                return 1; /* No conflict. */
902
 
        }
903
 
    }
904
 
    /* Look for another font with same encoding,
905
 
       because we want to reduce the number of new fonts.
906
 
       We also restrict with ones attached to same PS font,
907
 
       otherwise it creates too mixed fonts and disturbs word breaks.
908
 
     */
909
 
    e = pdf_locate_font_cache_elem(pdev, data->font);
910
 
    if (e != NULL) {
911
 
        for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
912
 
            if (pcpo->char_code != data->char_code || pcpo->glyph != data->glyph)
913
 
                continue; /* Need same Encoding to generate a proper ToUnicode. */
914
 
            if (pdfont->u.simple.s.type3.bitmap_font != pcpo->font->u.simple.s.type3.bitmap_font)
915
 
                continue;
916
 
            if (gs_matrix_compare(&pdfont->u.simple.s.type3.FontMatrix, &pcpo->font->u.simple.s.type3.FontMatrix))
917
 
                continue;
918
 
            if (data->cgp != NULL) {
919
 
                if (!pdf_check_encoding_compatibility(pcpo->font, data->cgp->s, data->cgp->num_all_chars))
920
 
                    continue;
921
 
            }
922
 
            if ((*e)->pdfont != pcpo->font)
923
 
                continue;
924
 
            data->pdfont = pcpo->font; /* Switch to the other font. */
925
 
            return 1;
926
 
        }
927
 
    }
928
 
    /* Check whether it can be added into the current font. */
929
 
    if (!computed_can_add_to_current_font)
930
 
        can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
931
 
    if (!can_add_to_current_font) {
932
 
        /* Can't substitute due to encoding conflict. */
933
 
        return 0;
934
 
    }
935
 
    /* The current font will share it with another font. */
936
 
    return 1;
937
 
}
938
 
 
939
 
static int
940
 
pdf_find_same_charproc_aux(gx_device_pdf *pdev,
941
 
            pdf_font_resource_t **ppdfont, pdf_char_proc_t **ppcp)
942
 
{
943
 
    pdf_char_proc_ownership_t *pcpo;
944
 
    int code;
945
 
 
946
 
    /* fixme: this passes parameters to pdf_is_charproc_compatible
947
 
       through special gx_device_pdf field pdev->find_resource_param
948
 
       due to prototype limitation of pdf_find_same_resource.
949
 
       It would be better to change the client data argument type in there to void. */
950
 
    for (pcpo = (*ppdfont)->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
951
 
        pdf_char_proc_t *pcp = pcpo->char_proc;
952
 
 
953
 
        if (*ppcp != pcp && pdf_is_same_charproc_attrs1(pdev, *ppcp, pcp)) {
954
 
            cos_object_t *pco0 = pcp->object;
955
 
            cos_object_t *pco1 = (*ppcp)->object;
956
 
 
957
 
            code = pco0->cos_procs->equal(pco0, pco1, pdev);
958
 
            if (code < 0) {
959
 
                return code;
960
 
            }
961
 
            if (code) {
962
 
                *ppcp = pcp;
963
 
                return 1;
964
 
            }
965
 
        }
966
 
    }
967
 
    return pdf_find_same_resource(pdev, resourceCharProc, (pdf_resource_t **)ppcp, pdf_is_charproc_compatible);
968
 
}
969
 
static int
970
 
pdf_find_same_charproc(gx_device_pdf *pdev,
971
 
            pdf_font_resource_t **ppdfont, const pdf_char_glyph_pairs_t *cgp,
972
 
            pdf_char_proc_t **ppcp, gs_glyph glyph, gs_char char_code,
973
 
            gs_font *font)
974
 
{
975
 
    charproc_compatibility_data_t data;
976
 
    int code;
977
 
 
978
 
    data.cgp = cgp;
979
 
    data.pdfont = *ppdfont;
980
 
    data.char_code = char_code;
981
 
    data.glyph = glyph;
982
 
    data.font = font;
983
 
    pdev->find_resource_param = &data;
984
 
    code = pdf_find_same_charproc_aux(pdev, ppdfont, ppcp);
985
 
    pdev->find_resource_param = NULL;
986
 
    *ppdfont = data.pdfont;
987
 
    return code;
988
 
}
989
 
 
990
 
static bool
991
 
pdf_is_charproc_defined(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, gs_char ch)
992
 
{
993
 
    pdf_char_proc_ownership_t *pcpo;
994
 
 
995
 
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
996
 
        if (pcpo->char_code == ch)
997
 
            return true;
998
 
    }
999
 
    return false;
1000
 
}
1001
 
 
1002
 
static int
1003
 
complete_adding_char(gx_device_pdf *pdev, gs_font *font,
1004
 
                     gs_glyph glyph, gs_char ch, pdf_char_proc_t *pcp,
1005
 
                     const gs_const_string *gnstr)
1006
 
{
1007
 
    pdf_font_resource_t *pdfont;
1008
 
    double *real_widths;
1009
 
    byte *glyph_usage;
1010
 
    int char_cache_size, width_cache_size;
1011
 
    pdf_encoding_element_t *pet;
1012
 
    int code;
1013
 
 
1014
 
    code = pdf_attached_font_resource(pdev, font, &pdfont,
1015
 
                &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1016
 
    if (code < 0)
1017
 
        return code;
1018
 
    code = pdf_attach_charproc(pdev, pdfont, pcp, glyph, ch, gnstr);
1019
 
    if (code < 0)
1020
 
        return code;
1021
 
    if (ch >= char_cache_size || ch >= width_cache_size)
1022
 
        return_error(gs_error_unregistered); /* Must not happen. */
1023
 
    pet = &pdfont->u.simple.Encoding[ch];
1024
 
    pdfont->Widths[ch] = pcp->real_width.x;
1025
 
    real_widths[ch * 2    ] = pcp->real_width.x;
1026
 
    real_widths[ch * 2 + 1] = pcp->real_width.y;
1027
 
    glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1028
 
    pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
1029
 
    if (pdfont->u.simple.v != NULL && font->WMode) {
1030
 
        pdfont->u.simple.v[ch].x = pcp->v.x;
1031
 
        pdfont->u.simple.v[ch].y = pcp->v.x;
1032
 
    }
1033
 
    pet->glyph = glyph;
1034
 
    pet->str = *gnstr;
1035
 
    pet->is_difference = true;
1036
 
    if (pdfont->u.simple.LastChar < (int)ch)
1037
 
        pdfont->u.simple.LastChar = (int)ch;
1038
 
    if (pdfont->u.simple.FirstChar > (int)ch)
1039
 
        pdfont->u.simple.FirstChar = (int)ch;
1040
 
    return 0;
1041
 
}
1042
 
 
1043
 
static int
1044
 
pdf_char_widths_from_charprocs(gx_device_pdf *pdev, gs_font *font)
1045
 
{
1046
 
    pdf_font_resource_t *pdfont;
1047
 
    double *real_widths;
1048
 
    byte *glyph_usage;
1049
 
    int char_cache_size, width_cache_size;
1050
 
    pdf_char_proc_ownership_t *pcpo;
1051
 
    int code;
1052
 
 
1053
 
    code = pdf_attached_font_resource(pdev, font, &pdfont,
1054
 
                &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1055
 
    if (code < 0)
1056
 
        return code;
1057
 
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
1058
 
        pdf_char_proc_t *pcp = pcpo->char_proc;
1059
 
        gs_char ch = pcpo->char_code;
1060
 
 
1061
 
        real_widths[ch * 2    ] = pcp->real_width.x;
1062
 
        real_widths[ch * 2 + 1] = pcp->real_width.y;
1063
 
        glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1064
 
    }
1065
 
    return 0;
1066
 
}
1067
 
 
1068
 
/*
1069
 
 * Complete charproc accumulation for a Type 3 font.
1070
 
 */
1071
 
int
1072
 
pdf_end_charproc_accum(gx_device_pdf *pdev, gs_font *font, const pdf_char_glyph_pairs_t *cgp,
1073
 
                       gs_glyph glyph, gs_char output_char_code, const gs_const_string *gnstr)
1074
 
{
1075
 
    int code;
1076
 
    pdf_resource_t *pres = (pdf_resource_t *)pdev->accumulating_substream_resource;
1077
 
    /* We could use pdfont->u.simple.s.type3.char_procs insted the thing above
1078
 
       unless the font is defined recursively.
1079
 
       But we don't want such assumption. */
1080
 
    pdf_char_proc_t *pcp = (pdf_char_proc_t *)pres;
1081
 
    pdf_font_resource_t *pdfont;
1082
 
    gs_char ch = output_char_code;
1083
 
    bool checking_glyph_variation = false;
1084
 
 
1085
 
    if (ch == GS_NO_CHAR)
1086
 
        return_error(gs_error_unregistered); /* Must not happen. */
1087
 
    if (ch >= 256)
1088
 
        return_error(gs_error_unregistered); /* Must not happen. */
1089
 
    code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
1090
 
    if (code < 0)
1091
 
        return code;
1092
 
    if (pdfont != (pdf_font_resource_t *)pdev->font3)
1093
 
        return_error(gs_error_unregistered); /* Must not happen. */
1094
 
    code = pdf_exit_substream(pdev);
1095
 
    if (code < 0)
1096
 
        return code;
1097
 
    if (!(pdfont->used[ch >> 3] & (0x80 >> (ch & 7))) ||
1098
 
        !(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))) {
1099
 
        /* First appearence or not cached - check for duplicates. */
1100
 
        pdf_font_resource_t *pdfont1 = pdfont;
1101
 
 
1102
 
        checking_glyph_variation = true;
1103
 
        /* CAUTION : a possible font change. */
1104
 
        code = pdf_find_same_charproc(pdev, &pdfont, cgp, &pcp, glyph, ch, font);
1105
 
        if (code < 0)
1106
 
            return code;
1107
 
        if (code != 0) {
1108
 
            code = pdf_cancel_resource(pdev, pres, resourceCharProc);
1109
 
            if (code < 0)
1110
 
                return code;
1111
 
            pdf_forget_resource(pdev, pres, resourceCharProc);
1112
 
            if (pdfont1 != pdfont) {
1113
 
                code = pdf_attach_font_resource(pdev, font, pdfont);
1114
 
                if (code < 0)
1115
 
                    return code;
1116
 
                code = pdf_char_widths_from_charprocs(pdev, font);
1117
 
                if (code < 0)
1118
 
                    return code;
1119
 
            }
1120
 
            pdev->charproc_just_accumulated = true;
1121
 
            return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
1122
 
        }
1123
 
        if (pdf_is_charproc_defined(pdev, pdfont, ch)) {
1124
 
            /* Encoding conflict after a font change. */
1125
 
            gs_font *base_font = font, *below;
1126
 
 
1127
 
            while ((below = base_font->base) != base_font &&
1128
 
                    base_font->procs.same_font(base_font, below, FONT_SAME_OUTLINES))
1129
 
                base_font = below;
1130
 
            code = pdf_make_font3_resource(pdev, base_font, &pdfont);
1131
 
            if (code < 0)
1132
 
                return code;
1133
 
            code = pdf_attach_font_resource(pdev, font, pdfont);
1134
 
            if (code < 0)
1135
 
                return code;
1136
 
        }
1137
 
    }
1138
 
    pdf_reserve_object_id(pdev, pres, 0);
1139
 
    if (checking_glyph_variation)
1140
 
        pdev->charproc_just_accumulated = true;
1141
 
    return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
1142
 
}
1143
 
 
1144
 
/* Add procsets to substream Resources. */
1145
 
int
1146
 
pdf_add_procsets(cos_dict_t *pcd, pdf_procset_t procsets)
1147
 
{
1148
 
    char str[5 + 7 + 7 + 7 + 5 + 2];
1149
 
    cos_value_t v;
1150
 
 
1151
 
    strcpy(str, "[/PDF");
1152
 
    if (procsets & ImageB)
1153
 
        strcat(str, "/ImageB");
1154
 
    if (procsets & ImageC)
1155
 
        strcat(str, "/ImageC");
1156
 
    if (procsets & ImageI)
1157
 
        strcat(str, "/ImageI");
1158
 
    if (procsets & Text)
1159
 
        strcat(str, "/Text");
1160
 
    strcat(str, "]");
1161
 
    cos_string_value(&v, (byte *)str, strlen(str));
1162
 
    return cos_dict_put_c_key(pcd, "/ProcSet", &v);
1163
 
}
1164
 
 
1165
 
/* Add a resource to substream Resources. */
1166
 
int
1167
 
pdf_add_resource(gx_device_pdf *pdev, cos_dict_t *pcd, const char *key, pdf_resource_t *pres)
1168
 
{
1169
 
    if (pcd != 0) {
1170
 
        const cos_value_t *v = cos_dict_find(pcd, (const byte *)key, strlen(key));
1171
 
        cos_dict_t *list;
1172
 
        int code;
1173
 
        char buf[10 + (sizeof(long) * 8 / 3 + 1)], buf1[sizeof(pres->rname) + 1];
1174
 
 
1175
 
        if (pdev->ForOPDFRead && !pres->global && pdev->accumulating_a_global_object) {
1176
 
            pres->global = true;
1177
 
            code = cos_dict_put_c_key_bool((cos_dict_t *)pres->object, "/.Global", true);
1178
 
            if (code < 0)
1179
 
                return code;
1180
 
        }
1181
 
        sprintf(buf, "%ld 0 R\n", pres->object->id);
1182
 
        if (v != NULL) {
1183
 
            if (v->value_type != COS_VALUE_OBJECT &&
1184
 
                v->value_type != COS_VALUE_RESOURCE)
1185
 
                return_error(gs_error_unregistered); /* Must not happen. */
1186
 
            list = (cos_dict_t *)v->contents.object;
1187
 
            if (list->cos_procs != &cos_dict_procs)
1188
 
                return_error(gs_error_unregistered); /* Must not happen. */
1189
 
        } else {
1190
 
            list = cos_dict_alloc(pdev, "pdf_add_resource");
1191
 
            if (list == NULL)
1192
 
                return_error(gs_error_VMerror);
1193
 
            code = cos_dict_put_c_key_object((cos_dict_t *)pcd, key, (cos_object_t *)list);
1194
 
            if (code < 0)
1195
 
                return code;
1196
 
        }
1197
 
        buf1[0] = '/';
1198
 
        strcpy(buf1 + 1, pres->rname);
1199
 
        return cos_dict_put_string(list, (const byte *)buf1, strlen(buf1),
1200
 
                        (const byte *)buf, strlen(buf));
1201
 
    }
1202
 
    return 0;
1203
 
}