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

« back to all changes in this revision

Viewing changes to base/gdevpdte.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
 
/* Encoding-based (Type 1/2/42) text processing for pdfwrite. */
18
 
 
19
 
#include "math_.h"
20
 
#include "memory_.h"
21
 
#include "gx.h"
22
 
#include "gserrors.h"
23
 
#include "gsutil.h"
24
 
#include "gxfcmap.h"
25
 
#include "gxfcopy.h"
26
 
#include "gxfont.h"
27
 
#include "gxfont0.h"
28
 
#include "gxfont0c.h"
29
 
#include "gxpath.h"             /* for getting current point */
30
 
#include "gxchar.h"     /* for gx_compute_text_oversampling & gx_lookup_cached_char */
31
 
#include "gxfcache.h"    /* for gx_lookup_fm_pair */
32
 
#include "gdevpsf.h"
33
 
#include "gdevpdfx.h"
34
 
#include "gdevpdfg.h"
35
 
#include "gdevpdfo.h"
36
 
#include "gdevpdtx.h"
37
 
#include "gdevpdtd.h"
38
 
#include "gdevpdtf.h"
39
 
#include "gdevpdts.h"
40
 
#include "gdevpdtt.h"
41
 
 
42
 
static int pdf_char_widths(gx_device_pdf *const pdev,
43
 
                            pdf_font_resource_t *pdfont, int ch,
44
 
                            gs_font_base *font,
45
 
                            pdf_glyph_widths_t *pwidths /* may be NULL */);
46
 
static int pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr,
47
 
                               const gs_matrix *pfmat,
48
 
                               pdf_text_process_state_t *ppts,
49
 
                               const gs_glyph *gdata);
50
 
 
51
 
/*
52
 
 * Process a string with a simple gs_font.
53
 
 */
54
 
int
55
 
pdf_process_string_aux(pdf_text_enum_t *penum, gs_string *pstr,
56
 
                          const gs_glyph *gdata, const gs_matrix *pfmat,
57
 
                          pdf_text_process_state_t *ppts)
58
 
{
59
 
    gs_font_base *font = (gs_font_base *)penum->current_font;
60
 
 
61
 
    switch (font->FontType) {
62
 
    case ft_TrueType:
63
 
    case ft_encrypted:
64
 
    case ft_encrypted2:
65
 
    case ft_user_defined:
66
 
    case ft_PCL_user_defined:
67
 
    case ft_GL2_stick_user_defined:
68
 
    case ft_GL2_531:
69
 
        break;
70
 
    default:
71
 
        return_error(gs_error_rangecheck);
72
 
    }
73
 
    return pdf_process_string(penum, pstr, pfmat, ppts, gdata);
74
 
}
75
 
 
76
 
/*
77
 
 * Add char code pair to ToUnicode CMap,
78
 
 * creating the CMap on neccessity.
79
 
 */
80
 
int
81
 
pdf_add_ToUnicode(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfont,
82
 
                  gs_glyph glyph, gs_char ch, const gs_const_string *gnstr)
83
 
{   int code;
84
 
    gs_char unicode;
85
 
 
86
 
    if (glyph == GS_NO_GLYPH)
87
 
        return 0;
88
 
    unicode = font->procs.decode_glyph((gs_font *)font, glyph, ch);
89
 
    if (unicode == GS_NO_CHAR && gnstr != NULL && gnstr->size == 7) {
90
 
        if (!memcmp(gnstr->data, "uni", 3)) {
91
 
            static const char *hexdigits = "0123456789ABCDEF";
92
 
            char *d0 = strchr(hexdigits, gnstr->data[3]);
93
 
            char *d1 = strchr(hexdigits, gnstr->data[4]);
94
 
            char *d2 = strchr(hexdigits, gnstr->data[5]);
95
 
            char *d3 = strchr(hexdigits, gnstr->data[6]);
96
 
 
97
 
            if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL)
98
 
                unicode = ((d0 - hexdigits) << 12) + ((d1 - hexdigits) << 8) +
99
 
                          ((d2 - hexdigits) << 4 ) +  (d3 - hexdigits);
100
 
        }
101
 
    }
102
 
    if (unicode != GS_NO_CHAR) {
103
 
        if (pdfont->cmap_ToUnicode == NULL) {
104
 
            /* ToUnicode CMaps are always encoded with two byte keys. See
105
 
             * Technical Note 5411, 'ToUnicode Mapping File Tutorial'
106
 
             * page 3.
107
 
             */
108
 
            /* Unfortunately, the above is not true. See the PDF Reference (version 1.7
109
 
             * p 472 'ToUnicode CMaps'. Even that documentation is incorrect as it
110
 
             * describes codespaceranges, in fact for Acrobat this is irrelevant,
111
 
             * but the bfranges must be one byte for simple fonts. By altering the
112
 
             * key size for CID fonts we can write both consistently correct.
113
 
             */
114
 
            uint num_codes = 256, key_size = 1;
115
 
 
116
 
            if (font->FontType == ft_CID_encrypted) {
117
 
                gs_font_cid0 *pfcid = (gs_font_cid0 *)font;
118
 
 
119
 
                num_codes = pfcid->cidata.common.CIDCount;
120
 
                key_size = 2;
121
 
            } else if (font->FontType == ft_CID_TrueType || font->FontType == ft_composite) {
122
 
                key_size = 2;
123
 
#ifdef DEPRECATED_906
124
 
                gs_font_cid2 *pfcid = (gs_font_cid2 *)font;
125
 
 
126
 
                num_codes = pfcid->cidata.common.CIDCount;
127
 
#else
128
 
                /* Since PScript5.dll creates GlyphNames2Unicode with character codes
129
 
                   instead CIDs, and with the WinCharSetFFFF-H2 CMap
130
 
                   character codes appears from the range 0-0xFFFF (Bug 687954),
131
 
                   we must use the maximal character code value for the ToUnicode
132
 
                   code count. */
133
 
                num_codes = 65536;
134
 
#endif
135
 
            }
136
 
            code = gs_cmap_ToUnicode_alloc(pdev->pdf_memory, pdfont->rid, num_codes, key_size,
137
 
                                            &pdfont->cmap_ToUnicode);
138
 
            if (code < 0)
139
 
                return code;
140
 
        }
141
 
        if (pdfont->cmap_ToUnicode != NULL)
142
 
            gs_cmap_ToUnicode_add_pair(pdfont->cmap_ToUnicode, ch, unicode);
143
 
    }
144
 
    return 0;
145
 
}
146
 
 
147
 
typedef struct {
148
 
    gx_device_pdf *pdev;
149
 
    pdf_resource_type_t rtype;
150
 
} pdf_resource_enum_data_t;
151
 
 
152
 
static int
153
 
process_resources2(void *client_data, const byte *key_data, uint key_size, const cos_value_t *v)
154
 
{
155
 
    pdf_resource_enum_data_t *data = (pdf_resource_enum_data_t *)client_data;
156
 
    pdf_resource_t *pres = pdf_find_resource_by_resource_id(data->pdev, data->rtype, v->contents.object->id);
157
 
 
158
 
    if (pres == NULL)
159
 
        return_error(gs_error_unregistered); /* Must not happen. */
160
 
    pres->where_used |= data->pdev->used_mask;
161
 
    return 0;
162
 
}
163
 
 
164
 
static int
165
 
process_resources1(void *client_data, const byte *key_data, uint key_size, const cos_value_t *v)
166
 
{
167
 
    pdf_resource_enum_data_t *data = (pdf_resource_enum_data_t *)client_data;
168
 
    static const char *rn[] = {PDF_RESOURCE_TYPE_NAMES};
169
 
    int i;
170
 
 
171
 
    for (i = 0; i < count_of(rn); i++) {
172
 
        if (rn[i] != NULL && !bytes_compare((const byte *)rn[i], strlen(rn[i]), key_data, key_size))
173
 
            break;
174
 
    }
175
 
    if (i >= count_of(rn))
176
 
        return 0;
177
 
    data->rtype = i;
178
 
    return cos_dict_forall((cos_dict_t *)v->contents.object, data, process_resources2);
179
 
}
180
 
 
181
 
