Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/vector/gdevpdte.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, 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
#include "gximage.h"
43
#include "gxcpath.h"
44
45
#include "gsfcmap.h"
46
#include "tessocr.h"
47
48
static int pdf_char_widths(gx_device_pdf *const pdev,
49
                            pdf_font_resource_t *pdfont, int ch,
50
                            gs_font_base *font,
51
                            pdf_glyph_widths_t *pwidths /* may be NULL */);
52
static int pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr,
53
                               const gs_matrix *pfmat,
54
                               pdf_text_process_state_t *ppts,
55
                               const gs_glyph *gdata);
56
57
/*
58
 * Process a string with a simple gs_font.
59
 */
60
int
61
pdf_process_string_aux(pdf_text_enum_t *penum, gs_string *pstr,
62
                          const gs_glyph *gdata, const gs_matrix *pfmat,
63
                          pdf_text_process_state_t *ppts)
64
1.49M
{
65
1.49M
    gs_font_base *font = (gs_font_base *)penum->current_font;
66
67
1.49M
    switch (font->FontType) {
68
268k
    case ft_TrueType:
69
1.30M
    case ft_encrypted:
70
1.49M
    case ft_encrypted2:
71
1.49M
    case ft_user_defined:
72
1.49M
    case ft_PDF_user_defined:
73
1.49M
    case ft_PCL_user_defined:
74
1.49M
    case ft_GL2_stick_user_defined:
75
1.49M
    case ft_GL2_531:
76
1.49M
    case ft_MicroType:
77
1.49M
        break;
78
0
    default:
79
0
        return_error(gs_error_rangecheck);
80
1.49M
    }
81
1.49M
    return pdf_process_string(penum, pstr, pfmat, ppts, gdata);
82
1.49M
}
83
84
static int OCRText(gx_device_pdf *pdev, gs_glyph glyph, gs_char ch, gs_char *length, byte **unicode)
85
0
{
86
#if OCR_VERSION > 0
87
    int code = 0;
88
89
    if(pdev->OCRStage == OCR_Rendered) {
90
        int llx, lly, urx, ury, char_count = 0, returned_count = 0, *returned;
91
        ocr_glyph_t *next_glyph = pdev->ocr_glyphs;
92
        int rows, stride, row, column;
93
        byte *bitmap = NULL, *src, *dest, *rowptr, srcmask, destmask;
94
        void *state;
95
        const char *language = pdev->ocr_language;
96
        gp_file *DbgFile;
97
98
        if(language == NULL || language[0] == 0)
99
            language = "eng";
100
101
        /* We should alredy have rendered a bitmap for all the glyphs in the
102
         * text operation, so this shuld be redundant, but best to be safe.
103
         */
104
        if(next_glyph == NULL)
105
            return_error(gs_error_unknownerror);
106
107
        /* Identify the bounding box of the returned glyphs by examing the bounds and position
108
         * of each glyph. At the same time count the number of expected returned characters.
109
         * We treat any empty bitmap (all 0x00 bytes) as a space because, obviously, the
110
         * OCR engine can't tell differentiate between a space character and no character at all.
111
         */
112
        llx = next_glyph->x;
113
        lly = next_glyph->y;
114
        urx = llx + next_glyph->width;
115
        ury = lly + next_glyph->height;
116
        if(next_glyph != NULL && !next_glyph->is_space)
117
            char_count++;
118
        next_glyph = (ocr_glyph_t *)next_glyph->next;
119
        while(next_glyph) {
120
            if(!next_glyph->is_space)
121
                char_count++;
122
            if(next_glyph->x < llx)
123
                llx = next_glyph->x;
124
            if(next_glyph->y < lly)
125
                lly = next_glyph->y;
126
            if(next_glyph->x + next_glyph->width > urx)
127
                urx = next_glyph->x + next_glyph->width;
128
            if(next_glyph->y + next_glyph->height > ury)
129
                ury = next_glyph->y + next_glyph->height;
130
            next_glyph = next_glyph->next;
131
        }
132
133
        /* Allocate and initialise the 'strip' bitmap which will receive all the
134
         * individual glyph bitmaps.
135
         */
136
        rows = ury - lly;
137
        stride = (((urx - llx) + 7) / 8) + 1;
138
        bitmap = gs_alloc_bytes(pdev->memory, rows * stride, "working OCR memory");
139
        if(bitmap == NULL)
140
            return_error(gs_error_VMerror);
141
        memset(bitmap, 0x00, rows * stride);
142
143
        /* Allocate a buffer for the OCR engine to return the Unicode code points. This needs work,
144
         * we might want more information returned (bounding boxes and confidence levels) and we
145
         * need to think about the possibility that the OCR engine finds more character than we
146
         * expected (eg fi ligatures returned as 'f' and 'i'.
147
         */
148
        returned = (int *)gs_alloc_bytes(pdev->memory, char_count * sizeof(int), "returned unicodes");
149
        if(returned == NULL) {
150
            gs_free_object(pdev->memory, bitmap, "working OCR memory");
151
            return_error(gs_error_VMerror);
152
        }
153
        memset(returned, 0x00, char_count * sizeof(int));
154
155
        /* Now copy each glyph bitmap to the correct position in the strip. This is complicated
156
         * by the fact that bitmaps are monochrome pcaked into bytes and so the destination
157
         * may not be aligned on a byte boundary.
158
         */
159
        next_glyph = (ocr_glyph_t *)pdev->ocr_glyphs;
160
        while(next_glyph) {
161
            rowptr = bitmap + ((next_glyph->y - lly) * stride) + (int)floor((next_glyph->x - llx) / 8);
162
            for(row = 0;row < next_glyph->height;row++) {
163
                dest = rowptr + row * stride;
164
                src = next_glyph->data + (row * next_glyph->raster);
165
                destmask = 0x80 >> (next_glyph->x - llx) % 8;
166
                srcmask = 0x80;
167
                for(column = 0; column < next_glyph->width;column++) {
168
                    if(*src & srcmask) {
169
                        *dest = *dest | destmask;
170
                    }
171
                    srcmask = srcmask >> 1;
172
                    if(srcmask == 0) {
173
                        srcmask = 0x80;
174
                        src++;
175
                    }
176
                    destmask = destmask >> 1;
177
                    if(destmask == 0) {
178
                        destmask = 0x80;
179
                        dest++;
180
                    }
181
                }
182
            }
183
            next_glyph = next_glyph->next;
184
        }
185
186
#if 0
187
        DbgFile = gp_fopen(pdev->memory, "d:/temp/bits.txt", "wb+");
188
        for(row = 0;row < rows;row++) {
189
            for(column = 0;column < stride;column++) {
190
                dest = bitmap + (row * stride);
191
                gp_fprintf(DbgFile, "%02x", dest[column]);
192
            }
193
            gp_fprintf(DbgFile, "\n");
194
        }
195
        gp_fclose(DbgFile);
196
#endif
197
        /* Initialise the OCR engine */
198
        code = ocr_init_api(pdev->memory->non_gc_memory, language,
199
            pdev->ocr_engine, &state);
200
        if(code < 0) {
201
            gs_free_object(pdev->memory, bitmap, "working OCR memory");
202
            gs_free_object(pdev->memory, returned, "returned unicodes");
203
            return 0;
204
        }
205
        returned_count = char_count;
206
207
        /* Pass our strip to the OCR engine */
208
        code = ocr_bitmap_to_unicodes(state,
209
            bitmap, 0, stride * 8, rows, stride,
210
            (int)pdev->HWResolution[0],
211
            (int)pdev->HWResolution[1],
212
            returned, &returned_count);
213
214
        /* and close the engine back down again */
215
        ocr_fin_api(pdev->memory->non_gc_memory, state);
216
        gs_free_object(pdev->memory, bitmap, "working OCR memory");
217
218
        if(code < 0) {
219
            pdev->OCRStage = OCR_Failed;
220
            gs_free_object(pdev->memory, returned, "returned unicodes");
221
            return code;
222
        }
223
224
        /* Future enhancement we should fall back to trying the individual bitmap here */
225
        if(returned_count != char_count) {
226
            pdev->OCRStage = OCR_Failed;
227
            gs_free_object(pdev->memory, returned, "returned unicodes");
228
            return 0;
229
        }
230
        pdev->OCRUnicode = returned;
231
232
        /* Actually perform OCR on the stored bitmaps */
233
        pdev->OCRStage = OCR_UnicodeAvailable;
234
    }
235
236
    if(pdev->OCRStage == OCR_UnicodeAvailable) {
237
        /* We've OCR'ed the bitmaps already, find the unicode value */
238
        ocr_glyph_t *new_glyph = (ocr_glyph_t *)pdev->ocr_glyphs;
239
        int ocr_index = 0;
240
        uint mask = 0xFF;
241
        int ix;
242
        char *u;
243
244
        /* Find the bitmap which matches the character/glyph we are processing */
245
        while(new_glyph) {
246
            if(new_glyph->char_code == ch || new_glyph->glyph == glyph) {
247
                ocr_glyph_t *g1 = pdev->ocr_glyphs;
248
249
                /* Spaces are handled specially, so just jump out now */
250
                if(new_glyph->is_space)
251
                    break;
252
253
                /* Otherwise, find all the bitmaps which lie to the left of the
254
                 * one we found (we are assuming for now that the returned
255
                 * Unicode values are left to right)
256
                 */
257
                while(g1) {
258
                    if(!g1->is_space) {
259
                        if(g1->x < new_glyph->x)
260
                            ocr_index++;
261
                    }
262
                    g1 = g1->next;
263
                }
264
                break;
265
            }
266
            new_glyph = new_glyph->next;
267
        }
268
269
        /* If we found a matching bitmap, get the corresponding unicode code point from
270
         * the stored values returned by the OCR engine.
271
         */
272
        if(new_glyph) {
273
            *unicode = (byte *)gs_alloc_bytes(pdev->memory, 2 * sizeof(ushort), "temporary Unicode array");
274
            if(*unicode == NULL)
275
                return_error(gs_error_VMerror);
276
            u = (char *)(*unicode);
277
            if(new_glyph->is_space) {
278
                memset(u, 0x00, 3);
279
                u[3] = 0x20;
280
            }
281
            else {
282
                for(ix = 0;ix < 4;ix++) {
283
                    u[3 - ix] = (pdev->OCRUnicode[ocr_index] & mask) >> (8 * ix);
284
                    mask = mask << 8;
285
                }
286
            }
287
            *length = 4;
288
        }
289
    }
290
    #endif
291
0
    return 0;
292
0
}
293
294
/*
295
 * Add char code pair to ToUnicode CMap,
296
 * creating the CMap on neccessity.
297
 */
298
int
299
pdf_add_ToUnicode(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfont,
300
                  gs_glyph glyph, gs_char ch, const gs_const_string *gnstr)
