Coverage Report

Created: 2026-09-14 07:34

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