/*
182
 
 * Register charproc fonts with the page or substream.
183
 
 */
184
 
int
185
 
pdf_used_charproc_resources(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
186
 
{
187
 
    if (pdfont->where_used & pdev->used_mask)
188
 
        return 0;
189
 
    pdfont->where_used |= pdev->used_mask;
190
 
    if (pdev->CompatibilityLevel >= 1.2)
191
 
        return 0;
192
 
    if (pdfont->FontType == ft_user_defined ||
193
 
        pdfont->FontType == ft_PCL_user_defined ||
194
 
        pdfont->FontType == ft_GL2_stick_user_defined ||
195
 
        pdfont->FontType == ft_GL2_531) {
196
 
        pdf_resource_enum_data_t data;
197
 
 
198
 
        data.pdev = pdev;
199
 
        return cos_dict_forall(pdfont->u.simple.s.type3.Resources, &data, process_resources1);
200
 
    }
201
 
    return 0;
202
 
}
203
 
 
204
 
/*
205
 
 * Given a text string and a simple gs_font, return a font resource suitable
206
 
 * for the text string, possibly re-encoding the string.  This
207
 
 * may involve creating a font resource and/or adding glyphs and/or Encoding
208
 
 * entries to it.
209
 
 *
210
 
 * Sets *ppdfont.
211
 
 */
212
 
static int
213
 
pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfont,
214
 
                  gs_char ch, const gs_glyph *gdata)
215
 
{
216
 
    gs_font_base *cfont, *ccfont;
217
 
    int code;
218
 
    gs_glyph copied_glyph;
219
 
    gs_const_string gnstr;
220
 
    pdf_encoding_element_t *pet;
221
 
    gs_glyph glyph;
222
 
 
223
 
    /*
224
 
     * In contradiction with pre-7.20 versions of pdfwrite,
225
 
     * we never re-encode texts due to possible encoding conflict while font merging.
226
 
     */
227
 
    cfont = pdf_font_resource_font(pdfont, false);
228
 
    ccfont = pdf_font_resource_font(pdfont, true);
229
 
    pet = &pdfont->u.simple.Encoding[ch];
230
 
    glyph = (gdata == NULL ? font->procs.encode_char(font, ch, GLYPH_SPACE_NAME)
231
 
                           : *gdata);
232
 
    if (glyph == GS_NO_GLYPH || glyph == pet->glyph)
233
 
        return 0;
234
 
    if (pet->glyph != GS_NO_GLYPH) { /* encoding conflict */
235
 
        return_error(gs_error_rangecheck);
236
 
        /* Must not happen because pdf_obtain_font_resource
237
 
            * checks for encoding compatibility.
238
 
            */
239
 
    }
240
 
    code = font->procs.glyph_name(font, glyph, &gnstr);
241
 
    if (code < 0)
242
 
        return code;    /* can't get name of glyph */
243
 
    if (font->FontType != ft_user_defined &&
244
 
        font->FontType != ft_PCL_user_defined &&
245
 
        font->FontType != ft_GL2_stick_user_defined &&
246
 
        font->FontType != ft_GL2_531) {
247
 
        /* The standard 14 fonts don't have a FontDescriptor. */
248
 
        code = (pdfont->base_font != 0 ?
249
 
                pdf_base_font_copy_glyph(pdfont->base_font, glyph, (gs_font_base *)font) :
250
 
                pdf_font_used_glyph(pdfont->FontDescriptor, glyph, (gs_font_base *)font));
251
 
        if (code < 0 && code != gs_error_undefined)
252
 
            return code;
253
 
        if (code == gs_error_undefined) {
254
 
            if (pdev->PDFA != 0 || pdev->PDFX) {
255
 
                switch (pdev->PDFACompatibilityPolicy) {
256
 
                    case 0:
257
 
                        emprintf(pdev->memory,
258
 
                             "Requested glyph not present in source font,\n not permitted in PDF/A, reverting to normal PDF output\n");
259
 
                        pdev->AbortPDFAX = true;
260
 
                        pdev->PDFA = 0;
261
 
                        break;
262
 
                    case 1:
263
 
                        emprintf(pdev->memory,
264
 
                             "Requested glyph not present in source font,\n not permitted in PDF/A, glyph will not be present in output file\n\n");
265
 
                        /* Returning an error causees text processing to try and
266
 
                         * handle the glyph by rendering to a bitmap instead of
267
 
                         * as a glyph in a font. This will eliminate the problem
268
 
                         * and the fiel should appear the same as the original.
269
 
                         */
270
 
                        return gs_error_unknownerror;
271
 
                        break;
272
 
                    case 2:
273
 
                        emprintf(pdev->memory,
274
 
                             "Requested glyph not present in source font,\n not permitted in PDF/A, aborting conversion\n");
275
 
                        /* Careful here, only certain errors will bubble up
276
 
                         * through the text processing.
277
 
                         */
278
 
                        return gs_error_invalidfont;
279
 
                        break;
280
 
                    default:
281
 
                        emprintf(pdev->memory,
282
 
                             "Requested glyph not present in source font,\n not permitted in PDF/A, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n");
283
 
                        pdev->AbortPDFAX = true;
284
 
                        pdev->PDFA = 0;
285
 
                        break;
286
 
                }
287
 
            }
288
 
            /* PS font has no such glyph. */
289
 
            if (bytes_compare(gnstr.data, gnstr.size, (const byte *)".notdef", 7)) {
290
 
                pet->glyph = glyph;
291
 
                pet->str = gnstr;
292
 
                pet->is_difference = true;
293
 
            }
294
 
        } else if (pdfont->base_font == NULL && ccfont != NULL &&
295
 
                (gs_copy_glyph_options(font, glyph, (gs_font *)ccfont, COPY_GLYPH_NO_NEW) != 1 ||
296
 
                    gs_copied_font_add_encoding((gs_font *)ccfont, ch, glyph) < 0)) {
297
 
            /*
298
 
                * The "complete" copy of the font appears incomplete
299
 
                * due to incrementally added glyphs. Drop the "complete"
300
 
                * copy now and continue with subset font only.
301
 
                *
302
 
                * Note that we need to add the glyph to the encoding of the
303
 
                * "complete" font, because "PPI-ProPag 2.6.1.4 (archivePg)"
304
 
                * creates multiple font copies with reduced encodings
305
 
                * (we believe it is poorly designed),
306
 
                * and we can merge the copies back to a single font (see Bug 686875).
307
 
                * We also check whether the encoding is compatible.
308
 
                * It must be compatible here due to the pdf_obtain_font_resource
309
 
                * and ccfont logics, but we want to ensure for safety reason.
310
 
                */
311
 
            ccfont = NULL;
312
 
            pdf_font_descriptor_drop_complete_font(pdfont->FontDescriptor);
313
 
        }
314
 
        /*
315
 
            * We arbitrarily allow the first encoded character in a given
316
 
            * position to determine the encoding associated with the copied
317
 
            * font.
318
 
            */
319
 
        copied_glyph = cfont->procs.encode_char((gs_font *)cfont, ch,
320
 
                                                GLYPH_SPACE_NAME);
321
 
        if (glyph != copied_glyph &&
322
 
            gs_copied_font_add_encoding((gs_font *)cfont, ch, glyph) < 0
323
 
            )
324
 
            pet->is_difference = true;
325
 
        pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
326
 
    }
327
 
    /*
328
 
        * We always generate ToUnicode for simple fonts, because
329
 
        * we can't detemine in advance, which glyphs the font actually uses.
330
 
        * The decision about writing it out is deferred until pdf_write_font_resource.
331
 
        */
332
 
    code = pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, &gnstr);
333
 
    if (code < 0)
334
 
        return code;
335
 
    pet->glyph = glyph;
336
 
    pet->str = gnstr;
337
 
    return 0;
338
 
}
339
 
 
340
 
/*
341
 
 * Estimate text bbox.
342
 
 */
343
 
static int
344
 
process_text_estimate_bbox(pdf_text_enum_t *pte, gs_font_base *font,
345
 
                          const gs_const_string *pstr,
346
 
                          const gs_matrix *pfmat,
347
 
                          gs_rect *text_bbox, gs_point *pdpt)