301
320k
{   int code = 0;
302
320k
    gs_char length = 0;
303
320k
    ushort *unicode = 0;
304
305
320k
    if (glyph == GS_NO_GLYPH)
306
0
        return 0;
307
320k
    if(pdev->UseOCR == UseOCRAlways) {
308
0
        code = OCRText(pdev, glyph, ch, &length, (byte **)&unicode);
309
0
        if(code < 0)
310
0
            return code;
311
0
    }
312
320k
    else {
313
320k
        length = font->procs.decode_glyph((gs_font *)font, glyph, ch, NULL, 0);
314
320k
        if(length == 0 || length == GS_NO_CHAR) {
315
281k
            if(gnstr != NULL && gnstr->size == 7) {
316
4.09k
                if(!memcmp(gnstr->data, "uni", 3)) {
317
47
                    static const char *hexdigits = "0123456789ABCDEF";
318
47
                    char *d0 = strchr(hexdigits, gnstr->data[3]);
319
47
                    char *d1 = strchr(hexdigits, gnstr->data[4]);
320
47
                    char *d2 = strchr(hexdigits, gnstr->data[5]);
321
47
                    char *d3 = strchr(hexdigits, gnstr->data[6]);
322
323
47
                    unicode = (ushort *)gs_alloc_bytes(pdev->memory, sizeof(ushort), "temporary Unicode array");
324
47
                    if(d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) {
325
47
                        char *u = (char *)unicode;
326
47
                        u[0] = ((d0 - hexdigits) << 4) + ((d1 - hexdigits));
327
47
                        u[1] = ((d2 - hexdigits) << 4) + ((d3 - hexdigits));
328
47
                        length = 2;
329
47
                    }
330
47
                }
331
4.09k
            }
332
277k
            else {
333
277k
                if(pdev->UseOCR != UseOCRNever) {
334
0
                    code = OCRText(pdev, glyph, ch, &length, (byte **)&unicode);
335
0
                    if(code < 0)
336
0
                        return code;
337
0
                }
338
277k
            }
339
281k
        }
340
320k
    }
341
342
320k
    if (length != 0 && length != GS_NO_CHAR) {
343
38.6k
        if (pdfont->cmap_ToUnicode == NULL) {
344
            /* ToUnicode CMaps are always encoded with two byte keys. See
345
             * Technical Note 5411, 'ToUnicode Mapping File Tutorial'
346
             * page 3.
347
             */
348
            /* Unfortunately, the above is not true. See the PDF Reference (version 1.7
349
             * p 472 'ToUnicode CMaps'. Even that documentation is incorrect as it
350
             * describes codespaceranges, in fact for Acrobat this is irrelevant,
351
             * but the bfranges must be one byte for simple fonts. By altering the
352
             * key size for CID fonts we can write both consistently correct.
353
             */
354
964
            uint num_codes = 256, key_size = 1;
355
356
964
            if (font->FontType == ft_CID_encrypted) {
357
0
                gs_font_cid0 *pfcid = (gs_font_cid0 *)font;
358
359
0
                num_codes = pfcid->cidata.common.CIDCount;
360
0
                key_size = 2;
361
964
            } else if (font->FontType == ft_CID_TrueType || font->FontType == ft_composite) {
362
126
                key_size = 2;
363
                /* Since PScript5.dll creates GlyphNames2Unicode with character codes
364
                   instead CIDs, and with the WinCharSetFFFF-H2 CMap
365
                   character codes appears from the range 0-0xFFFF (Bug 687954),
366
                   we must use the maximal character code value for the ToUnicode
367
                   code count. */
368
126
                num_codes = 65536;
369
126
            }
370
964
            code = gs_cmap_ToUnicode_alloc(pdev->pdf_memory, pdfont->rid, num_codes, key_size, length,
371
964
                                            &pdfont->cmap_ToUnicode);
372
964
            if (code < 0) {
373
0
                if (unicode)
374
0
                    gs_free_object(pdev->memory, unicode, "temporary Unicode array");
375
0
                return code;
376
0
            }
377
37.7k
        } else {
378
37.7k
            if (((gs_cmap_ToUnicode_t *)pdfont->cmap_ToUnicode)->value_size < length){
379
7
                gs_cmap_ToUnicode_realloc(pdev->pdf_memory, length, &pdfont->cmap_ToUnicode);
380
7
            }
381
37.7k
        }
382
383
38.6k
        if (!unicode) {
384
38.6k
            unicode = (ushort *)gs_alloc_bytes(pdev->memory, length * sizeof(short), "temporary Unicode array");
385
38.6k
            if (unicode == NULL)
386
0
                return_error(gs_error_VMerror);
387
38.6k
            length = font->procs.decode_glyph((gs_font *)font, glyph, ch, unicode, length);
388
38.6k
        }
389
390
38.6k
        if (pdfont->cmap_ToUnicode != NULL)
391
38.6k
            gs_cmap_ToUnicode_add_pair(pdfont->cmap_ToUnicode, ch, unicode, length);
392
38.6k
        if (length > 2 && pdfont->u.simple.Encoding != NULL)
393
33
            pdfont->TwoByteToUnicode = 0;
394
38.6k
    }
395
396
320k
    if (unicode)
397
38.6k
        gs_free_object(pdev->memory, unicode, "temporary Unicode array");
398
320k
    return 0;
399
320k
}
400
401
typedef struct {
402
    gx_device_pdf *pdev;
403
    pdf_resource_type_t rtype;
404
} pdf_resource_enum_data_t;
405
406
static int
407
process_resources2(void *client_data, const byte *key_data, uint key_size, const cos_value_t *v)
408
0
{
409
0
    pdf_resource_enum_data_t *data = (pdf_resource_enum_data_t *)client_data;
410
0
    pdf_resource_t *pres = pdf_find_resource_by_resource_id(data->pdev, data->rtype, v->contents.object->id);
411
412
0
    if (pres == NULL)
413
0
        return_error(gs_error_unregistered); /* Must not happen. */
414
0
    pres->where_used |= data->pdev->used_mask;
415
0
    return 0;
416
0
}
417
418
static int
419
process_resources1(void *client_data, const byte *key_data, uint key_size, const cos_value_t *v)
420
0
{
421
0
    pdf_resource_enum_data_t *data = (pdf_resource_enum_data_t *)client_data;
422
0
    static const char *rn[] = {PDF_RESOURCE_TYPE_NAMES};
423
0
    int i;
424
425
0
    for (i = 0; i < count_of(rn); i++) {
426
0
        if (rn[i] != NULL && !bytes_compare((const byte *)rn[i], strlen(rn[i]), key_data, key_size))
427
0
            break;
428
0
    }
429
0
    if (i >= count_of(rn))
430
0
        return 0;
431
0
    data->rtype = i;
432
0
    return cos_dict_forall((cos_dict_t *)v->contents.object, data, process_resources2);
433
0
}
434
435
/*
436
 * Register charproc fonts with the page or substream.
437
 */
438
int
439
pdf_used_charproc_resources(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
440
114k
{
441
114k
    if (pdfont->where_used & pdev->used_mask)
442
110k
        return 0;
443
3.70k
    pdfont->where_used |= pdev->used_mask;
444
3.70k
    if (pdev->CompatibilityLevel >= 1.2)
445
3.70k
        return 0;
446
0
    if (pdfont->FontType == ft_user_defined ||
447
0
        pdfont->FontType == ft_PDF_user_defined ||
448
0
        pdfont->FontType == ft_PCL_user_defined ||
449
0
        pdfont->FontType == ft_MicroType ||
450
0
        pdfont->FontType == ft_GL2_stick_user_defined ||
451
0
        pdfont->FontType == ft_GL2_531) {
452
0
        pdf_resource_enum_data_t data;
453
454
0
        data.pdev = pdev;
455
0
        return cos_dict_forall(pdfont->u.simple.s.type3.Resources, &data, process_resources1);
456
0
    }
457
0
    return 0;
458
0
}
459
460
/*
461
 * Given a text string and a simple gs_font, return a font resource suitable
462
 * for the text string, possibly re-encoding the string.  This
463
 * may involve creating a font resource and/or adding glyphs and/or Encoding
464
 * entries to it.
465
 *
466
 * Sets *ppdfont.
467
 */
468
static int
469
pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfont,
470
                  gs_char ch, const gs_glyph *gdata)
471
5.97M
{
472
5.97M
    gs_font_base *cfont, *ccfont;
473
5.97M
    int code;
474
5.97M
    gs_glyph copied_glyph;
475
5.97M
    gs_const_string gnstr;
476
5.97M
    pdf_encoding_element_t *pet;
477
5.97M
    gs_glyph glyph;
478
479
    /*
480
     * In contradiction with pre-7.20 versions of pdfwrite,
481
     * we never re-encode texts due to possible encoding conflict while font merging.
482
     */
483
5.97M
    cfont = pdf_font_resource_font(pdfont, false);
484
5.97M
    ccfont = pdf_font_resource_font(pdfont, true);
485
5.97M
    pet = &pdfont->u.simple.Encoding[ch];
486
5.97M
    glyph = (gdata == NULL ? font->procs.encode_char(font, ch, GLYPH_SPACE_NAME)
487
5.97M
                           : *gdata);
488
5.97M
    if (glyph == GS_NO_GLYPH || glyph == pet->glyph) {
489
5.68M
        if((pdfont->cmap_ToUnicode == NULL || !gs_cmap_ToUnicode_check_pair(pdfont->cmap_ToUnicode, ch)) && pdev->UseOCR != UseOCRNever)
490
0
            (void)pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, NULL);
491
5.68M
        return 0;
492
5.68M
    }
493
294k
    if (pet->glyph != GS_NO_GLYPH) { /* encoding conflict */
494
0
        return_error(gs_error_rangecheck);
495
        /* Must not happen because pdf_obtain_font_resource
496
         * checks for encoding compatibility.
497
         */
498
0
    }
499
294k
    code = font->procs.glyph_name(font, glyph, &gnstr);
500
294k
    if (code < 0)
501
0
        return code; /* can't get name of glyph */
502
294k
    if (font->FontType != ft_user_defined &&
503
294k
        font->FontType != ft_PDF_user_defined &&
504
294k
        font->FontType != ft_PCL_user_defined &&
505
294k
        font->FontType != ft_MicroType &&
506
294k
        font->FontType != ft_GL2_stick_user_defined &&
507
294k
        font->FontType != ft_GL2_531) {
508
        /* The standard 14 fonts don't have a FontDescriptor. */
509
292k
        code = (pdfont->base_font != 0 ?
510
34.9k
                pdf_base_font_copy_glyph(pdfont->base_font, glyph, (gs_font_base *)font) :
511
292k
                pdf_font_used_glyph(pdfont->FontDescriptor, glyph, (gs_font_base *)font));
512
292k
        if (code < 0 && code != gs_error_undefined)
513
260
            return code;
514
292k
        if (code == gs_error_undefined) {
515
2.08k
            if (pdev->PDFA != 0 || pdev->PDFX) {
516
0
                switch (pdev->PDFACompatibilityPolicy) {
517
0
                    case 0:
518
0
                        emprintf(pdev->memory,
519
0
                             "Requested glyph not present in source font,\n not permitted in PDF/A, reverting to normal PDF output\n");
520
0
                        pdev->AbortPDFAX = true;
521
0
                        pdev->PDFA = 0;
522
0
                        break;
523
0
                    case 1:
524
0
                        emprintf(pdev->memory,
525
0
                             "Requested glyph not present in source font,\n not permitted in PDF/A, glyph will not be present in output file\n\n");
526
                        /* Returning an error causees text processing to try and
527
                         * handle the glyph by rendering to a bitmap instead of
528
                         * as a glyph in a font. This will eliminate the problem
529
                         * and the fiel should appear the same as the original.
530
                         */
531
0
                        return_error(gs_error_unknownerror);
532
0
                        break;
533
0
                    case 2:
534
0
                        emprintf(pdev->memory,
535
0
                             "Requested glyph not present in source font,\n not permitted in PDF/A, aborting conversion\n");
536
                        /* Careful here, only certain errors will bubble up
537
                         * through the text processing.
538
                         */
539
0
                        return_error(gs_error_invalidfont);
540
0
                        break;
541
0
                    default:
542
0
                        emprintf(pdev->memory,
543
0
                             "Requested glyph not present in source font,\n not permitted in PDF/A, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n");
544
0
                        pdev->AbortPDFAX = true;
545
0
                        pdev->PDFA = 0;
546
0
                        break;
547
0
                }
548
0
            }
549
            /* PS font has no such glyph. */
550
2.08k
            if (bytes_compare(gnstr.data, gnstr.size, (const byte *)".notdef", 7)) {
551
2.08k
                pet->glyph = glyph;
552
2.08k
                pdf_copy_string_to_encoding(pdev, &gnstr, pet);
553
2.08k
                pet->is_difference = true;
554
2.08k
            }
555
290k
        } else if (pdfont->base_font == NULL && ccfont != NULL &&
556
290k
                (gs_copy_glyph_options(font, glyph, (gs_font *)ccfont, COPY_GLYPH_NO_NEW) != 1 ||
557
253k
                    gs_copied_font_add_encoding((gs_font *)ccfont, ch, glyph) < 0)) {
558
               /*
559
                * The "complete" copy of the font appears incomplete
560
                * due to incrementally added glyphs. Drop the "complete"
561
                * copy now and continue with subset font only.
562
                *
563
                * Note that we need to add the glyph to the encoding of the
564
                * "complete" font, because "PPI-ProPag 2.6.1.4 (archivePg)"
565
                * creates multiple font copies with reduced encodings
566
                * (we believe it is poorly designed),
567
                * and we can merge the copies back to a single font (see Bug 686875).
568
                * We also check whether the encoding is compatible.
569
                * It must be compatible here due to the pdf_obtain_font_resource
570
                * and ccfont logics, but we want to ensure for safety reason.
571
                */
572
116
            ccfont = NULL;
573
116
            pdf_font_descriptor_drop_complete_font(pdfont->FontDescriptor);
574
116
        }
575
        /*
576
            * We arbitrarily allow the first encoded character in a given
577
            * position to determine the encoding associated with the copied
578
            * font.
579
            */
580
292k
        copied_glyph = cfont->procs.encode_char((gs_font *)cfont, ch,
581
292k
                                                GLYPH_SPACE_NAME);
582
292k
        if (glyph != copied_glyph &&
583
292k
            gs_copied_font_add_encoding((gs_font *)cfont, ch, glyph) < 0
584
292k
            )
585
2.08k
            pet->is_difference = true;
586
292k
        pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
587
292k
    }
588
    /*
589
     * We always generate ToUnicode for simple fonts, because
590
     * we can't detemine in advance, which glyphs the font actually uses.
591
     * The decision about writing it out is deferred until pdf_write_font_resource.
592
     */
593
294k
    code = pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, &gnstr);
594
294k
    if(code < 0)
595
0
        return code;
596
294k
    pet->glyph = glyph;
597
294k
    return pdf_copy_string_to_encoding(pdev, &gnstr, pet);
598
294k
}
599
600
/*
601
 * Estimate text bbox.
602
 */
603
static int
604
process_text_estimate_bbox(pdf_text_enum_t *pte, gs_font_base *font,
605
                          const gs_const_string *pstr,
606
                          const gs_matrix *pfmat,
607
                          gs_rect *text_bbox, gs_point *pdpt)
608
1.32M
{
609
1.32M
    int i;
610
1.32M
    int space_char =
611
1.32M
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
612
1.02M
         pte->text.space.s_char : -1);
613
1.32M
    int WMode = font->WMode;
614
1.32M
    int code = 0;
615
1.32M
    gs_point total = {0, 0};
616
1.32M
    gs_point p0, p1, p2, p3;
617
1.32M
    gs_fixed_point origin;
618
1.32M
    gs_matrix m;
619
1.32M
    int xy_index = pte->xy_index, info_flags = 0;
620
1.32M
    gx_path *path = gs_text_enum_path(pte);
621
622
1.32M
    code = gx_path_current_point(path, &origin);
623
1.32M
    if (code < 0)
624
0
        return code;
625
1.32M
    m = ctm_only(pte->pgs);
626
1.32M
    m.tx = fixed2float(origin.x);
627
1.32M
    m.ty = fixed2float(origin.y);
628
1.32M
    gs_matrix_multiply(pfmat, &m, &m);
629
630
    /* If the FontBBox is all 0, then its clearly wrong, so determine the text width
631
     * accurately by processing the glyph program.
632
     */
633
1.32M
    if (font->FontBBox.p.x == font->FontBBox.q.x ||
634
1.32M
        font->FontBBox.p.y == font->FontBBox.q.y) {
635
17.0k
            info_flags = GLYPH_INFO_BBOX | GLYPH_INFO_WIDTH0 << WMode;
636
1.30M
    } else {
637
1.30M
        double width, height;
638
639
        /* This is a heuristic for Bug #700124. We try to determine whether a given glyph
640
         * is used in a string by using the current point, glyph width and advance width
641
         * to see if the glyph is fully clipped out, if it is we don't include it in the
642
         * output, or in subset fonts.
643
         *
644
         * Previously we used the FontBBox to determine a quick glyph width, but
645
         * in bug #699454 and bug #699571 we saw that OneVision EPSExport could construct
646
         * fonts with a wildly incorrect BBox ([0 0 2 1]) and then draw the text without
647
         * an advance width, leading us to conclude the glyph was clipped out and eliding it.
648
         *
649
         * To solve this we added code to process the glyph program and extract an accurate
650
         * width of the glyph. However, this proved slow. So here we attempt to decide if
651
         * the FontBBox is sensible by applying the FontMatrix to it, and looking to see
652
         * if that results in a reasonable number of co-ordinates in font space. If it
653
         * does then we use the FontBBox for speed, otherwise we carefully process the
654
         * glyphs in the font and extract their accurate widths.
655
         */
656
1.30M
        gs_point_transform(font->FontBBox.p.x, font->FontBBox.p.y, &font->FontMatrix, &p0);
657
1.30M
        gs_point_transform(font->FontBBox.p.x, font->FontBBox.q.y, &font->FontMatrix, &p1);
658
1.30M
        gs_point_transform(font->FontBBox.q.x, font->FontBBox.p.y, &font->FontMatrix, &p2);
659
1.30M
        gs_point_transform(font->FontBBox.q.x, font->FontBBox.q.y, &font->FontMatrix, &p3);
660
1.30M
        width = max(fabs(p2.x), fabs(p3.x)) - p0.x;
661
1.30M
        height = max(fabs(p1.y), fabs(p3.y)) - p0.y;
662
663
        /* Yes, this is a magic number. There's no reasoning here, its just a guess, we may
664
         * need to adjust this in future. Or possibly do away with it altogether if it proves
665
         * unreliable.
666
         */
667
1.30M
        if (fabs(width) < 0.1 || fabs(height) < 0.1) {
668
2.22k
            info_flags = GLYPH_INFO_BBOX | GLYPH_INFO_WIDTH0 << WMode;
669
1.30M
        } else {
670
1.30M
            gs_point_transform(font->FontBBox.p.x, font->FontBBox.p.y, &m, &p0);
671
1.30M
            gs_point_transform(font->FontBBox.p.x, font->FontBBox.q.y, &m, &p1);
672
1.30M
            gs_point_transform(font->FontBBox.q.x, font->FontBBox.p.y, &m, &p2);
673
1.30M
            gs_point_transform(font->FontBBox.q.x, font->FontBBox.q.y, &m, &p3);
674
1.30M
            info_flags = GLYPH_INFO_WIDTH0 << WMode;
675
1.30M
        }
676
1.30M
    }
677
678
6.94M
    for (i = 0; i < pstr->size; ++i) {
679
5.72M
        byte c = pstr->data[i];
680
5.72M
        gs_rect bbox;
681
5.72M
        gs_point wanted, tpt;
682
5.72M
        gs_glyph glyph = font->procs.encode_char((gs_font *)font, c,
683
5.72M
                                        GLYPH_SPACE_NAME);
684
5.72M
        gs_glyph_info_t info;
685
5.72M
        int code;
686
687
5.72M
        if (glyph == GS_NO_GLYPH)
688
8
            return_error (gs_error_invalidfont);
689
690
5.72M
        memset(&info, 0x00, sizeof(gs_glyph_info_t));
691
5.72M
        code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
692
5.72M
                                            info_flags,
693
5.72M
                                            &info);
694
695
        /* If we got an undefined error, and its a type 1/CFF font, try to
696
         * find the /.notdef glyph and use its width instead (as this is the
697
         * glyph which will be rendered). We don't do this for other font types
698
         * as it seems Acrobat/Distiller may not do so either.
699
         */
700
        /* The GL/2 stick font does not supply the enumerate_glyphs method,
701
         * *and* leaves it uninitialised. But it should not be possible to
702
         * get an undefiend error with this font anyway.
703
         */
704
5.72M
        if (code < 0) {
705
101k
            if ((font->FontType == ft_encrypted ||
706
101k
            font->FontType == ft_encrypted2)) {
707
95.3k
                int index;
708
709
95.3k
                for (index = 0;
710
95.3k
                    (font->procs.enumerate_glyph((gs_font *)font, &index,
711
95.3k
                    (GLYPH_SPACE_NAME), &glyph)) >= 0 &&
712
95.3k
                    index != 0;) {
713
714
95.3k
                    if (gs_font_glyph_is_notdef(font, glyph)) {
715
12
                        code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
716
12
                                            info_flags,
717
12
                                            &info);
718
719
12
                    if (code < 0)
720
0
                        return code;
721
12
                    }
722
95.3k
                    break;
723
95.3k
                }
724
95.3k
            }
725
101k
            if (code < 0)
726
101k
                return code;
727
101k
        }
728
5.62M
        if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
729
3.44M
            code = gs_text_replaced_width(&pte->text, xy_index++, &tpt);
730
3.44M
            if (code < 0)
731
0
                return code;
732
733
3.44M
            gs_distance_transform(tpt.x, tpt.y, &ctm_only(pte->pgs), &wanted);
734
3.44M
        } else {
735
2.17M
            gs_distance_transform(info.width[WMode].x,
736
2.17M
                                  info.width[WMode].y,
737
2.17M
                                  &m, &wanted);
738
2.17M
            if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
739
352k
                gs_distance_transform(pte->text.delta_all.x,
740
352k
                                      pte->text.delta_all.y,
741
352k
                                      &ctm_only(pte->pgs), &tpt);
742
352k
                wanted.x += tpt.x;
743
352k
                wanted.y += tpt.y;
744
352k
            }
745
2.17M
            if (pstr->data[i] == space_char && pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
746
9.62k
                gs_distance_transform(pte->text.delta_space.x,
747
9.62k
                                      pte->text.delta_space.y,
748
9.62k
                                      &ctm_only(pte->pgs), &tpt);
749
9.62k
                wanted.x += tpt.x;
750
9.62k
                wanted.y += tpt.y;
751
9.62k
            }
752
2.17M
        }
753
754
5.62M
        if (info_flags & GLYPH_INFO_BBOX) {
755
36.5k
            gs_point_transform(info.bbox.p.x, info.bbox.p.x, &m, &p0);
756
36.5k
            gs_point_transform(info.bbox.p.x, info.bbox.q.y, &m, &p1);
757
36.5k
            gs_point_transform(info.bbox.q.x, info.bbox.p.y, &m, &p2);
758
36.5k
            gs_point_transform(info.bbox.q.x, info.bbox.q.y, &m, &p3);
759
36.5k
        }
760
761
5.62M
        bbox.p.x = min(min(p0.x, p1.x), min(p2.x, p3.x));
762
5.62M
        bbox.p.y = min(min(p0.y, p1.y), min(p2.y, p3.y));
763
5.62M
        bbox.q.x = max(max(p0.x, p1.x), max(p2.x, p3.x));
764
5.62M
        bbox.q.y = max(max(p0.y, p1.y), max(p2.y, p3.y));
765
766
5.62M
        bbox.q.x = bbox.p.x + max(bbox.q.x - bbox.p.x, wanted.x);
767
5.62M
        bbox.q.y = bbox.p.y + max(bbox.q.y - bbox.p.y, wanted.y);
768
5.62M
        bbox.p.x += total.x;
769
5.62M
        bbox.p.y += total.y;
770
5.62M
        bbox.q.x += total.x;
771
5.62M
        bbox.q.y += total.y;
772
773
5.62M
        total.x += wanted.x;