348
 
{
349
 
    int i;
350
 
    int space_char =
351
 
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
352
 
         pte->text.space.s_char : -1);
353
 
    int WMode = font->WMode;
354
 
    int code = 0;
355
 
    gs_point total = {0, 0};
356
 
    gs_fixed_point origin;
357
 
    gs_matrix m;
358
 
    int xy_index = pte->xy_index;
359
 
 
360
 
    if (font->FontBBox.p.x == font->FontBBox.q.x ||
361
 
        font->FontBBox.p.y == font->FontBBox.q.y)
362
 
        return_error(gs_error_undefined);
363
 
    code = gx_path_current_point(pte->path, &origin);
364
 
    if (code < 0)
365
 
        return code;
366
 
    m = ctm_only(pte->pis);
367
 
    m.tx = fixed2float(origin.x);
368
 
    m.ty = fixed2float(origin.y);
369
 
    gs_matrix_multiply(pfmat, &m, &m);
370
 
    for (i = 0; i < pstr->size; ++i) {
371
 
        byte c = pstr->data[i];
372
 
        gs_rect bbox;
373
 
        gs_point wanted, tpt, p0, p1, p2, p3;
374
 
        gs_glyph glyph = font->procs.encode_char((gs_font *)font, c,
375
 
                                        GLYPH_SPACE_NAME);
376
 
        gs_glyph_info_t info;
377
 
        int code;
378
 
 
379
 
        if (glyph == gs_no_glyph)
380
 
            return_error (gs_error_invalidfont);
381
 
 
382
 
        code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
383
 
                                            GLYPH_INFO_WIDTH0 << WMode,
384
 
                                            &info);
385
 
 
386
 
        /* If we got an undefined error, and its a type 1/CFF font, try to
387
 
         * find the /.notdef glyph and use its width instead (as this is the
388
 
         * glyph which will be rendered). We don't do this for other font types
389
 
         * as it seems Acrobat/Distiller may not do so either.
390
 
         */
391
 
        /* The GL/2 stick font does not supply the enumerate_glyphs method,
392
 
         * *and* leaves it uninitialised. But it should not be possible to
393
 
         * get an undefiend error with this font anyway.
394
 
         */
395
 
        if (code < 0) {
396
 
            if ((font->FontType == ft_encrypted ||
397
 
            font->FontType == ft_encrypted2)) {
398
 
                int index;
399
 
 
400
 
                for (index = 0;
401
 
                    (font->procs.enumerate_glyph((gs_font *)font, &index,
402
 
                    (GLYPH_SPACE_NAME), &glyph)) >= 0 &&
403
 
                    index != 0;) {
404
 
 
405
 
                    if (gs_font_glyph_is_notdef(font, glyph)) {
406
 
                        code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
407
 
                                            GLYPH_INFO_WIDTH0 << WMode,
408
 
                                            &info);
409
 
 
410
 
                    if (code < 0)
411
 
                        return code;
412
 
                    }
413
 
                    break;
414
 
                }
415
 
            }
416
 
            if (code < 0)
417
 
                return code;
418
 
        }
419
 
        gs_point_transform(font->FontBBox.p.x, font->FontBBox.p.y, &m, &p0);
420
 
        gs_point_transform(font->FontBBox.p.x, font->FontBBox.q.y, &m, &p1);
421
 
        gs_point_transform(font->FontBBox.q.x, font->FontBBox.p.y, &m, &p2);
422
 
        gs_point_transform(font->FontBBox.q.x, font->FontBBox.q.y, &m, &p3);
423
 
        bbox.p.x = min(min(p0.x, p1.x), min(p1.x, p2.x)) + total.x;
424
 
        bbox.p.y = min(min(p0.y, p1.y), min(p1.y, p2.y)) + total.y;
425
 
        bbox.q.x = max(max(p0.x, p1.x), max(p1.x, p2.x)) + total.x;
426
 
        bbox.q.y = max(max(p0.y, p1.y), max(p1.y, p2.y)) + total.y;
427
 
        if (i == 0)
428
 
            *text_bbox = bbox;
429
 
        else
430
 
            rect_merge(*text_bbox, bbox);
431
 
        if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
432
 
            gs_text_replaced_width(&pte->text, xy_index++, &tpt);
433
 
            gs_distance_transform(tpt.x, tpt.y, &ctm_only(pte->pis), &wanted);
434
 
        } else {
435
 
            gs_distance_transform(info.width[WMode].x,
436
 
                                  info.width[WMode].y,
437
 
                                  &m, &wanted);
438
 
            if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
439
 
                gs_distance_transform(pte->text.delta_all.x,
440
 
                                      pte->text.delta_all.y,
441
 
                                      &ctm_only(pte->pis), &tpt);
442
 
                wanted.x += tpt.x;
443
 
                wanted.y += tpt.y;
444
 
            }
445
 
            if (pstr->data[i] == space_char && pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
446
 
                gs_distance_transform(pte->text.delta_space.x,
447
 
                                      pte->text.delta_space.y,
448
 
                                      &ctm_only(pte->pis), &tpt);
449
 
                wanted.x += tpt.x;
450
 
                wanted.y += tpt.y;
451
 
            }
452
 
        }
453
 
        total.x += wanted.x;
454
 
        total.y += wanted.y;
455
 
    }
456
 
    *pdpt = total;
457
 
    return 0;
458
 
}
459
 
 
460
 
void
461
 
adjust_first_last_char(pdf_font_resource_t *pdfont, byte *str, int size)
462
 
{
463
 
    int i;
464
 
 
465
 
    for (i = 0; i < size; ++i) {
466
 
        int chr = str[i];
467
 
 
468
 
        if (chr < pdfont->u.simple.FirstChar)
469
 
            pdfont->u.simple.FirstChar = chr;
470
 
        if (chr > pdfont->u.simple.LastChar)
471
 
            pdfont->u.simple.LastChar = chr;
472
 
    }
473
 
}
474
 
 
475
 
int
476
 
pdf_shift_text_currentpoint(pdf_text_enum_t *penum, gs_point *wpt)
477
 
{
478
 
    gs_state *pgs;
479
 
    extern_st(st_gs_state);
480
 
 
481
 
    if (gs_object_type(penum->dev->memory, penum->pis) != &st_gs_state) {
482
 
        /* Probably never happens. Not sure though. */
483
 
        return_error(gs_error_unregistered);
484
 
    }
485
 
    pgs = (gs_state *)penum->pis;
486
 
    return gs_moveto_aux(penum->pis, gx_current_path(pgs),
487
 
                              fixed2float(penum->origin.x) + wpt->x,
488
 
                              fixed2float(penum->origin.y) + wpt->y);
489
 
}
490
 
 
491
 
/*
492
 
 * Internal procedure to process a string in a non-composite font.
493
 
 * Doesn't use or set pte->{data,size,index}; may use/set pte->xy_index;
494
 
 * may set penum->returned.total_width.  Sets ppts->values.
495
 
 *
496
 
 * Note that the caller is responsible for re-encoding the string, if
497
 
 * necessary; for adding Encoding entries in pdfont; and for copying any
498
 
 * necessary glyphs.  penum->current_font provides the gs_font for getting
499
 
 * glyph metrics, but this font's Encoding is not used.
500
 
 */
501
 
static int process_text_return_width(const pdf_text_enum_t *pte,
502
 
                                      gs_font_base *font,
503
 
                                      pdf_text_process_state_t *ppts,
504
 
                                      const gs_const_string *pstr, const gs_glyph *gdata,
505
 
                                      gs_point *pdpt, int *accepted);
506
 
static int
507
 
pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr,
508
 
                   const gs_matrix *pfmat,
509
 
                   pdf_text_process_state_t *ppts, const gs_glyph *gdata)
510
 