774
5.62M
        total.y += wanted.y;
775
776
5.62M
        if (i == 0)
777
1.23M
            *text_bbox = bbox;
778
4.38M
        else
779
5.62M
            rect_merge(*text_bbox, bbox);
780
5.62M
    }
781
1.22M
    *pdpt = total;
782
1.22M
    return 0;
783
1.32M
}
784
785
void
786
adjust_first_last_char(pdf_font_resource_t *pdfont, byte *str, int size)
787
1.32M
{
788
1.32M
    int i;
789
790
7.26M
    for (i = 0; i < size; ++i) {
791
5.93M
        int chr = str[i];
792
793
5.93M
        if (chr < pdfont->u.simple.FirstChar)
794
29.7k
            pdfont->u.simple.FirstChar = chr;
795
5.93M
        if (chr > pdfont->u.simple.LastChar)
796
70.3k
            pdfont->u.simple.LastChar = chr;
797
5.93M
    }
798
1.32M
}
799
800
int
801
pdf_shift_text_currentpoint(pdf_text_enum_t *penum, gs_point *wpt)
802
1.34M
{
803
1.34M
    return gs_moveto_aux(penum->pgs, gx_current_path(penum->pgs),
804
1.34M
                              fixed2float(penum->origin.x) + wpt->x,
805
1.34M
                              fixed2float(penum->origin.y) + wpt->y);
806
1.34M
}
807
808
/*
809
 * Internal procedure to process a string in a non-composite font.
810
 * Doesn't use or set pte->{data,size,index}; may use/set pte->xy_index;
811
 * may set penum->returned.total_width.  Sets ppts->values.
812
 *
813
 * Note that the caller is responsible for re-encoding the string, if
814
 * necessary; for adding Encoding entries in pdfont; and for copying any
815
 * necessary glyphs.  penum->current_font provides the gs_font for getting
816
 * glyph metrics, but this font's Encoding is not used.
817
 */
818
static int process_text_return_width(const pdf_text_enum_t *pte,
819
                                      gs_font_base *font,
820
                                      pdf_text_process_state_t *ppts,
821
                                      const gs_const_string *pstr, const gs_glyph *gdata,
822
                                      gs_point *pdpt, int *accepted, gs_rect *bbox);
823
static int
824
pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr,
825
                   const gs_matrix *pfmat,
826
                   pdf_text_process_state_t *ppts, const gs_glyph *gdata)
827
1.49M
{
828
1.49M
    gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
829
1.49M
    gs_font_base *font = (gs_font_base *)penum->current_font;
830
1.49M
    pdf_font_resource_t *pdfont;
831
1.49M
    gs_text_params_t *text = &penum->text;
832
1.49M
    int code = 0, mask;
833
1.49M
    gs_point width_pt;
834
1.49M
    int accepted;
835
1.49M
    gs_rect text_bbox = {{0, 0}, {0, 0}}, glyphs_bbox = {{10000,10000}, {0,0}};
836
1.49M
    unsigned int operation = text->operation;
837
1.49M
    gx_path *path = gs_text_enum_path(penum);
838
839
1.49M
    code = pdf_obtain_font_resource(penum, pstr, &pdfont);
840
1.49M
    if (code < 0)
841
165k
        return code;
842
1.33M
    if (pfmat == 0)
843
1.33M
        pfmat = &font->FontMatrix;
844
1.33M
    if (text->operation & TEXT_RETURN_WIDTH) {
845
1.33M
        code = gx_path_current_point(path, &penum->origin);
846
1.33M
        if (code < 0)
847
0
            return code;
848
1.33M
    }
849
1.33M
    if (text->size == 0)
850
1.27k
        return 0;
851
1.33M
    if (penum->pgs->text_rendering_mode != 3 && !(text->operation & TEXT_DO_NONE)) {
852
        /*
853
         * Acrobat Reader can't handle text with huge coordinates,
854
         * so don't emit the text if it is outside the clip bbox
855
         * (Note : it ever fails with type 3 fonts).
856
         */
857
858
1.32M
        code = process_text_estimate_bbox(penum, font, (gs_const_string *)pstr, pfmat,
859
1.32M
                                          &text_bbox, &width_pt);
860
1.32M
        if (code == 0) {
861
1.22M
            gs_fixed_rect clip_bbox;
862
1.22M
            gs_rect rect;
863
864
1.22M
            if (penum->pcpath) {
865
1.22M
                gx_cpath_outer_box(penum->pcpath, &clip_bbox);
866
1.22M
                rect.p.x = fixed2float(clip_bbox.p.x);
867
1.22M
                rect.p.y = fixed2float(clip_bbox.p.y);
868
1.22M
                rect.q.x = fixed2float(clip_bbox.q.x);
869
1.22M
                rect.q.y = fixed2float(clip_bbox.q.y);
870
1.22M
                rect_intersect(rect, text_bbox);
871
1.22M
                if (rect.p.x > rect.q.x || rect.p.y > rect.q.y) {
872
4.54k
                    penum->index += pstr->size;
873
4.54k
                    text->operation &= ~TEXT_DO_DRAW;
874
4.54k
                }
875
1.22M
            }
876
1.22M
        } else {
877
101k
            gs_matrix m;
878
101k
            gs_fixed_point origin;
879
101k
            gs_point p0, p1, p2, p3;
880
881
101k
            code = gx_path_current_point(path, &origin);
882
101k
            if (code < 0)
883
0
                goto done;
884
885
101k
            m = ctm_only(penum->pgs);
886
101k
            m.tx = fixed2float(origin.x);
887
101k
            m.ty = fixed2float(origin.y);
888
101k
            gs_matrix_multiply(pfmat, &m, &m);
889
890
101k
            if (font->FontBBox.p.x != font->FontBBox.q.x) {
891
96.6k
                text_bbox.p.x = font->FontBBox.p.x;
892
96.6k
                text_bbox.q.x = font->FontBBox.q.x;
893
96.6k
            } else {
894
4.45k
                text_bbox.p.x = 0;
895
4.45k
                text_bbox.q.x = 1000;
896
4.45k
            }
897
101k
            if (font->FontBBox.p.y != font->FontBBox.q.y) {
898
96.6k
                text_bbox.p.y = font->FontBBox.p.y;
899
96.6k
                text_bbox.q.y = font->FontBBox.q.y;
900
96.6k
            } else {
901
4.45k
                text_bbox.p.y = 0;
902
4.45k
                text_bbox.q.y = 1000;
903
4.45k
            }
904
101k
            gs_point_transform(text_bbox.p.x, text_bbox.p.y, &m, &p0);
905
101k
            gs_point_transform(text_bbox.p.x, text_bbox.q.y, &m, &p1);
906
101k
            gs_point_transform(text_bbox.q.x, text_bbox.p.y, &m, &p2);
907
101k
            gs_point_transform(text_bbox.q.x, text_bbox.q.y, &m, &p3);
908
101k
            text_bbox.p.x = min(min(p0.x, p1.x), min(p1.x, p2.x));
909
101k
            text_bbox.p.y = min(min(p0.y, p1.y), min(p1.y, p2.y));
910
101k
            text_bbox.q.x = max(max(p0.x, p1.x), max(p1.x, p2.x));
911
101k
            text_bbox.q.y = max(max(p0.y, p1.y), max(p1.y, p2.y));
912
101k
        }
913
1.32M
    } else {
914
        /* We have no penum->pcpath. */
915
5.41k
    }
916
917
    /*
918
     * Note that pdf_update_text_state sets all the members of ppts->values
919
     * to their current values.
920
     */
921
1.33M
    code = pdf_update_text_state(ppts, penum, pdfont, pfmat);
922
1.33M
    if (code > 0) {
923
        /* Try not to emulate ADD_TO_WIDTH if we don't have to. */
924
0
        if (code & TEXT_ADD_TO_SPACE_WIDTH) {
925
0
            if (!memchr(pstr->data, penum->text.space.s_char, pstr->size))
926
0
                code &= ~TEXT_ADD_TO_SPACE_WIDTH;
927
0
        }
928
0
    }
929
1.33M
    if (code < 0)
930
0
        goto done;
931
1.33M
    mask = code;
932
933
1.33M
    if (text->operation & TEXT_REPLACE_WIDTHS)
934
1.07M
        mask |= TEXT_REPLACE_WIDTHS;
935
936
    /*
937
     * The only operations left to handle are TEXT_DO_DRAW and
938
     * TEXT_RETURN_WIDTH.
939
     */
940
1.33M
    if (mask == 0) {
941
        /*
942
         * If any character has real_width != Width, we have to process
943
         * the string character-by-character.  process_text_return_width
944
         * will tell us what we need to know.
945
         */
946
259k
        if (!(text->operation & (TEXT_DO_DRAW | TEXT_RETURN_WIDTH))) {
947
0
            code = 0;
948
0
            goto done;
949
0
        }
950
259k
        code = process_text_return_width(penum, font, ppts,
951
259k
                                         (gs_const_string *)pstr, gdata,
952
259k
                                         &width_pt, &accepted, &glyphs_bbox);
953
259k
        if (code < 0)
954
303
            goto done;
955
258k
        if (code == 0) {
956
            /* No characters with redefined widths -- the fast case. */
957
258k
            if (text->operation & TEXT_DO_DRAW || penum->pgs->text_rendering_mode == 3) {
958
256k
                code = pdf_append_chars(pdev, pstr->data, accepted,
959
256k
                                        width_pt.x, width_pt.y, false);
960
256k
                if (code < 0)
961
0
                    goto done;
962
256k
                adjust_first_last_char(pdfont, pstr->data, accepted);
963
256k
                penum->index += accepted;
964
256k
            } else if (text->operation & TEXT_DO_NONE)
965
3
                penum->index += accepted;
966
258k
        } else {
967
            /* Use the slow case.  Set mask to any non-zero value. */
968
0
            mask = TEXT_RETURN_WIDTH;
969
0
        }
970
258k
    }
971
1.33M
    if (mask) {
972
        /* process_text_modify_width destroys text parameters, save them now. */
973
1.07M
        int index0 = penum->index, xy_index = penum->xy_index;
974
1.07M
        gs_text_params_t text = penum->text;
975
1.07M
        int xy_index_step = (!(penum->text.operation & TEXT_REPLACE_WIDTHS) ? 0 :
976
1.07M
                             penum->text.x_widths == penum->text.y_widths ? 2 : 1);
977
        /* A glyphshow takes a shortcut by storing the single glyph directly into
978
         * penum->text.data.d_glyph. However, process_text_modify_width
979
         * replaces pte->text.data.bytes (these two are part of a union) with
980
         * pstr->data, which is not valid for a glyphshow because it alters
981
         * the glyph value store there. If we make a copy of the single glyph,
982
         * it all works correctly.then
983
         */
984
1.07M
        gs_glyph gdata_i, *gdata_p = (gs_glyph *)gdata;
985
1.07M
        if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
986
0
            gdata_i = *gdata;
987
0
            gdata_p = &gdata_i;
988
0
        }
989
990
1.07M
        if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
991
1.07M
            if (penum->text.x_widths != NULL)
992
1.07M
                penum->text.x_widths += xy_index * xy_index_step;
993
1.07M
            if (penum->text.y_widths != NULL)
994
1.07M
                penum->text.y_widths += xy_index * xy_index_step;
995
1.07M
        }
996
1.07M
        penum->xy_index = 0;
997
1.07M
        code = process_text_modify_width(penum, (gs_font *)font, ppts,
998
1.07M
                                         (gs_const_string *)pstr,
999
1.07M
                                         &width_pt, (const gs_glyph *)gdata_p, false, 1);
1000
1.07M
        if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
1001
1.07M
            if (penum->text.x_widths != NULL)
1002
1.07M
                penum->text.x_widths -= xy_index * xy_index_step;
1003
1.07M
            if (penum->text.y_widths != NULL)
1004
1.07M
                penum->text.y_widths -= xy_index * xy_index_step;
1005
1.07M
        }
1006
1.07M
        penum->xy_index += xy_index;
1007
1.07M
        adjust_first_last_char(pdfont, pstr->data, penum->index);
1008
1.07M
        penum->text = text;
1009
1.07M
        penum->index += index0;
1010
1.07M
        if (code < 0)
1011
571
            goto done;
1012
1.07M
    }
1013
1014
    /* Finally, return the total width if requested. */
1015
1.32M
    if (pdev->Eps2Write && penum->pcpath) {
1016
495k
        gx_device_clip cdev;
1017
495k
        gx_drawing_color devc;
1018
495k
        fixed x0, y0, bx2, by2;
1019
1020
495k
        if (glyphs_bbox.p.x != 10000 && glyphs_bbox.q.x != 0){
1021
0
            gs_matrix m;
1022
0
            gs_fixed_point origin;
1023
0
            gs_point p0, p1, p2, p3;
1024
1025
0
            code = gx_path_current_point(path, &origin);
1026
0
            if (code < 0)
1027
0
                return code;
1028
1029
0
            m = ctm_only(penum->pgs);
1030
0
            m.tx = fixed2float(origin.x);
1031
0
            m.ty = fixed2float(origin.y);
1032
0
            gs_matrix_multiply(pfmat, &m, &m);
1033
1034
0
            gs_point_transform(glyphs_bbox.p.x, glyphs_bbox.p.y, &m, &p0);
1035
0
            gs_point_transform(glyphs_bbox.p.x, glyphs_bbox.q.y, &m, &p1);
1036
0
            gs_point_transform(glyphs_bbox.q.x, glyphs_bbox.p.y, &m, &p2);
1037
0
            gs_point_transform(glyphs_bbox.q.x, glyphs_bbox.q.y, &m, &p3);
1038
0
            glyphs_bbox.p.x = min(min(p0.x, p1.x), min(p1.x, p2.x));
1039
0
            glyphs_bbox.p.y = min(min(p0.y, p1.y), min(p1.y, p2.y));
1040
0
            glyphs_bbox.q.x = max(max(p0.x, p1.x), max(p1.x, p2.x));
1041
0
            glyphs_bbox.q.y = max(max(p0.y, p1.y), max(p1.y, p2.y));
1042
0
            if (glyphs_bbox.p.y > text_bbox.p.y)
1043
0
                text_bbox.p.y = glyphs_bbox.p.y;
1044
0
            if (glyphs_bbox.q.y < text_bbox.q.y)
1045
0
                text_bbox.q.y = glyphs_bbox.q.y;
1046
0
        }
1047
        /* removed this section for bug #695671, where the rotated text
1048
         * doesn't contribute the 'height' of the text to the x dimension
1049
         * of the bounding box if this code is present. I can't see why
1050
         * this clamping was done, if it turns out to be required then
1051
         * we will need to revisit this and bug #695671.
1052
        text_bbox.p.x = fixed2float(penum->origin.x);
1053
        text_bbox.q.x = text_bbox.p.x + width_pt.x;
1054
         */
1055
1056
495k
        x0 = float2fixed(text_bbox.p.x);
1057
495k
        y0 = float2fixed(text_bbox.p.y);
1058
495k
        bx2 = float2fixed(text_bbox.q.x) - x0;
1059
495k
        by2 = float2fixed(text_bbox.q.y) - y0;
1060
1061
495k
        pdev->AccumulatingBBox++;
1062
495k
        gx_make_clip_device_on_stack(&cdev, penum->pcpath, (gx_device *)pdev);
1063
495k
        set_nonclient_dev_color(&devc, gx_device_black((gx_device *)pdev));  /* any non-white color will do */
1064
495k
        gx_default_fill_triangle((gx_device *) pdev, x0, y0,
1065
495k
                                 float2fixed(text_bbox.p.x) - x0,
1066
495k
                                 float2fixed(text_bbox.q.y) - y0,
1067
495k
                                 bx2, by2, &devc, lop_default);
1068
495k
        gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
1069
495k
                                 float2fixed(text_bbox.q.x) - x0,
1070
495k
                                 float2fixed(text_bbox.p.y) - y0,
1071
495k
                                 bx2, by2, &devc, lop_default);
1072
495k
        pdev->AccumulatingBBox--;
1073
495k
    }
1074
1.32M
    if (!(operation & TEXT_RETURN_WIDTH)) {
1075
0
        code = 0;
1076
0
        goto done;
1077
0
    }
1078
1.32M
    if (operation & TEXT_DO_NONE) {
1079
        /* stringwidth needs to transform to user space. */
1080
5.41k
        gs_point p;
1081
1082
5.41k
        gs_distance_transform_inverse(width_pt.x, width_pt.y, &ctm_only(penum->pgs), &p);
1083
5.41k
        penum->returned.total_width.x += p.x;
1084
5.41k
        penum->returned.total_width.y += p.y;
1085
5.41k
    } else
1086
1.32M
        penum->returned.total_width = width_pt;
1087
1.32M
    code = pdf_shift_text_currentpoint(penum, &width_pt);
1088
1089
1.33M
done:
1090
1.33M
    text->operation = operation;
1091
1.33M
    return code;
1092
1.32M
}
1093
1094
/*
1095
 * Get the widths (unmodified and possibly modified) of a given character
1096
 * in a simple font.  May add the widths to the widths cache (pdfont->Widths
1097
 * and pdf_font_cache_elem::real_widths).  Return 1 if the widths were not cached.
1098
 */
1099
static int
1100
pdf_char_widths(gx_device_pdf *const pdev,
1101
                pdf_font_resource_t *pdfont, int ch, gs_font_base *font,
1102
                pdf_glyph_widths_t *pwidths /* may be NULL */)
1103
5.97M
{
1104
5.97M
    pdf_glyph_widths_t widths;
1105
5.97M
    int code;
1106
5.97M
    byte *glyph_usage;
1107
5.97M
    double *real_widths;
1108
5.97M
    int char_cache_size, width_cache_size;
1109
5.97M
    pdf_font_resource_t *pdfont1;
1110
1111
5.97M
    code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont1,
1112
5.97M
                                &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1113
5.97M
    if (code < 0)
1114
0
        return code;
1115
5.97M
    if (pdfont1 != pdfont)
1116
0
        return_error(gs_error_unregistered); /* Must not happen. */
1117
5.97M
    if (ch < 0 || ch > 255)
1118
0
        return_error(gs_error_rangecheck);
1119
5.97M
    if (ch >= width_cache_size)
1120
0
        return_error(gs_error_unregistered); /* Must not happen. */
1121
5.97M
    if (pwidths == 0)
1122
0
        pwidths = &widths;
1123
5.97M
    if ((font->FontType != ft_user_defined &&
1124
5.97M
        font->FontType != ft_PDF_user_defined &&
1125
5.97M
        font->FontType != ft_PCL_user_defined &&
1126
5.97M
        font->FontType != ft_MicroType &&
1127
5.97M
        font->FontType != ft_GL2_stick_user_defined &&
1128
5.97M
        font->FontType != ft_GL2_531) && real_widths[ch] == 0) {
1129
        /* Might be an unused char, or just not cached. */
1130
414k
        gs_glyph glyph = pdfont->u.simple.Encoding[ch].glyph;
1131
1132
414k
        code = pdf_glyph_widths(pdfont, font->WMode, glyph, (gs_font *)font, pwidths, NULL);
1133
414k
        if (code < 0)
1134
0
            return code;
1135
414k
        pwidths->BBox.p.x = pwidths->BBox.p.y = pwidths->BBox.q.x = pwidths->BBox.q.y = 0;
1136
414k
        if (font->WMode != 0 && code > 0 && !pwidths->replaced_v) {
1137
            /*
1138
             * The font has no Metrics2, so it must write
1139
             * horizontally due to PS spec.
1140
             * Therefore we need to fill the Widths array,
1141
             * which is required by PDF spec.
1142
             * Take it from WMode==0.
1143
             */
1144
0
            code = pdf_glyph_widths(pdfont, 0, glyph, (gs_font *)font, pwidths, NULL);
1145
0
        }
1146
414k
        if (pwidths->replaced_v) {
1147
393k
            pdfont->u.simple.v[ch].x = pwidths->real_width.v.x - pwidths->Width.v.x;
1148
393k
            pdfont->u.simple.v[ch].y = pwidths->real_width.v.y - pwidths->Width.v.y;
1149
393k
        } else
1150
20.4k
            pdfont->u.simple.v[ch].x = pdfont->u.simple.v[ch].y = 0;
1151
414k
        if (code == 0) {
1152
414k
            pdfont->Widths[ch] = pwidths->Width.w;
1153
414k
            real_widths[ch] = pwidths->real_width.w;
1154
414k
        } else {
1155
31
            if ((font->WMode == 0 || pwidths->ignore_wmode) && !pwidths->replaced_v)
1156
31
                pdfont->Widths[ch] = pwidths->real_width.w;
1157
31
        }
1158
5.55M
    } else {
1159
5.55M
        if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
1160
5.55M
            font->FontType == ft_MicroType || font->FontType == ft_GL2_stick_user_defined ||
1161
5.55M
            font->FontType == ft_GL2_531 || font->FontType == ft_PDF_user_defined ) {
1162
8.32k
            if (!(pdfont->used[ch >> 3] & 0x80 >> (ch & 7)))
1163
896
        return_error(gs_error_undefined); /* The charproc was not accumulated. */
1164
7.42k
            if (!pdev->charproc_just_accumulated &&
1165
7.42k
                !(pdfont->u.simple.s.type3.cached[ch >> 3] & 0x80 >> (ch & 7))) {
1166
                 /* The charproc uses setcharwidth.
1167
                    Need to accumulate again to check for a glyph variation. */
1168
419
        return_error(gs_error_undefined);
1169
419
            }
1170
7.42k
        }
1171
5.55M
        if (pdev->charproc_just_accumulated && (font->FontType == ft_user_defined || font->FontType == ft_PDF_user_defined)) {
1172
4.45k
            pwidths->BBox.p.x = pdev->charproc_BBox.p.x;
1173
4.45k
            pwidths->BBox.p.y = pdev->charproc_BBox.p.y;
1174
4.45k
            pwidths->BBox.q.x = pdev->charproc_BBox.q.x;
1175
4.45k
            pwidths->BBox.q.y = pdev->charproc_BBox.q.y;
1176
4.45k
        }
1177
5.55M
        pwidths->Width.w = pdfont->Widths[ch];
1178
5.55M
        pwidths->Width.v = pdfont->u.simple.v[ch];
1179
5.55M
        pwidths->real_width.v.x = pwidths->real_width.v.y = 0;
1180
5.55M
        pwidths->ignore_wmode = false;
1181
5.55M
        if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
1182
5.55M
            font->FontType == ft_MicroType || font->FontType == ft_GL2_stick_user_defined ||
1183
5.55M
            font->FontType == ft_GL2_531 || font->FontType == ft_PDF_user_defined) {
1184
7.01k
            pwidths->real_width.w = real_widths[ch * 2];
1185
7.01k
            pwidths->Width.xy.x = pwidths->Width.w;
1186
7.01k
            pwidths->Width.xy.y = 0;
1187
7.01k
            pwidths->real_width.xy.x = real_widths[ch * 2 + 0];
1188
7.01k
            pwidths->real_width.xy.y = real_widths[ch * 2 + 1];
1189
7.01k
            pwidths->replaced_v = 0;
1190
5.54M
        } else if (font->WMode) {
1191
0
            pwidths->real_width.w = real_widths[ch];
1192
0
            pwidths->Width.xy.x = 0;
1193
0
            pwidths->Width.xy.y = pwidths->Width.w;
1194
0
            pwidths->real_width.xy.x = 0;
1195
0
            pwidths->real_width.xy.y = pwidths->real_width.w;
1196
5.54M
        } else {
1197
5.54M
            pwidths->real_width.w = real_widths[ch];
1198
5.54M
            pwidths->Width.xy.x = pwidths->Width.w;
1199
5.54M
            pwidths->Width.xy.y = 0;
1200
5.54M
            pwidths->real_width.xy.x = pwidths->real_width.w;
1201
5.54M
            pwidths->real_width.xy.y = 0;
1202
5.54M
        }