{
511
 
    gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
512
 
    gs_font_base *font = (gs_font_base *)penum->current_font;
513
 
    pdf_font_resource_t *pdfont;
514
 
    const gs_text_params_t *text = &penum->text;
515
 
    int code = 0, mask;
516
 
    gs_point width_pt;
517
 
    int accepted;
518
 
 
519
 
    code = pdf_obtain_font_resource(penum, pstr, &pdfont);
520
 
    if (code < 0)
521
 
        return code;
522
 
    if (pfmat == 0)
523
 
        pfmat = &font->FontMatrix;
524
 
    if (text->operation & TEXT_RETURN_WIDTH) {
525
 
        code = gx_path_current_point(penum->path, &penum->origin);
526
 
        if (code < 0)
527
 
            return code;
528
 
    }
529
 
    if (text->size == 0)
530
 
        return 0;
531
 
    if (penum->pis->text_rendering_mode != 3 && !(text->operation & TEXT_DO_NONE)) {
532
 
        /*
533
 
         * Acrobat Reader can't handle text with huge coordinates,
534
 
         * so skip the text if it is outside the clip bbox
535
 
         * (Note : it ever fails with type 3 fonts).
536
 
         */
537
 
        gs_rect text_bbox = {{0, 0}, {0, 0}};
538
 
 
539
 
        code = process_text_estimate_bbox(penum, font, (gs_const_string *)pstr, pfmat,
540
 
                                          &text_bbox, &width_pt);
541
 
        if (code == 0) {
542
 
            gs_fixed_rect clip_bbox;
543
 
            gs_rect rect;
544
 
 
545
 
            gx_cpath_outer_box(penum->pcpath, &clip_bbox);
546
 
            rect.p.x = fixed2float(clip_bbox.p.x);
547
 
            rect.p.y = fixed2float(clip_bbox.p.y);
548
 
            rect.q.x = fixed2float(clip_bbox.q.x);
549
 
            rect.q.y = fixed2float(clip_bbox.q.y);
550
 
            rect_intersect(rect, text_bbox);
551
 
            if (rect.p.x > rect.q.x || rect.p.y > rect.q.y) {
552
 
                penum->index += pstr->size;
553
 
                goto finish;
554
 
            }
555
 
        }
556
 
    } else {
557
 
        /* We have no penum->pcpath. */
558
 
    }
559
 
 
560
 
    /*
561
 
     * Note that pdf_update_text_state sets all the members of ppts->values
562
 
     * to their current values.
563
 
     */
564
 
    code = pdf_update_text_state(ppts, penum, pdfont, pfmat);
565
 
    if (code > 0) {
566
 
        /* Try not to emulate ADD_TO_WIDTH if we don't have to. */
567
 
        if (code & TEXT_ADD_TO_SPACE_WIDTH) {
568
 
            if (!memchr(pstr->data, penum->text.space.s_char, pstr->size))
569
 
                code &= ~TEXT_ADD_TO_SPACE_WIDTH;
570
 
        }
571
 
    }
572
 
    if (code < 0)
573
 
        return code;
574
 
    mask = code;
575
 
 
576
 
    if (text->operation & TEXT_REPLACE_WIDTHS)
577
 
        mask |= TEXT_REPLACE_WIDTHS;
578
 
 
579
 
    /*
580
 
     * The only operations left to handle are TEXT_DO_DRAW and
581
 
     * TEXT_RETURN_WIDTH.
582
 
     */
583
 
    if (mask == 0) {
584
 
        /*
585
 
         * If any character has real_width != Width, we have to process
586
 
         * the string character-by-character.  process_text_return_width
587
 
         * will tell us what we need to know.
588
 
         */
589
 
        if (!(text->operation & (TEXT_DO_DRAW | TEXT_RETURN_WIDTH)))
590
 
            return 0;
591
 
        code = process_text_return_width(penum, font, ppts,
592
 
                                         (gs_const_string *)pstr, gdata,
593
 
                                         &width_pt, &accepted);
594
 
        if (code < 0)
595
 
            return code;
596
 
        if (code == 0) {
597
 
            /* No characters with redefined widths -- the fast case. */
598
 
            if (text->operation & TEXT_DO_DRAW || penum->pis->text_rendering_mode == 3) {
599
 
                code = pdf_append_chars(pdev, pstr->data, accepted,
600
 
                                        width_pt.x, width_pt.y, false);
601
 
                if (code < 0)
602
 
                    return code;
603
 
                adjust_first_last_char(pdfont, pstr->data, accepted);
604
 
                penum->index += accepted;
605
 
            } else if (text->operation & TEXT_DO_NONE)
606
 
                penum->index += accepted;
607
 
        } else {
608
 
            /* Use the slow case.  Set mask to any non-zero value. */
609
 
            mask = TEXT_RETURN_WIDTH;
610
 
        }
611
 
    }
612
 
    if (mask) {
613
 
        /* process_text_modify_width destroys text parameters, save them now. */
614
 
        int index0 = penum->index, xy_index = penum->xy_index;
615
 
        gs_text_params_t text = penum->text;
616
 
        int xy_index_step = (!(penum->text.operation & TEXT_REPLACE_WIDTHS) ? 0 :
617
 
                             penum->text.x_widths == penum->text.y_widths ? 2 : 1);
618
 
        /* A glyphshow takes a shortcut by storing the single glyph directly into
619
 
         * penum->text.data.d_glyph. However, process_text_modify_width
620
 
         * replaces pte->text.data.bytes (these two are part of a union) with
621
 
         * pstr->data, which is not valid for a glyphshow because it alters
622
 
         * the glyph value store there. If we make a copy of the single glyph,
623
 
         * it all works correctly.then
624
 
         */
625
 
        gs_glyph gdata_i, *gdata_p = (gs_glyph *)gdata;
626
 
        if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
627
 
            gdata_i = *gdata;
628
 
            gdata_p = &gdata_i;
629
 
        }
630
 
 
631
 
        if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
632
 
            if (penum->text.x_widths != NULL)
633
 
                penum->text.x_widths += xy_index * xy_index_step;
634
 
            if (penum->text.y_widths != NULL)
635
 
                penum->text.y_widths += xy_index * xy_index_step;
636
 
        }
637
 
        penum->xy_index = 0;
638
 
        code = process_text_modify_width(penum, (gs_font *)font, ppts,
639
 
                                         (gs_const_string *)pstr,
640
 
                                         &width_pt, (const gs_glyph *)gdata_p, false);
641
 
        if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
642
 
            if (penum->text.x_widths != NULL)
643
 
                penum->text.x_widths -= xy_index * xy_index_step;
644
 
            if (penum->text.y_widths != NULL)
645
 
                penum->text.y_widths -= xy_index * xy_index_step;
646
 
        }
647
 
        penum->xy_index += xy_index;
648
 
        adjust_first_last_char(pdfont, pstr->data, penum->index);
649
 
        penum->text = text;
650
 
        penum->index += index0;
651
 
        if (code < 0)
652
 
            return code;
653
 
    }
654
 
 
655
 
finish:
656
 
    /* Finally, return the total width if requested. */
657
 
    if (!(text->operation & TEXT_RETURN_WIDTH))
658
 
        return 0;
659
 
    if (text->operation & TEXT_DO_NONE) {
660
 
        /* stringwidth needs to transform to user space. */
661
 
        gs_point p;
662
 
 
663
 
        gs_distance_transform_inverse(width_pt.x, width_pt.y, &ctm_only(penum->pis), &p);
664
 
        penum->returned.total_width.x += p.x;
665
 
        penum->returned.total_width.y += p.y;
666
 
    } else
667
 
        penum->returned.total_width = width_pt;
668
 
    return pdf_shift_text_currentpoint(penum, &width_pt);
669
 
}
670
 
 
671
 
/*
672
 
 * Get the widths (unmodified and possibly modified) of a given character
673
 
 * in a simple font.  May add the widths to the widths cache (pdfont->Widths
674
 
 * and pdf_font_cache_elem::real_widths).  Return 1 if the widths were not cached.
675
 
 */
676
 
static int
677
 
pdf_char_widths(gx_device_pdf *const pdev,
678
 
                pdf_font_resource_t *pdfont, int ch, gs_font_base *font,
679
 
                pdf_glyph_widths_t *pwidths /* may be NULL */)
680
 