1203
5.55M
        code = 0;
1204
5.55M
    }
1205
5.97M
    return code;
1206
5.97M
}
1207
1208
/*
1209
 * Convert glyph widths (.Width.xy and .real_widths.xy) from design to PDF text space
1210
 * Zero-out one of Width.xy.x/y per PDF Ref 5.3.3 "Text Space Details"
1211
 */
1212
static void
1213
pdf_char_widths_to_uts(pdf_font_resource_t *pdfont /* may be NULL for non-Type3 */,
1214
                       pdf_glyph_widths_t *pwidths)
1215
5.99M
{
1216
5.99M
    if (pdfont && (pdfont->FontType == ft_user_defined ||
1217
2.22M
        pdfont->FontType == ft_PDF_user_defined ||
1218
2.22M
        pdfont->FontType == ft_PCL_user_defined ||
1219
2.22M
        pdfont->FontType == ft_MicroType ||
1220
2.22M
        pdfont->FontType == ft_GL2_stick_user_defined ||
1221
2.22M
        pdfont->FontType == ft_GL2_531)) {
1222
7.01k
        gs_matrix *pmat = &pdfont->u.simple.s.type3.FontMatrix;
1223
1224
7.01k
        pwidths->Width.xy.x *= pmat->xx; /* formula simplified based on wy in glyph space == 0 */
1225
7.01k
        pwidths->Width.xy.y  = 0.0; /* WMode == 0 for PDF Type 3 fonts */
1226
7.01k
        gs_distance_transform(pwidths->real_width.xy.x, pwidths->real_width.xy.y, pmat, &pwidths->real_width.xy);
1227
5.98M
    } else {
1228
        /*
1229
         * For other font types:
1230
         * - PDF design->text space is a simple scaling by 0.001.
1231
         * - The Width.xy.x/y that should be zeroed-out per 5.3.3 "Text Space Details" is already 0.
1232
         */
1233
5.98M
        pwidths->Width.xy.x /= 1000.0;
1234
5.98M
        pwidths->Width.xy.y /= 1000.0;
1235
5.98M
        pwidths->real_width.xy.x /= 1000.0;
1236
5.98M
        pwidths->real_width.xy.y /= 1000.0;
1237
5.98M
    }
1238
5.99M
}
1239
1240
/*
1241
 * Compute the total text width (in user space).  Return 1 if any
1242
 * character had real_width != Width, otherwise 0.
1243
 */
1244
static int
1245
process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font,
1246
                          pdf_text_process_state_t *ppts,
1247
                          const gs_const_string *pstr, const gs_glyph *gdata,
1248
                          gs_point *pdpt, int *accepted, gs_rect *bbox)
1249
259k
{
1250
259k
    int i;
1251
259k
    gs_point w;
1252
259k
    gs_point dpt;
1253
259k
    int num_spaces = 0;
1254
259k
    int space_char =
1255
259k
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
1256
212k
         pte->text.space.s_char : -1);
1257
259k
    int widths_differ = 0, code;
1258
259k
    gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
1259
259k
    pdf_font_resource_t *pdfont;
1260
1261
259k
    code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont, NULL, NULL, NULL, NULL);
1262
259k
    if (code < 0)
1263
0
        return code;
1264
2.47M
    for (i = 0, w.x = w.y = 0; i < pstr->size; ++i) {
1265
2.22M
        pdf_glyph_widths_t cw; /* in PDF text space */
1266
2.22M
        gs_char ch = pstr->data[i];
1267
1268
        /* Initialise some variables */
1269
2.22M
        cw.real_width.xy.x = cw.real_width.xy.y = cw.Width.xy.x = cw.Width.xy.y = 0;
1270
2.22M
        cw.BBox.p.x = cw.BBox.p.y = cw.BBox.q.x = cw.BBox.q.y = 0;
1271
1272
2.22M
        {  const gs_glyph *gdata_i = (gdata != NULL ? gdata + i : 0);
1273
1274
2.22M
            code = pdf_encode_string_element(pdev, (gs_font *)font, pdfont, ch, gdata_i);
1275
1276
2.22M
            if (code < 0)
1277
0
                return code;
1278
2.22M
        }
1279
2.22M
        if ((font->FontType == ft_user_defined ||
1280
2.22M
            font->FontType == ft_PDF_user_defined ||
1281
2.22M
            font->FontType == ft_PCL_user_defined ||
1282
2.22M
            font->FontType == ft_GL2_stick_user_defined ||
1283
2.22M
            font->FontType == ft_MicroType ||
1284
2.22M
            font->FontType == ft_GL2_531) &&
1285
2.22M
            (i > 0 || !pdev->charproc_just_accumulated) &&
1286
2.22M
            !(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))){
1287
3.15k
            code = gs_error_undefined;
1288
3.15k
        }
1289
2.21M
        else {
1290
2.21M
            if (font->FontType == ft_PCL_user_defined) {
1291
                /* Check the cache, if the glyph has been flushed, assume that
1292
                 * it has been redefined, and do not use the current glyph.
1293
                 * Additional code in pdf_text_process will also spot this
1294
                 * condition and will not capture the glyph in this font.
1295
                 */
1296
                /* Cache checking code copied from gxchar.c, show_proceed,
1297
                 * case 0, 'plain char'.
1298
                 */
1299
0
                gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
1300
0
                gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
1301
0
                    pte->fstack.items[pte->fstack.depth].font);
1302
0
                int wmode = rfont->WMode;
1303
0
                gs_log2_scale_point log2_scale = {0,0};
1304
0
                gs_fixed_point subpix_origin = {0,0};
1305
0
                cached_fm_pair *pair;
1306
1307
0
                code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pgs), &log2_scale,
1308
0
                    false, &pair);
1309
0
                if (code < 0)
1310
0
                    return code;
1311
0
                if (gx_lookup_cached_char(pfont, pair, ch, wmode,
1312
0
                    1, &subpix_origin) == 0) {
1313
                        /* Character is not in cache, must have been redefined. */
1314
0
                    code = gs_error_undefined;
1315
0
                }
1316
0
                else {
1317
                    /* Character is in cache, go ahead and use it */
1318
0
                    code = pdf_char_widths((gx_device_pdf *)pte->dev,
1319
0
                                   ppts->values.pdfont, ch, font, &cw);
1320
0
                }
1321
0
            } else
1322
                /* Not a PCL bitmap font, we don't need to worry about redefined glyphs */
1323
2.21M
                code = pdf_char_widths((gx_device_pdf *)pte->dev,
1324
2.21M
                                   ppts->values.pdfont, ch, font, &cw);
1325
2.21M
        }
1326
2.22M
        if (code < 0) {
1327
3.15k
            if (i)
1328
2.85k
                break;
1329
303
            *accepted = 0;
1330
303
            return code;
1331
3.15k
        }
1332
2.21M
        pdf_char_widths_to_uts(pdfont, &cw);
1333
2.21M
        w.x += cw.real_width.xy.x;
1334
2.21M
        w.y += cw.real_width.xy.y;
1335
2.21M
        if (cw.real_width.xy.x != cw.Width.xy.x ||
1336
2.21M
            cw.real_width.xy.y != cw.Width.xy.y
1337
2.21M
            )
1338
0
            widths_differ = 1;
1339
2.21M
        if (pstr->data[i] == space_char)
1340
9.62k
            ++num_spaces;
1341
2.21M
        if (cw.BBox.p.x != 0 && cw.BBox.q.x != 0){
1342
0
            if (cw.BBox.p.x < bbox->p.x)
1343
0
                bbox->p.x = cw.BBox.p.x;
1344
0
            if (cw.BBox.p.y < bbox->p.y)
1345
0
                bbox->p.y = cw.BBox.p.y;
1346
0
            if (cw.BBox.q.x > bbox->q.x)
1347
0
                bbox->q.x = cw.BBox.q.x;
1348
0
            if (cw.BBox.q.y > bbox->q.y)
1349
0
                bbox->q.y = cw.BBox.q.y;
1350
0
        }
1351
2.21M
    }
1352
258k
    *accepted = i;
1353
258k
    gs_distance_transform(w.x * ppts->values.size, w.y * ppts->values.size,
1354
258k
                          &ppts->values.matrix, &dpt);
1355
258k
    if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
1356
139k
        int num_chars = *accepted;
1357
139k
        gs_point tpt;
1358
1359
139k
        gs_distance_transform(pte->text.delta_all.x, pte->text.delta_all.y,
1360
139k
                              &ctm_only(pte->pgs), &tpt);
1361
139k
        dpt.x += tpt.x * num_chars;
1362
139k
        dpt.y += tpt.y * num_chars;
1363
139k
    }
1364
258k
    if (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
1365
46.1k
        gs_point tpt;
1366
1367
46.1k
        gs_distance_transform(pte->text.delta_space.x, pte->text.delta_space.y,
1368
46.1k
                              &ctm_only(pte->pgs), &tpt);
1369
46.1k
        dpt.x += tpt.x * num_spaces;
1370
46.1k
        dpt.y += tpt.y * num_spaces;
1371
46.1k
    }
1372
258k
    *pdpt = dpt;
1373
1374
258k
    return widths_differ;
1375
259k
}
1376
1377
/*
1378
 * Emulate TEXT_ADD_TO_ALL_WIDTHS and/or TEXT_ADD_TO_SPACE_WIDTH,
1379
 * and implement TEXT_REPLACE_WIDTHS if requested.
1380
 * Uses and updates ppts->values.matrix; uses ppts->values.pdfont.
1381
 *
1382
 * Destroys the text parameters in *pte.
1383
 * The caller must restore them.
1384
 */
1385
int
1386
process_text_modify_width(pdf_text_enum_t *pte, gs_font *font,
1387
                          pdf_text_process_state_t *ppts,
1388
                          const gs_const_string *pstr,
1389
                          gs_point *pdpt, const gs_glyph *gdata, bool composite, int decoded_bytes)
1390
1.08M
{
1391
1.08M
    gx_device_pdf *const pdev = (gx_device_pdf *)pte->dev;
1392
1.08M
    int space_char =
1393
1.08M
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
1394
827k
         pte->text.space.s_char : -1);
1395
1.08M
    gs_point start, total;
1396
1.08M
    pdf_font_resource_t *pdfont3 = NULL;
1397
1.08M
    int code;
1398
1399
1.08M
    if (font->FontType == ft_user_defined ||
1400
1.08M
        font->FontType == ft_PDF_user_defined ||
1401
1.08M
        font->FontType == ft_PCL_user_defined ||
1402
1.08M
        font->FontType == ft_MicroType ||
1403
1.08M
        font->FontType == ft_GL2_stick_user_defined ||
1404
1.08M
        font->FontType == ft_GL2_531) {
1405
2.28k
        code = pdf_attached_font_resource(pdev, font, &pdfont3, NULL, NULL, NULL, NULL);
1406
2.28k
        if (code < 0)
1407
0
            return code;
1408
1409
2.28k
    }
1410
1.08M
    pte->text.data.bytes = pstr->data;
1411
1.08M
    pte->text.size = pstr->size;
1412
1.08M
    pte->index = 0;
1413
1.08M
    pte->text.operation &= ~TEXT_FROM_ANY;
1414
1.08M
    pte->text.operation |= TEXT_FROM_STRING;