{
681
 
    pdf_glyph_widths_t widths;
682
 
    int code;
683
 
    byte *glyph_usage;
684
 
    double *real_widths;
685
 
    int char_cache_size, width_cache_size;
686
 
    pdf_font_resource_t *pdfont1;
687
 
 
688
 
    code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont1,
689
 
                                &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
690
 
    if (code < 0)
691
 
        return code;
692
 
    if (pdfont1 != pdfont)
693
 
        return_error(gs_error_unregistered); /* Must not happen. */
694
 
    if (ch < 0 || ch > 255)
695
 
        return_error(gs_error_rangecheck);
696
 
    if (ch >= width_cache_size)
697
 
        return_error(gs_error_unregistered); /* Must not happen. */
698
 
    if (pwidths == 0)
699
 
        pwidths = &widths;
700
 
    if ((font->FontType != ft_user_defined &&
701
 
        font->FontType != ft_PCL_user_defined &&
702
 
        font->FontType != ft_GL2_stick_user_defined &&
703
 
        font->FontType != ft_GL2_531) && real_widths[ch] == 0) {
704
 
        /* Might be an unused char, or just not cached. */
705
 
        gs_glyph glyph = pdfont->u.simple.Encoding[ch].glyph;
706
 
 
707
 
        code = pdf_glyph_widths(pdfont, font->WMode, glyph, (gs_font *)font, pwidths, NULL);
708
 
        if (code < 0)
709
 
            return code;
710
 
        if (font->WMode != 0 && code > 0 && !pwidths->replaced_v) {
711
 
            /*
712
 
             * The font has no Metrics2, so it must write
713
 
             * horizontally due to PS spec.
714
 
             * Therefore we need to fill the Widths array,
715
 
             * which is required by PDF spec.
716
 
             * Take it from WMode==0.
717
 
             */
718
 
            code = pdf_glyph_widths(pdfont, 0, glyph, (gs_font *)font, pwidths, NULL);
719
 
        }
720
 
        if (pwidths->replaced_v) {
721
 
            pdfont->u.simple.v[ch].x = pwidths->real_width.v.x - pwidths->Width.v.x;
722
 
            pdfont->u.simple.v[ch].y = pwidths->real_width.v.y - pwidths->Width.v.y;
723
 
        } else
724
 
            pdfont->u.simple.v[ch].x = pdfont->u.simple.v[ch].y = 0;
725
 
        if (code == 0) {
726
 
            pdfont->Widths[ch] = pwidths->Width.w;
727
 
            real_widths[ch] = pwidths->real_width.w;
728
 
        } else {
729
 
            if (font->WMode == 0 && !pwidths->replaced_v)
730
 
                pdfont->Widths[ch] = pwidths->real_width.w;
731
 
        }
732
 
    } else {
733
 
        if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
734
 
            font->FontType == ft_GL2_stick_user_defined || font->FontType == ft_GL2_531) {
735
 
            if (!(pdfont->used[ch >> 3] & 0x80 >> (ch & 7)))
736
 
                return gs_error_undefined; /* The charproc was not accumulated. */
737
 
            if (!pdev->charproc_just_accumulated &&
738
 
                !(pdfont->u.simple.s.type3.cached[ch >> 3] & 0x80 >> (ch & 7))) {
739
 
                 /* The charproc uses setcharwidth.
740
 
                    Need to accumulate again to check for a glyph variation. */
741
 
                return gs_error_undefined;
742
 
            }
743
 
        }
744
 
        pwidths->Width.w = pdfont->Widths[ch];
745
 
        pwidths->Width.v = pdfont->u.simple.v[ch];
746
 
        if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
747
 
            font->FontType == ft_GL2_stick_user_defined || font->FontType == ft_GL2_531) {
748
 
            pwidths->real_width.w = real_widths[ch * 2];
749
 
            pwidths->Width.xy.x = pwidths->Width.w;
750
 
            pwidths->Width.xy.y = 0;
751
 
            pwidths->real_width.xy.x = real_widths[ch * 2 + 0];
752
 
            pwidths->real_width.xy.y = real_widths[ch * 2 + 1];
753
 
            pwidths->replaced_v = 0;
754
 
        } else if (font->WMode) {
755
 
            pwidths->real_width.w = real_widths[ch];
756
 
            pwidths->Width.xy.x = 0;
757
 
            pwidths->Width.xy.y = pwidths->Width.w;
758
 
            pwidths->real_width.xy.x = 0;
759
 
            pwidths->real_width.xy.y = pwidths->real_width.w;
760
 
        } else {
761
 
            pwidths->real_width.w = real_widths[ch];
762
 
            pwidths->Width.xy.x = pwidths->Width.w;
763
 
            pwidths->Width.xy.y = 0;
764
 
            pwidths->real_width.xy.x = pwidths->real_width.w;
765
 
            pwidths->real_width.xy.y = 0;
766
 
        }
767
 
        code = 0;
768
 
    }
769
 
    return code;
770
 
}
771
 
 
772
 
/*
773
 
 * Convert glyph widths (.Width.xy and .real_widths.xy) from design to PDF text space
774
 
 * Zero-out one of Width.xy.x/y per PDF Ref 5.3.3 "Text Space Details"
775
 
 */
776
 
static void
777
 
pdf_char_widths_to_uts(pdf_font_resource_t *pdfont /* may be NULL for non-Type3 */,
778
 
                       pdf_glyph_widths_t *pwidths)
779
 
{
780
 
    if (pdfont && (pdfont->FontType == ft_user_defined ||
781
 
        pdfont->FontType == ft_PCL_user_defined ||
782
 
        pdfont->FontType == ft_GL2_stick_user_defined ||
783
 
        pdfont->FontType == ft_GL2_531)) {
784
 
        gs_matrix *pmat = &pdfont->u.simple.s.type3.FontMatrix;
785
 
 
786
 
        pwidths->Width.xy.x *= pmat->xx; /* formula simplified based on wy in glyph space == 0 */
787
 
        pwidths->Width.xy.y  = 0.0; /* WMode == 0 for PDF Type 3 fonts */
788
 
        gs_distance_transform(pwidths->real_width.xy.x, pwidths->real_width.xy.y, pmat, &pwidths->real_width.xy);
789
 
    } else {
790
 
        /*
791
 
         * For other font types:
792
 
         * - PDF design->text space is a simple scaling by 0.001.
793
 
         * - The Width.xy.x/y that should be zeroed-out per 5.3.3 "Text Space Details" is already 0.
794
 
         */
795
 
        pwidths->Width.xy.x /= 1000.0;
796
 
        pwidths->Width.xy.y /= 1000.0;
797
 
        pwidths->real_width.xy.x /= 1000.0;
798
 
        pwidths->real_width.xy.y /= 1000.0;
799
 
    }
800
 
}
801
 
 
802
 
/*
803
 
 * Compute the total text width (in user space).  Return 1 if any
804
 
 * character had real_width != Width, otherwise 0.
805
 
 */
806
 
static int
807
 
process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font,
808
 
                          pdf_text_process_state_t *ppts,
809
 
                          const gs_const_string *pstr, const gs_glyph *gdata,
810
 
                          gs_point *pdpt, int *accepted)
811
 
{
812
 
    int i;
813
 
    gs_point w;
814
 
    gs_point dpt;
815
 
    int num_spaces = 0;
816
 
    int space_char =
817
 
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
818
 
         pte->text.space.s_char : -1);
819
 
    int widths_differ = 0, code;
820
 
    gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
821
 
    pdf_font_resource_t *pdfont;
822
 
 
823
 
    code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont, NULL, NULL, NULL, NULL);
824
 
    if (code < 0)
825
 
        return code;
826
 
    for (i = 0, w.x = w.y = 0; i < pstr->size; ++i) {
827
 
        pdf_glyph_widths_t cw; /* in PDF text space */
828
 
        gs_char ch = pstr->data[i];
829
 
 
830
 
        {  const gs_glyph *gdata_i = (gdata != NULL ? gdata + i : 0);
831
 
 
832
 
            code = pdf_encode_string_element(pdev, (gs_font *)font, pdfont, ch, gdata_i);
833
 
            if (code < 0)
834
 
                return code;
835
 
        }
836
 
        if ((font->FontType == ft_user_defined ||
837
 
            font->FontType == ft_PCL_user_defined ||
838
 
            font->FontType == ft_GL2_stick_user_defined ||
839
 
            font->FontType == ft_GL2_531) &&
840
 
            (i > 0 || !pdev->charproc_just_accumulated) &&
841
 
            !(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))){
842
 
            code = gs_error_undefined;
843
 
        }