1415
1.08M
    start.x = ppts->values.matrix.tx;
1416
1.08M
    start.y = ppts->values.matrix.ty;
1417
1.08M
    total.x = total.y = 0;  /* user space */
1418
    /*
1419
     * Note that character widths are in design space, but text.delta_*
1420
     * values and the width value returned in *pdpt are in user space,
1421
     * and the width values for pdf_append_chars are in device space.
1422
     */
1423
4.86M
    for (;;) {
1424
4.86M
        pdf_glyph_widths_t cw;  /* design space, then converted to PDF text space */
1425
4.86M
        gs_point did, wanted, tpt;  /* user space */
1426
4.86M
        gs_point v = {0, 0}; /* design space */
1427
4.86M
        gs_char chr;
1428
4.86M
        gs_glyph glyph;
1429
4.86M
        int index = pte->index;
1430
4.86M
        gs_text_enum_t pte1 = *(gs_text_enum_t *)pte;
1431
4.86M
        int FontType;
1432
4.86M
        bool use_cached_v = true;
1433
4.86M
        byte composite_type3_text[1];
1434
1435
4.86M
        code = pte1.orig_font->procs.next_char_glyph(&pte1, &chr, &glyph);
1436
4.86M
        if (code == 2) { /* end of string */
1437
1.08M
            gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true);
1438
1.08M
            break;
1439
1.08M
        }
1440
3.77M
        if (code < 0)
1441
0
            return code;
1442
3.77M
        if (composite) { /* from process_cmap_text */
1443
23.8k
            gs_font *subfont = pte1.fstack.items[pte1.fstack.depth].font;
1444
1445
23.8k
            if (subfont->FontType == ft_user_defined || subfont->FontType == ft_PDF_user_defined ) {
1446
0
                pdf_font_resource_t *pdfont;
1447
1448
0
                FontType = subfont->FontType;
1449
0
                code = pdf_attached_font_resource(pdev, subfont,
1450
0
                            &pdfont, NULL, NULL, NULL, NULL);
1451
0
                if (code < 0)
1452
0
                    return code;
1453
0
                chr = pdf_find_glyph(pdfont, glyph);
1454
0
                composite_type3_text[0] = (byte)chr;
1455
0
                code = pdf_char_widths((gx_device_pdf *)pte->dev,
1456
0
                                       ppts->values.pdfont, chr, (gs_font_base *)subfont,
1457
0
                                       &cw);
1458
23.8k
            } else {
1459
23.8k
                pdf_font_resource_t *pdsubf = ppts->values.pdfont->u.type0.DescendantFont;
1460
1461
23.8k
                FontType = pdsubf->FontType;
1462
23.8k
                code = pdf_glyph_widths(pdsubf, font->WMode, glyph, subfont, &cw,
1463
23.8k
                    pte->cdevproc_callout ? pte->cdevproc_result : NULL);
1464
23.8k
            }
1465
3.75M
        } else {/* must be a base font */
1466
3.75M
            const gs_glyph *gdata_i = (gdata != NULL ? gdata + pte->index : 0);
1467
1468
                /* gdata is NULL when composite == true, or the text isn't a single byte.  */
1469
3.75M
            code = pdf_encode_string_element(pdev, font, ppts->values.pdfont, chr, gdata_i);
1470
3.75M
            FontType = font->FontType;
1471
3.75M
            if (code >= 0) {
1472
3.75M
                if (chr == GS_NO_CHAR && glyph != GS_NO_GLYPH) {
1473
                    /* glyphshow, we have no char code. Bug 686988.*/
1474
0
                    code = pdf_glyph_widths(ppts->values.pdfont, font->WMode, glyph, font, &cw, NULL);
1475
0
                    use_cached_v = false; /* Since we have no chr and don't call pdf_char_widths. */
1476
3.75M
                } else {
1477
3.75M
                    code = pdf_char_widths((gx_device_pdf *)pte->dev,
1478
3.75M
                                       ppts->values.pdfont, chr, (gs_font_base *)font,
1479
3.75M
                                       &cw);
1480
3.75M
                    if (code == 0 && font->FontType == ft_PCL_user_defined) {
1481
                        /* Check the cache, if the glyph has been flushed, assume that
1482
                         * it has been redefined, and do not use the current glyph.
1483
                         * Additional code in pdf_text_process will also spot this
1484
                         * condition and will not capture the glyph in this font.
1485
                         */
1486
                        /* Cache checking code copied from gxchar.c, show_proceed,
1487
                         * case 0, 'plain char'.
1488
                         */
1489
0
                        gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
1490
0
                        gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
1491
0
                            pte->fstack.items[pte->fstack.depth].font);
1492
0
                        int wmode = rfont->WMode;
1493
0
                        gs_log2_scale_point log2_scale = {0,0};
1494
0
                        gs_fixed_point subpix_origin = {0,0};
1495
0
                        cached_fm_pair *pair;
1496
1497
0
                        code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pgs), &log2_scale,
1498
0
                            false, &pair);
1499
0
                        if (code < 0)
1500
0
                            return code;
1501
0
                        if (gx_lookup_cached_char(pfont, pair, chr, wmode,
1502
0
                            1, &subpix_origin) == 0) {
1503
                        /* Character is not in cache, must have been redefined. */
1504
0
                            code = gs_error_undefined;
1505
0
                        }
1506
0
                    }
1507
3.75M
                }
1508
3.75M
            }
1509
3.75M
        }
1510
3.77M
        if (code < 0) {
1511
1.57k
            if (index > 0)
1512
1.00k
                break;
1513
571
            return code;
1514
1.57k
        }
1515
        /* TrueType design grid is 2048x2048 against the nominal PS/PDF grid of
1516
         * 1000x1000. This can lead to rounding errors when converting to text space
1517
         * and comparing against any entries in /W or /Widths arrays. We fix the
1518
         * TrueType widths to the nearest integer here to avoid this.
1519
         * See Bug #693825
1520
         */
1521
3.77M
        if (FontType == ft_CID_TrueType || FontType == ft_TrueType) {
1522
515k
            cw.Width.w = floor(cw.Width.w + 0.5);
1523
515k
            cw.Width.xy.x = floor(cw.Width.xy.x + 0.5);
1524
515k
            cw.Width.xy.y = floor(cw.Width.xy.y + 0.5);
1525
515k
            cw.Width.v.x = floor(cw.Width.v.x + 0.5);
1526
515k
            cw.Width.v.y = floor(cw.Width.v.y + 0.5);
1527
515k
            cw.real_width.w = floor(cw.real_width.w + 0.5);
1528
515k
            cw.real_width.xy.x = floor(cw.real_width.xy.x + 0.5);
1529
515k
            cw.real_width.xy.y = floor(cw.real_width.xy.y + 0.5);
1530
515k
            cw.real_width.v.x = floor(cw.real_width.v.x + 0.5);
1531
515k
            cw.real_width.v.y = floor(cw.real_width.v.y + 0.5);
1532
515k
        }
1533
1534
3.77M
        gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true);
1535
3.77M
        if (composite || !use_cached_v) {
1536
23.8k
            if (cw.replaced_v) {
1537
23.6k
                v.x = cw.real_width.v.x - cw.Width.v.x;
1538
23.6k
                v.y = cw.real_width.v.y - cw.Width.v.y;
1539
23.6k
            }
1540
23.8k
        } else
1541
3.75M
            v = ppts->values.pdfont->u.simple.v[chr];
1542
3.77M
        if (font->WMode && !cw.ignore_wmode) {
1543
            /* With WMode 1 v-vector is (WMode 1 origin) - (WMode 0 origin).
1544
               The glyph shifts in the opposite direction.  */
1545
191
            v.x = - v.x;
1546
191
            v.y = - v.y;
1547
3.77M
        } else {
1548
            /* With WMode 0 v-vector is (Metrics sb) - (native sb).
1549
               The glyph shifts in same direction.  */
1550
3.77M
        }
1551
        /* pdf_glyph_origin is not longer used. */
1552
3.77M
        if (v.x != 0 || v.y != 0) {
1553
8.60k
            gs_point glyph_origin_shift;
1554
8.60k
            double scale0;
1555
1556
8.60k
            if (FontType == ft_TrueType || FontType == ft_CID_TrueType)
1557
8.45k
                scale0 = (float)0.001;
1558
153
            else
1559
153
                scale0 = 1;
1560
8.60k
            glyph_origin_shift.x = v.x * scale0;
1561
8.60k
            glyph_origin_shift.y = v.y * scale0;
1562
8.60k
            if (composite) {
1563
925
                gs_font *subfont = pte->fstack.items[pte->fstack.depth].font;
1564
1565
925
                gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1566
925
                                      &subfont->FontMatrix, &glyph_origin_shift);
1567
925
            }
1568
8.60k
            gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1569
8.60k
                                  &font->FontMatrix, &glyph_origin_shift);
1570
8.60k
            gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1571
8.60k
                                  &ctm_only(pte->pgs), &glyph_origin_shift);
1572
8.60k
            if (glyph_origin_shift.x != 0 || glyph_origin_shift.y != 0) {
1573
8.60k
                ppts->values.matrix.tx = start.x + total.x + glyph_origin_shift.x;
1574
8.60k
                ppts->values.matrix.ty = start.y + total.y + glyph_origin_shift.y;
1575
8.60k
                code = pdf_set_text_state_values(pdev, &ppts->values);
1576
8.60k
                if (code < 0)
1577
0
                    break;
1578
8.60k
            }
1579
8.60k
        }
1580
3.77M
        pdf_char_widths_to_uts(pdfont3, &cw); /* convert design->text space */
1581
3.77M
        if (pte->text.operation & (TEXT_DO_DRAW | TEXT_RENDER_MODE_3)) {
1582
3.75M
            gs_distance_transform(cw.Width.xy.x * ppts->values.size,
1583
3.75M
                                  cw.Width.xy.y * ppts->values.size,
1584
3.75M
                                  &ppts->values.matrix, &did);
1585
3.75M
            gs_distance_transform(((font->WMode && !cw.ignore_wmode) ? 0 : ppts->values.character_spacing),
1586
3.75M
                                  ((font->WMode && !cw.ignore_wmode) ? ppts->values.character_spacing : 0),
1587
3.75M
                                  &ppts->values.matrix, &tpt);
1588
3.75M
            did.x += tpt.x;
1589
3.75M
            did.y += tpt.y;
1590
            /* If pte->single_byte_space == 0 then we had a widthshow or awidthshow from
1591
             * PostScript, so we apply the PostScript rules. Otherwise it was from PDF
1592
             * in which case if the number of bytes in the character code was 1 we apply
1593
             * word spacing. If it was PDF and we had a multi-byte decode, do not apply
1594
             * word spacing (how ugly!). Note tht its important this is applied the same to
1595
             * both the 'did' and 'wanted' calculations (see below).
1596
             */
1597
3.75M
            if (chr == space_char && (!pte->single_byte_space || decoded_bytes == 1)) {
1598
52.0k
                gs_distance_transform(((font->WMode && !cw.ignore_wmode)? 0 : ppts->values.word_spacing),
1599
52.0k
                                      ((font->WMode && !cw.ignore_wmode) ? ppts->values.word_spacing : 0),
1600
52.0k
                                      &ppts->values.matrix, &tpt);
1601
52.0k
                did.x += tpt.x;
1602
52.0k
                did.y += tpt.y;
1603
52.0k
            }
1604
3.75M
            if (composite && (FontType == ft_user_defined || FontType == ft_PDF_user_defined))
1605
0
                code = pdf_append_chars(pdev, composite_type3_text, 1, did.x, did.y, composite);
1606
3.75M
            else
1607
3.75M
                code = pdf_append_chars(pdev, pstr->data + index, pte->index - index, did.x, did.y, composite);
1608
3.75M
            if (code < 0)
1609
0
                break;
1610
3.75M
        } else