844
 
        else {
845
 
            if (font->FontType == ft_PCL_user_defined) {
846
 
                /* Check the cache, if the glyph has been flushed, assume that
847
 
                 * it has been redefined, and do not use the current glyph.
848
 
                 * Additional code in pdf_text_process will also spot this
849
 
                 * condition and will not capture the glyph in this font.
850
 
                 */
851
 
                /* Cache checking code copied from gxchar.c, show_proceed,
852
 
                 * case 0, 'plain char'.
853
 
                 */
854
 
                gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
855
 
                gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
856
 
                    pte->fstack.items[pte->fstack.depth].font);
857
 
                int wmode = rfont->WMode;
858
 
                gs_log2_scale_point log2_scale = {0,0};
859
 
                gs_fixed_point subpix_origin = {0,0};
860
 
                cached_fm_pair *pair;
861
 
 
862
 
                code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pis), &log2_scale,
863
 
                    false, &pair);
864
 
                if (code < 0)
865
 
                    return code;
866
 
                if (gx_lookup_cached_char(pfont, pair, ch, wmode,
867
 
                    1, &subpix_origin) == 0) {
868
 
                        /* Character is not in cache, must have been redefined. */
869
 
                    code = gs_error_undefined;
870
 
                }
871
 
                else {
872
 
                    /* Character is in cache, go ahead and use it */
873
 
                    code = pdf_char_widths((gx_device_pdf *)pte->dev,
874
 
                                   ppts->values.pdfont, ch, font, &cw);
875
 
                }
876
 
            } else
877
 
                /* Not a PCL bitmap font, we don't need to worry about redefined glyphs */
878
 
                code = pdf_char_widths((gx_device_pdf *)pte->dev,
879
 
                                   ppts->values.pdfont, ch, font, &cw);
880
 
        }
881
 
        if (code < 0) {
882
 
            if (i)
883
 
                break;
884
 
            *accepted = 0;
885
 
            return code;
886
 
        }
887
 
        pdf_char_widths_to_uts(pdfont, &cw);
888
 
        w.x += cw.real_width.xy.x;
889
 
        w.y += cw.real_width.xy.y;
890
 
        if (cw.real_width.xy.x != cw.Width.xy.x ||
891
 
            cw.real_width.xy.y != cw.Width.xy.y
892
 
            )
893
 
            widths_differ = 1;
894
 
        if (pstr->data[i] == space_char)
895
 
            ++num_spaces;
896
 
    }
897
 
    *accepted = i;
898
 
    gs_distance_transform(w.x * ppts->values.size, w.y * ppts->values.size,
899
 
                          &ppts->values.matrix, &dpt);
900
 
    if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
901
 
        int num_chars = *accepted;
902
 
        gs_point tpt;
903
 
 
904
 
        gs_distance_transform(pte->text.delta_all.x, pte->text.delta_all.y,
905
 
                              &ctm_only(pte->pis), &tpt);
906
 
        dpt.x += tpt.x * num_chars;
907
 
        dpt.y += tpt.y * num_chars;
908
 
    }
909
 
    if (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
910
 
        gs_point tpt;
911
 
 
912
 
        gs_distance_transform(pte->text.delta_space.x, pte->text.delta_space.y,
913
 
                              &ctm_only(pte->pis), &tpt);
914
 
        dpt.x += tpt.x * num_spaces;
915
 
        dpt.y += tpt.y * num_spaces;
916
 
    }
917
 
    *pdpt = dpt;
918
 
 
919
 
    return widths_differ;
920
 
}
921
 
 
922
 
#ifdef DEPRECATED_906
923
 
/*
924
 
 * Retrieve glyph origing shift for WMode = 1 in design units.
925
 
 */
926
 
static void
927
 
pdf_glyph_origin(pdf_font_resource_t *pdfont, int ch, int WMode, gs_point *p)
928
 
{
929
 
    /* For CID fonts PDF viewers provide glyph origin shift automatically.
930
 
     * Therefore we only need to do for non-CID fonts.
931
 
     */
932
 
    switch (pdfont->FontType) {
933
 
        case ft_encrypted:
934
 
        case ft_encrypted2:
935
 
        case ft_TrueType:
936
 
        case ft_user_defined:
937
 
            *p = pdfont->u.simple.v[ch];
938
 
            break;
939
 
        default:
940
 
            p->x = p->y = 0;
941
 
            break;
942
 
    }
943
 
}
944
 
#endif
945
 
 
946
 
/*
947
 
 * Emulate TEXT_ADD_TO_ALL_WIDTHS and/or TEXT_ADD_TO_SPACE_WIDTH,
948
 
 * and implement TEXT_REPLACE_WIDTHS if requested.
949
 
 * Uses and updates ppts->values.matrix; uses ppts->values.pdfont.
950
 
 *
951
 
 * Destroys the text parameters in *pte.
952
 
 * The caller must restore them.
953
 
 */
954
 
int
955
 
process_text_modify_width(pdf_text_enum_t *pte, gs_font *font,
956
 
                          pdf_text_process_state_t *ppts,
957
 
                          const gs_const_string *pstr,
958
 
                          gs_point *pdpt, const gs_glyph *gdata, bool composite)
959
 
{
960
 
    gx_device_pdf *const pdev = (gx_device_pdf *)pte->dev;
961
 
    int space_char =
962
 
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
963
 
         pte->text.space.s_char : -1);
964
 
    gs_point start, total;
965
 
    pdf_font_resource_t *pdfont3 = NULL;
966
 
    int code;
967
 
 
968
 
    if (font->FontType == ft_user_defined ||
969
 
        font->FontType == ft_PCL_user_defined ||
970
 
        font->FontType == ft_GL2_stick_user_defined ||
971
 
        font->FontType == ft_GL2_531) {
972
 
        code = pdf_attached_font_resource(pdev, font, &pdfont3, NULL, NULL, NULL, NULL);
973
 
        if (code < 0)
974
 
            return code;
975
 
 
976
 
    }
977
 
    pte->text.data.bytes = pstr->data;
978
 
    pte->text.size = pstr->size;
979
 
    pte->index = 0;
980
 
    pte->text.operation &= ~TEXT_FROM_ANY;
981
 
    pte->text.operation |= TEXT_FROM_STRING;
982
 
    start.x = ppts->values.matrix.tx;
983
 
    start.y = ppts->values.matrix.ty;
984
 
    total.x = total.y = 0;      /* user space */
985
 
    /*
986
 
     * Note that character widths are in design space, but text.delta_*
987
 
     * values and the width value returned in *pdpt are in user space,
988
 
     * and the width values for pdf_append_chars are in device space.
989
 
     */
990
 
    for (;;) {
991
 
        pdf_glyph_widths_t cw;  /* design space, then converted to PDF text space */
992
 
        gs_point did, wanted, tpt;      /* user space */
993
 
        gs_point v = {0, 0}; /* design space */
994
 
        gs_char chr;
995
 
        gs_glyph glyph;
996
 
        int index = pte->index;
997
 
        gs_text_enum_t pte1 = *(gs_text_enum_t *)pte;
998
 
        int FontType;
999
 
        bool use_cached_v = true;
1000
 
        byte composite_type3_text[1];
1001
 
 
1002
 
        code = pte1.orig_font->procs.next_char_glyph(&pte1, &chr, &glyph);
1003
 
        if (code == 2) { /* end of string */
1004
 
            gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true);
1005
 
            break;
1006
 
        }
1007
 
        if (code < 0)
1008
 
            return code;
1009
 
        if (composite) { /* from process_cmap_text */
1010
 
            gs_font *subfont = pte1.fstack.items[pte1.fstack.depth].font;
1011
 
 
1012
 
            if (subfont->FontType == ft_user_defined) {
1013
 
                pdf_font_resource_t *pdfont;
1014
 
 
1015
 
                FontType = subfont->FontType;
1016
 
                code = pdf_attached_font_resource(pdev, subfont,
1017
 
                            &pdfont, NULL, NULL, NULL, NULL);
1018
 
                if (code < 0)
1019
 
                    return code;
1020
 
                chr = pdf_find_glyph(pdfont, glyph);
1021
 
                composite_type3_text[0] = (byte)chr;
1022
 
                code = pdf_char_widths((gx_device_pdf *)pte->dev,
1023
 
                                       ppts->values.pdfont, chr, (gs_font_base *)subfont,
1024
 
                                       &cw);
1025
 
            } else {
1026
 
                pdf_font_resource_t *pdsubf = ppts->values.pdfont->u.type0.DescendantFont;
1027
 
 
1028
 
                FontType = pdsubf->FontType;
1029
 
                code = pdf_glyph_widths(pdsubf, font->WMode, glyph, subfont, &cw,
1030
 
                    pte->cdevproc_callout ? pte->cdevproc_result : NULL);
1031
 
            }
1032
 
        } else {/* must be a base font */
1033
 
            const gs_glyph *gdata_i = (gdata != NULL ? gdata + pte->index : 0);
1034
 
 
1035
 
                /* gdata is NULL when composite == true, or the text isn't a single byte.  */
1036
 
            code = pdf_encode_string_element(pdev, font, ppts->values.pdfont, chr, gdata_i);
1037
 
            FontType = font->FontType;
1038
 
            if (code >= 0) {
1039
 
                if (chr == GS_NO_CHAR && glyph != GS_NO_GLYPH) {
1040
 
                    /* glyphshow, we have no char code. Bug 686988.*/
1041
 
                    code = pdf_glyph_widths(ppts->values.pdfont, font->WMode, glyph, font, &cw, NULL);
1042
 
                    use_cached_v = false; /* Since we have no chr and don't call pdf_char_widths. */
1043
 
                } else {
1044
 
                    code = pdf_char_widths((gx_device_pdf *)pte->dev,
1045
 
                                       ppts->values.pdfont, chr, (gs_font_base *)font,
1046
 
                                       &cw);
1047
 
                    if (code == 0 && font->FontType == ft_PCL_user_defined) {
1048
 
                        /* Check the cache, if the glyph has been flushed, assume that
1049
 
                         * it has been redefined, and do not use the current glyph.
1050
 
                         * Additional code in pdf_text_process will also spot this
1051
 
                         * condition and will not capture the glyph in this font.
1052
 
                         */
1053
 
                        /* Cache checking code copied from gxchar.c, show_proceed,
1054
 
                         * case 0, 'plain char'.
1055
 
                         */
1056
 
                        gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
1057
 
                        gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
1058
 
                            pte->fstack.items[pte->fstack.depth].font);
1059
 
                        int wmode = rfont->WMode;
1060
 
                        gs_log2_scale_point log2_scale = {0,0};
1061
 
                        gs_fixed_point subpix_origin = {0,0};
1062
 
                        cached_fm_pair *pair;
1063
 
 
1064
 
                        code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pis), &log2_scale,
1065
 
                            false, &pair);
1066
 
                        if (code < 0)
1067
 
                            return code;
1068
 
                        if (gx_lookup_cached_char(pfont, pair, chr, wmode,
1069
 
                            1, &subpix_origin) == 0) {
1070
 
                        /* Character is not in cache, must have been redefined. */
1071
 
                            code = gs_error_undefined;
1072
 
                        }
1073
 
                    }
1074
 
                }
1075
 
            }
1076
 
        }
1077
 
        if (code < 0) {
1078
 
            if (index > 0)
1079
 
                break;
1080
 
            return code;
1081
 
        }
1082
 
        gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true);
1083
 
        if (composite || !use_cached_v) {
1084
 
            if (cw.replaced_v) {
1085
 
                v.x = cw.real_width.v.x - cw.Width.v.x;
1086
 
                v.y = cw.real_width.v.y - cw.Width.v.y;
1087
 
            }
1088
 
        } else
1089
 
            v = ppts->values.pdfont->u.simple.v[chr];
1090
 
        if (font->WMode) {
1091
 
            /* With WMode 1 v-vector is (WMode 1 origin) - (WMode 0 origin).
1092
 
               The glyph shifts in the opposite direction.  */
1093
 
            v.x = - v.x;
1094
 
            v.y = - v.y;
1095
 
        } else {
1096
 
            /* With WMode 0 v-vector is (Metrics sb) - (native sb).
1097
 
               The glyph shifts in same direction.  */
1098
 
        }
1099
 
        /* pdf_glyph_origin is not longer used. */
1100
 
        if (v.x != 0 || v.y != 0) {
1101
 
            gs_point glyph_origin_shift;
1102
 
            double scale0;
1103
 
 
1104
 
            if (FontType == ft_TrueType || FontType == ft_CID_TrueType)
1105
 
                scale0 = (float)0.001;
1106
 
            else
1107
 
                scale0 = 1;
1108
 
            glyph_origin_shift.x = v.x * scale0;
1109
 
            glyph_origin_shift.y = v.y * scale0;
1110
 
            if (composite) {
1111
 
                gs_font *subfont = pte->fstack.items[pte->fstack.depth].font;
1112
 
 
1113
 
                gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1114
 
                                      &subfont->FontMatrix, &glyph_origin_shift);
1115
 
            }
1116
 
            gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1117
 
                                  &font->FontMatrix, &glyph_origin_shift);
1118
 
            gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1119
 
                                  &ctm_only(pte->pis), &glyph_origin_shift);
1120
 
            if (glyph_origin_shift.x != 0 || glyph_origin_shift.y != 0) {
1121
 
                ppts->values.matrix.tx = start.x + total.x + glyph_origin_shift.x;
1122
 
                ppts->values.matrix.ty = start.y + total.y + glyph_origin_shift.y;
1123
 
                code = pdf_set_text_state_values(pdev, &ppts->values);
1124
 
                if (code < 0)
1125
 
                    break;
1126
 
            }
1127
 
        }
1128
 
        pdf_char_widths_to_uts(pdfont3, &cw); /* convert design->text space */
1129
 
        if (pte->text.operation & (TEXT_DO_DRAW | TEXT_RENDER_MODE_3)) {
1130
 
            gs_distance_transform(cw.Width.xy.x * ppts->values.size,
1131
 
                                  cw.Width.xy.y * ppts->values.size,
1132
 
                                  &ppts->values.matrix, &did);
1133
 
            gs_distance_transform((font->WMode ? 0 : ppts->values.character_spacing),
1134
 
                                  (font->WMode ? ppts->values.character_spacing : 0),
1135
 
                                  &ppts->values.matrix, &tpt);
1136
 
            did.x += tpt.x;
1137
 
            did.y += tpt.y;
1138
 
            if (chr == space_char) {
1139
 
                gs_distance_transform((font->WMode ? 0 : ppts->values.word_spacing),
1140
 
                                      (font->WMode ? ppts->values.word_spacing : 0),
1141
 
                                      &ppts->values.matrix, &tpt);
1142
 
                did.x += tpt.x;
1143
 
                did.y += tpt.y;
1144
 
            }
1145
 
            if (composite && FontType == ft_user_defined)
1146
 
                code = pdf_append_chars(pdev, composite_type3_text, 1, did.x, did.y, composite);
1147
 
            else
1148
 
                code = pdf_append_chars(pdev, pstr->data + index, pte->index - index, did.x, did.y, composite);
1149
 
            if (code < 0)
1150
 
                break;
1151
 
        } else
1152
 
            did.x = did.y = 0;
1153
 
        if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
1154
 
            gs_point dpt;
1155
 
 
1156
 
            code = gs_text_replaced_width(&pte->text, pte->xy_index++, &dpt);
1157
 
            if (code < 0)
1158
 
                return_error(gs_error_unregistered);
1159
 
            gs_distance_transform(dpt.x, dpt.y, &ctm_only(pte->pis), &wanted);