1611
17.1k
            did.x = did.y = 0;
1612
3.77M
        if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
1613
3.75M
            gs_point dpt;
1614
1615
            /* We are applying a width override, from x/y/xyshow. This coudl be from
1616
             * a PostScript file, or it could be from a PDF file where we have a font
1617
             * with a FontMatrix which is neither horizontal nor vertical. If we use TJ
1618
             * for that, then we end up applying the displacement twice, once here where
1619
             * we add a TJ, and once when we actually draw the glyph (TJ is added *after*
1620
             * the glyph is drawn, unlike xshow). So in this case we don't want to try
1621
             * and use a TJ, we need to position the glyphs using text positioning
1622
             * operators.
1623
             */
1624
3.75M
            if(cw.Width.xy.x != cw.real_width.xy.x || cw.Width.xy.y != cw.real_width.xy.y)
1625
0
                pdev->text->text_state->can_use_TJ = false;
1626
1627
3.75M
            code = gs_text_replaced_width(&pte->text, pte->xy_index++, &dpt);
1628
3.75M
            if (code < 0)
1629
0
                return_error(gs_error_unregistered);
1630
3.75M
            gs_distance_transform(dpt.x, dpt.y, &ctm_only(pte->pgs), &wanted);
1631
1632
3.75M
            gs_distance_transform(((font->WMode && !cw.ignore_wmode) ? 0 : ppts->values.character_spacing),
1633
3.75M
                                  ((font->WMode && !cw.ignore_wmode) ? ppts->values.character_spacing : 0),
1634
3.75M
                                  &ppts->values.matrix, &tpt);
1635
3.75M
            wanted.x += tpt.x;
1636
3.75M
            wanted.y += tpt.y;
1637
1638
3.75M
            if (chr == space_char && (!pte->single_byte_space || decoded_bytes == 1)) {
1639
52.0k
                gs_distance_transform(((font->WMode && !cw.ignore_wmode)? 0 : ppts->values.word_spacing),
1640
52.0k
                                      ((font->WMode && !cw.ignore_wmode) ? ppts->values.word_spacing : 0),
1641
52.0k
                                      &ppts->values.matrix, &tpt);
1642
52.0k
                wanted.x += tpt.x;
1643
52.0k
                wanted.y += tpt.y;
1644
52.0k
            }
1645
3.75M
        } else {
1646
23.8k
            pdev->text->text_state->can_use_TJ = true;
1647
23.8k
            gs_distance_transform(cw.real_width.xy.x * ppts->values.size,
1648
23.8k
                                  cw.real_width.xy.y * ppts->values.size,
1649
23.8k
                                  &ppts->values.matrix, &wanted);
1650
23.8k
            if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
1651
986
                gs_distance_transform(pte->text.delta_all.x,
1652
986
                                      pte->text.delta_all.y,
1653
986
                                      &ctm_only(pte->pgs), &tpt);
1654
986
                wanted.x += tpt.x;
1655
986
                wanted.y += tpt.y;
1656
986
            }
1657
            /* See comment above for 'did' calculations, the application of word spacing must
1658
             * be the same for did and wanted.
1659
             */
1660
23.8k
            if (chr == space_char && (!pte->single_byte_space || decoded_bytes == 1)) {
1661
0
                gs_distance_transform(pte->text.delta_space.x,
1662
0
                                      pte->text.delta_space.y,
1663
0
                                      &ctm_only(pte->pgs), &tpt);
1664
0
                wanted.x += tpt.x;
1665
0
                wanted.y += tpt.y;
1666
0
            }
1667
23.8k
        }
1668
3.77M
        total.x += wanted.x;
1669
3.77M
        total.y += wanted.y;
1670
3.77M
        if (wanted.x != did.x || wanted.y != did.y) {
1671
3.73M
            ppts->values.matrix.tx = start.x + total.x;
1672
3.73M
            ppts->values.matrix.ty = start.y + total.y;
1673
3.73M
            code = pdf_set_text_state_values(pdev, &ppts->values);
1674
3.73M
            if (code < 0)
1675
0
                break;
1676
3.73M
        }
1677
3.77M
        pdev->charproc_just_accumulated = false;
1678
3.77M
    }
1679
1.08M
    *pdpt = total;
1680
1.08M
    return 0;
1681
1.08M
}
1682
1683
/*
1684
 * Get character code from a glyph code.
1685
 * An usage of this function is very undesirable,
1686
 * because a glyph may be unlisted in Encoding.
1687
 */
1688
int
1689
pdf_encode_glyph(gs_font_base *bfont, gs_glyph glyph0,
1690
            byte *buf, int buf_size, int *char_code_length)
1691
0
{
1692
0
    gs_char c;
1693
1694
0
    *char_code_length = 1;
1695
0
    if (*char_code_length > buf_size)
1696
0
        return_error(gs_error_rangecheck); /* Must not happen. */
1697
0
    for (c = 0; c < 255; c++) {
1698
0
        gs_glyph glyph1 = bfont->procs.encode_char((gs_font *)bfont, c,
1699
0
                    GLYPH_SPACE_NAME);
1700
0
        if (glyph1 == glyph0) {
1701
0
            buf[0] = (byte)c;
1702
0
            return 0;
1703
0
        }
1704
0
    }
1705
0
    return_error(gs_error_rangecheck); /* Can't encode. */
1706
0
}
1707
1708
/* ---------------- Type 1 or TrueType font ---------------- */
1709
1710
/*
1711
 * Process a text string in a simple font.
1712
 */
1713
int
1714
process_plain_text(gs_text_enum_t *pte, void *vbuf, uint bsize)
1715
1.49M
{
1716
1.49M
    byte *const buf = vbuf;
1717
1.49M
    uint count;
1718
1.49M
    uint operation = pte->text.operation;
1719
1.49M
    pdf_text_enum_t *penum = (pdf_text_enum_t *)pte;
1720
1.49M
    int code;
1721
1.49M
    gs_string str;
1722
1.49M
    pdf_text_process_state_t text_state;
1723
1.49M
    const gs_glyph *gdata = NULL;
1724
1725
1.49M
    if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) {
1726
1.49M
        count = pte->text.size - pte->index;
1727
1.49M
        if (bsize < count)
1728
0
            return_error(gs_error_unregistered); /* Must not happen. */
1729
1.49M
        memcpy(buf, (const byte *)pte->text.data.bytes + pte->index, count);
1730
1.49M
    } else if (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR)) {
1731
        /* Check that all chars fit in a single byte. */
1732
2.32k
        const gs_char *cdata;
1733
2.32k
        int i;
1734
1735
2.32k
        if (operation & TEXT_FROM_CHARS) {
1736
2.32k
            cdata = pte->text.data.chars;
1737
2.32k
            count = (pte->text.size - pte->index);
1738
2.32k
        } else {
1739
0
            cdata = &pte->text.data.d_char;
1740
0
            count = 1;
1741
0
        }
1742
2.32k
        if (bsize < count * sizeof(gs_char))
1743
0
            return_error(gs_error_unregistered); /* Must not happen. */
1744
19.8k
        for (i = 0; i < count; ++i) {
1745
17.5k
            gs_char chr = cdata[pte->index + i];
1746
1747
17.5k
            if (chr & ~0xff)
1748
0
                return_error(gs_error_rangecheck);
1749
17.5k
            buf[i] = (byte)chr;
1750
17.5k
        }
1751
2.32k
    } else if (operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH)) {
1752
        /*
1753
         * Since PDF has no analogue of 'glyphshow',
1754
         * we try to encode glyphs with the current
1755
         * font's encoding. If the current font has no encoding,
1756
         * or the encoding doesn't contain necessary glyphs,
1757
         * the text will be represented with a Type 3 font with
1758
         * bitmaps or outlines.
1759
         *
1760
         * When we fail with encoding (136-01.ps is an example),
1761
         * we could locate a PDF font resource or create a new one
1762
         * with same outlines and an appropriate encoding.
1763
         * Also we could change .notdef entries in the
1764
         * copied font (assuming that document designer didn't use
1765
         * .notdef for a meanful printing).
1766
         * fixme: Not implemented yet.
1767
         */
1768
0
        gs_font *font = pte->current_font;
1769
0
        uint size;
1770
0
        int i;
1771
1772
0
        if (operation & TEXT_FROM_GLYPHS) {
1773
0
            gdata = pte->text.data.glyphs;
1774
0
            size = pte->text.size - pte->index;
1775
0
        } else {
1776
0
            gdata = &pte->text.data.d_glyph;
1777
0
            size = 1;
1778
0
        }
1779
0
        if (!pdf_is_simple_font(font))
1780
0
            return_error(gs_error_unregistered); /* Must not happen. */
1781
0
        count = 0;
1782
0
        for (i = 0; i < size; ++i) {
1783
0
            pdf_font_resource_t *pdfont;
1784
0
            gs_glyph glyph = gdata[pte->index + i];
1785
0
            int char_code_length;
1786
1787
0
            code = pdf_encode_glyph((gs_font_base *)font, glyph,
1788
0
                         buf + count, size - count, &char_code_length);
1789
0
            if (code < 0)
1790
0
                break;
1791
            /* Even if we already have a glyph encoded at this position in the font
1792
             * it may not be the *right* glyph. We effectively use the first byte of
1793
             * the glyph name as the index when using glyphshow which means that
1794
             * /o and /omicron would be encoded at the same index. So we need
1795
             * to check the actual glyph to see if they are the same. To do
1796
             * that we need the PDF font resource which is attached to the font (if any).
1797
             * cf bugs #695259 and #695168
1798
             */
1799
0
            code = pdf_attached_font_resource((gx_device_pdf *)penum->dev, font,
1800
0
                            &pdfont, NULL, NULL, NULL, NULL);
1801
0
            if (code >= 0 && pdfont && pdfont->u.simple.Encoding[*(buf + count)].glyph != glyph)
1802
                /* the glyph doesn't match the glyph already encoded at this position.
1803
                 * Breaking out here will start a new PDF font resource in the code below.
1804
                 */
1805
0
                break;
1806
0
            count += char_code_length;
1807
0
            if (operation & TEXT_INTERVENE)
1808
0
                break; /* Just do one character. */
1809
0
        }
1810
0
        if (i < size) {
1811
0
            pdf_font_resource_t *pdfont;
1812
1813
0
            str.data = buf;
1814
0
            str.size = size;
1815
0
            code = pdf_obtain_font_resource_unencoded(penum, &str, &pdfont, gdata);
1816
0
            if (code < 0) {
1817
                /*
1818
                 * pdf_text_process will fall back
1819
                 * to default implementation.
1820
                 */
1821
0
                return code;
1822
0
            }
1823
0
            count = size;
1824
0
        }
1825
        /*  So far we will use TEXT_FROM_STRING instead
1826
            TEXT_FROM_*_GLYPH*. Since we used a single
1827
            byte encoding, the character index appears invariant
1828
            during this substitution.
1829
         */
1830
0
    } else
1831
0
        return_error(gs_error_rangecheck);
1832
1.49M
    str.data = buf;
1833
1.49M
    if (count > 1 && (operation & TEXT_INTERVENE)) {
1834
        /* Just do one character. */
1835
0
        str.size = 1;
1836
0
        code = pdf_process_string_aux(penum, &str, gdata, NULL, &text_state);
1837
0
        if (code >= 0) {
1838
0
            pte->returned.current_char = buf[0];
1839
0
            code = TEXT_PROCESS_INTERVENE;
1840
0
        }
1841
1.49M
    } else {
1842
1.49M
        str.size = count;
1843
1.49M
        code = pdf_process_string_aux(penum, &str, gdata, NULL, &text_state);
1844
1.49M
    }
1845
1.49M
    return code;
1846
1.49M
}