1160
 
        } else {
1161
 
            gs_distance_transform(cw.real_width.xy.x * ppts->values.size,
1162
 
                                  cw.real_width.xy.y * ppts->values.size,
1163
 
                                  &ppts->values.matrix, &wanted);
1164
 
            if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
1165
 
                gs_distance_transform(pte->text.delta_all.x,
1166
 
                                      pte->text.delta_all.y,
1167
 
                                      &ctm_only(pte->pis), &tpt);
1168
 
                wanted.x += tpt.x;
1169
 
                wanted.y += tpt.y;
1170
 
            }
1171
 
            if (chr == space_char && pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
1172
 
                gs_distance_transform(pte->text.delta_space.x,
1173
 
                                      pte->text.delta_space.y,
1174
 
                                      &ctm_only(pte->pis), &tpt);
1175
 
                wanted.x += tpt.x;
1176
 
                wanted.y += tpt.y;
1177
 
            }
1178
 
        }
1179
 
        total.x += wanted.x;
1180
 
        total.y += wanted.y;
1181
 
        if (wanted.x != did.x || wanted.y != did.y) {
1182
 
            ppts->values.matrix.tx = start.x + total.x;
1183
 
            ppts->values.matrix.ty = start.y + total.y;
1184
 
            code = pdf_set_text_state_values(pdev, &ppts->values);
1185
 
            if (code < 0)
1186
 
                break;
1187
 
        }
1188
 
        pdev->charproc_just_accumulated = false;
1189
 
    }
1190
 
    *pdpt = total;
1191
 
    return 0;
1192
 
}
1193
 
 
1194
 
/*
1195
 
 * Get character code from a glyph code.
1196
 
 * An usage of this function is very undesirable,
1197
 
 * because a glyph may be unlisted in Encoding.
1198
 
 */
1199
 
int
1200
 
pdf_encode_glyph(gs_font_base *bfont, gs_glyph glyph0,
1201
 
            byte *buf, int buf_size, int *char_code_length)
1202
 
{
1203
 
    gs_char c;
1204
 
 
1205
 
    *char_code_length = 1;
1206
 
    if (*char_code_length > buf_size)
1207
 
        return_error(gs_error_rangecheck); /* Must not happen. */
1208
 
    for (c = 0; c < 255; c++) {
1209
 
        gs_glyph glyph1 = bfont->procs.encode_char((gs_font *)bfont, c,
1210
 
                    GLYPH_SPACE_NAME);
1211
 
        if (glyph1 == glyph0) {
1212
 
            buf[0] = (byte)c;
1213
 
            return 0;
1214
 
        }
1215
 
    }
1216
 
    return_error(gs_error_rangecheck); /* Can't encode. */
1217
 
}
1218
 
 
1219
 
/* ---------------- Type 1 or TrueType font ---------------- */
1220
 
 
1221
 
/*
1222
 
 * Process a text string in a simple font.
1223
 
 */
1224
 
int
1225
 
process_plain_text(gs_text_enum_t *pte, void *vbuf, uint bsize)
1226
 
{
1227
 
    byte *const buf = vbuf;
1228
 
    uint count;
1229
 
    uint operation = pte->text.operation;
1230
 
    pdf_text_enum_t *penum = (pdf_text_enum_t *)pte;
1231
 
    int code;
1232
 
    gs_string str;
1233
 
    pdf_text_process_state_t text_state;
1234
 
    const gs_glyph *gdata = NULL;
1235
 
 
1236
 
    if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) {
1237
 
        count = pte->text.size - pte->index;
1238
 
        if (bsize < count)
1239
 
            return_error(gs_error_unregistered); /* Must not happen. */
1240
 
        memcpy(buf, (const byte *)pte->text.data.bytes + pte->index, count);
1241
 
    } else if (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR)) {
1242
 
        /* Check that all chars fit in a single byte. */
1243
 
        const gs_char *cdata;
1244
 
        int i;
1245
 
 
1246
 
        if (operation & TEXT_FROM_CHARS) {
1247
 
            cdata = pte->text.data.chars;
1248
 
            count = (pte->text.size - pte->index);
1249
 
        } else {
1250
 
            cdata = &pte->text.data.d_char;
1251
 
            count = 1;
1252
 
        }
1253
 
        if (bsize < count * sizeof(gs_char))
1254
 
            return_error(gs_error_unregistered); /* Must not happen. */
1255
 
        for (i = 0; i < count; ++i) {
1256
 
            gs_char chr = cdata[pte->index + i];
1257
 
 
1258
 
            if (chr & ~0xff)
1259
 
                return_error(gs_error_rangecheck);
1260
 
            buf[i] = (byte)chr;
1261
 
        }
1262
 
    } else if (operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH)) {
1263
 
        /*
1264
 
         * Since PDF has no analogue of 'glyphshow',
1265
 
         * we try to encode glyphs with the current
1266
 
         * font's encoding. If the current font has no encoding,
1267
 
         * or the encoding doesn't contain necessary glyphs,
1268
 
         * the text will be represented with a Type 3 font with
1269
 
         * bitmaps or outlines.
1270
 
         *
1271
 
         * When we fail with encoding (136-01.ps is an example),
1272
 
         * we could locate a PDF font resource or create a new one
1273
 
         * with same outlines and an appropriate encoding.
1274
 
         * Also we could change .notdef entries in the
1275
 
         * copied font (assuming that document designer didn't use
1276
 
         * .notdef for a meanful printing).
1277
 
         * fixme: Not implemented yet.
1278
 
         */
1279
 
        gs_font *font = pte->current_font;
1280
 
        uint size;
1281
 
        int i;
1282
 
 
1283
 
        if (operation & TEXT_FROM_GLYPHS) {
1284
 
            gdata = pte->text.data.glyphs;
1285
 
            size = pte->text.size - pte->index;
1286
 
        } else {
1287
 
            gdata = &pte->text.data.d_glyph;
1288
 
            size = 1;
1289
 
        }
1290
 
        if (!pdf_is_simple_font(font))
1291
 
            return_error(gs_error_unregistered); /* Must not happen. */
1292
 
        count = 0;
1293
 
        for (i = 0; i < size; ++i) {
1294
 
            gs_glyph glyph = gdata[pte->index + i];
1295
 
            int char_code_length;
1296
 
 
1297
 
            code = pdf_encode_glyph((gs_font_base *)font, glyph,
1298
 
                         buf + count, size - count, &char_code_length);
1299
 
            if (code < 0)
1300
 
                break;
1301
 
            count += char_code_length;
1302
 
            if (operation & TEXT_INTERVENE)
1303
 
                break; /* Just do one character. */
1304
 
        }
1305
 
        if (i < size) {
1306
 
            pdf_font_resource_t *pdfont;
1307
 
 
1308
 
            str.data = buf;
1309
 
            str.size = size;
1310
 
            code = pdf_obtain_font_resource_unencoded(penum, &str, &pdfont, gdata);
1311
 
            if (code < 0) {
1312
 
                /*
1313
 
                 * pdf_text_process will fall back
1314
 
                 * to default implementation.
1315
 
                 */
1316
 
                return code;
1317
 
            }
1318
 
            count = size;
1319
 
        }
1320
 
        /*  So far we will use TEXT_FROM_STRING instead
1321
 
            TEXT_FROM_*_GLYPH*. Since we used a single
1322
 
            byte encoding, the character index appears invariant
1323
 
            during this substitution.
1324
 
         */
1325
 
    } else
1326
 
        return_error(gs_error_rangecheck);
1327
 
    str.data = buf;
1328
 
    if (count > 1 && (operation & TEXT_INTERVENE)) {
1329
 
        /* Just do one character. */
1330
 
        str.size = 1;
1331
 
        code = pdf_process_string_aux(penum, &str, gdata, NULL, &text_state);
1332
 
        if (code >= 0) {
1333
 
            pte->returned.current_char = buf[0];
1334
 
            code = TEXT_PROCESS_INTERVENE;
1335
 
        }
1336
 
    } else {
1337
 
        str.size = count;
1338
 
        code = pdf_process_string_aux(penum, &str, gdata, NULL, &text_state);
1339
 
    }
1340
 
    return code;
1341
 
}