Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/devices/vector/gdevpdte.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 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.98M
{
65
4.98M
    gs_font_base *font = (gs_font_base *)penum->current_font;
66
67
4.98M
    switch (font->FontType) {
68
200k
    case ft_TrueType:
69
3.90M
    case ft_encrypted:
70
4.61M
    case ft_encrypted2:
71
4.93M
    case ft_user_defined:
72
4.98M
    case ft_PDF_user_defined:
73
4.98M
    case ft_PCL_user_defined:
74
4.98M
    case ft_GL2_stick_user_defined:
75
4.98M
    case ft_GL2_531:
76
4.98M
    case ft_MicroType:
77
4.98M
        break;
78
0
    default:
79
0
        return_error(gs_error_rangecheck);
80
4.98M
    }
81
4.98M
    return pdf_process_string(penum, pstr, pfmat, ppts, gdata);
82
4.98M
}
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, 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, 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
728k
{   int code = 0;
322
728k
    gs_char length = 0;
323
728k
    ushort *unicode = 0;
324
325
728k
    if (glyph == GS_NO_GLYPH)
326
0
        return 0;
327
728k
    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
728k
    else {
333
728k
        length = font->procs.decode_glyph((gs_font *)font, glyph, ch, NULL, 0);
334
728k
        if(length == 0 || length == GS_NO_CHAR) {
335
602k
            if(gnstr != NULL && gnstr->size == 7) {
336
56.2k
                if(!memcmp(gnstr->data, "uni", 3)) {
337
452
                    static const char *hexdigits = "0123456789ABCDEF";
338
452
                    char *d0 = strchr(hexdigits, gnstr->data[3]);
339
452
                    char *d1 = strchr(hexdigits, gnstr->data[4]);
340
452
                    char *d2 = strchr(hexdigits, gnstr->data[5]);
341
452
                    char *d3 = strchr(hexdigits, gnstr->data[6]);
342
343
452
                    unicode = (ushort *)gs_alloc_bytes(pdev->memory, sizeof(ushort), "temporary Unicode array");
344
452
                    if (unicode == NULL)
345
0
                        return_error(gs_error_VMerror);
346
347
452
                    if(d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) {
348
452
                        char *u = (char *)unicode;
349
452
                        u[0] = ((d0 - hexdigits) << 4) + ((d1 - hexdigits));
350
452
                        u[1] = ((d2 - hexdigits) << 4) + ((d3 - hexdigits));
351
452
                        length = 2;
352
452
                    }
353
452
                }
354
56.2k
            }
355
545k
            else {
356
545k
                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
545k
            }
362
602k
        }
363
728k
    }
364
365
728k
    if (length != 0 && length != GS_NO_CHAR) {
366
126k
        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.91k
            uint num_codes = 256, key_size = 1;
378
379
2.91k
            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.91k
            } else if (font->FontType == ft_CID_TrueType || font->FontType == ft_composite) {
385
205
                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
205
                num_codes = 65536;
392
205
            }
393
2.91k
            code = gs_cmap_ToUnicode_alloc(pdev->pdf_memory, pdfont->rid, num_codes, key_size, length,
394
2.91k
                                            &pdfont->cmap_ToUnicode);
395
2.91k
            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
123k
        } else {
401
123k
            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
123k
        }
407
408
126k
        if (!unicode) {
409
126k
            unicode = (ushort *)gs_alloc_bytes(pdev->memory, length * sizeof(short), "temporary Unicode array");
410
126k
            if (unicode == NULL)
411
0
                return_error(gs_error_VMerror);
412
126k
            length = font->procs.decode_glyph((gs_font *)font, glyph, ch, unicode, length);
413
126k
        }
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
126k
        if (pdfont->cmap_ToUnicode != NULL) {
435
126k
            if (pdfont->u.simple.Encoding != NULL) {
436
110k
                if (length <= 2)
437
110k
                    gs_cmap_ToUnicode_add_pair(pdfont->cmap_ToUnicode, ch, unicode, length);
438
110k
            } else
439
16.1k
                gs_cmap_ToUnicode_add_pair(pdfont->cmap_ToUnicode, ch, unicode, length);
440
126k
        }
441
126k
    }
442
443
728k
    if (unicode)
444
126k
        gs_free_object(pdev->memory, unicode, "temporary Unicode array");
445
728k
    return 0;
446
728k
}
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
470k
{
488
470k
    if (pdfont->where_used & pdev->used_mask)
489
458k
        return 0;
490
11.6k
    pdfont->where_used |= pdev->used_mask;
491
11.6k
    if (pdev->CompatibilityLevel >= 1.2)
492
11.6k
        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
19.2M
{
519
19.2M
    gs_font_base *cfont, *ccfont;
520
19.2M
    int code;
521
19.2M
    gs_glyph copied_glyph;
522
19.2M
    gs_const_string gnstr;
523
19.2M
    pdf_encoding_element_t *pet;
524
19.2M
    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
19.2M
    cfont = pdf_font_resource_font(pdfont, false);
531
19.2M
    ccfont = pdf_font_resource_font(pdfont, true);
532
19.2M
    pet = &pdfont->u.simple.Encoding[ch];
533
19.2M
    glyph = (gdata == NULL ? font->procs.encode_char(font, ch, GLYPH_SPACE_NAME)
534
19.2M
                           : *gdata);
535
19.2M
    if (glyph == GS_NO_GLYPH || glyph == pet->glyph) {
536
18.5M
        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
18.5M
        return 0;
539
18.5M
    }
540
649k
    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
649k
    code = font->procs.glyph_name(font, glyph, &gnstr);
547
649k
    if (code < 0)
548
0
        return code; /* can't get name of glyph */
549
649k
    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
649k
    if (font->FontType != ft_user_defined &&
584
649k
        font->FontType != ft_PDF_user_defined &&
585
649k
        font->FontType != ft_PCL_user_defined &&
586
649k
        font->FontType != ft_MicroType &&
587
649k
        font->FontType != ft_GL2_stick_user_defined &&
588
649k
        font->FontType != ft_GL2_531) {
589
        /* The standard 14 fonts don't have a FontDescriptor. */
590
631k
        code = (pdfont->base_font != 0 ?
591
131k
                pdf_base_font_copy_glyph(pdfont->base_font, glyph, (gs_font_base *)font) :
592
631k
                pdf_font_used_glyph(pdfont->FontDescriptor, glyph, (gs_font_base *)font));
593
631k
        if (code < 0 && code != gs_error_undefined)
594
7.64k
            return code;
595
623k
        if (code == gs_error_undefined) {
596
9.44k
            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
9.44k
            if (bytes_compare(gnstr.data, gnstr.size, (const byte *)".notdef", 7)) {
632
9.44k
                pet->glyph = glyph;
633
9.44k
                pdf_copy_string_to_encoding(pdev, &gnstr, pet);
634
9.44k
                pet->is_difference = true;
635
9.44k
            }
636
614k
        } else if (pdfont->base_font == NULL && ccfont != NULL &&
637
614k
                (gs_copy_glyph_options(font, glyph, (gs_font *)ccfont, COPY_GLYPH_NO_NEW) != 1 ||
638
468k
                    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
788
            ccfont = NULL;
654
788
            pdf_font_descriptor_drop_complete_font(pdfont->FontDescriptor);
655
788
        }
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
623k
        copied_glyph = cfont->procs.encode_char((gs_font *)cfont, ch,
662
623k
                                                GLYPH_SPACE_NAME);
663
623k
        if (glyph != copied_glyph &&
664
623k
            gs_copied_font_add_encoding((gs_font *)cfont, ch, glyph) < 0
665
623k
            )
666
9.45k
            pet->is_difference = true;
667
623k
        pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
668
623k
    }
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
641k
    code = pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, &gnstr);
675
641k
    if(code < 0)
676
0
        return code;
677
641k
    pet->glyph = glyph;
678
641k
    return pdf_copy_string_to_encoding(pdev, &gnstr, pet);
679
641k
}
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.35M
{
690
4.35M
    int i;
691
4.35M
    int space_char =
692
4.35M
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
693
4.18M
         pte->text.space.s_char : -1);
694
4.35M
    int WMode = font->WMode;
695
4.35M
    int code = 0;
696
4.35M
    gs_point total = {0, 0};
697
4.35M
    gs_point p0, p1, p2, p3;
698
4.35M
    gs_fixed_point origin;
699
4.35M
    gs_matrix m;
700
4.35M
    int xy_index = pte->xy_index, info_flags = 0;
701
4.35M
    gx_path *path = gs_text_enum_path(pte);
702
703
4.35M
    code = gx_path_current_point(path, &origin);
704
4.35M
    if (code < 0)
705
0
        return code;
706
4.35M
    m = ctm_only(pte->pgs);
707
4.35M
    m.tx = fixed2float(origin.x);
708
4.35M
    m.ty = fixed2float(origin.y);
709
4.35M
    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.35M
    if (font->FontBBox.p.x == font->FontBBox.q.x ||
715
4.35M
        font->FontBBox.p.y == font->FontBBox.q.y) {
716
301k
            info_flags = GLYPH_INFO_BBOX | GLYPH_INFO_WIDTH0 << WMode;
717
4.05M
    } else {
718
4.05M
        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.05M
        gs_point_transform(font->FontBBox.p.x, font->FontBBox.p.y, &font->FontMatrix, &p0);
738
4.05M
        gs_point_transform(font->FontBBox.p.x, font->FontBBox.q.y, &font->FontMatrix, &p1);
739
4.05M
        gs_point_transform(font->FontBBox.q.x, font->FontBBox.p.y, &font->FontMatrix, &p2);
740
4.05M
        gs_point_transform(font->FontBBox.q.x, font->FontBBox.q.y, &font->FontMatrix, &p3);
741
4.05M
        width = max(fabs(p2.x), fabs(p3.x)) - p0.x;
742
4.05M
        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.05M
        if (fabs(width) < 0.1 || fabs(height) < 0.1) {
749
5.23k
            info_flags = GLYPH_INFO_BBOX | GLYPH_INFO_WIDTH0 << WMode;
750
4.05M
        } else {
751
4.05M
            gs_point_transform(font->FontBBox.p.x, font->FontBBox.p.y, &m, &p0);
752
4.05M
            gs_point_transform(font->FontBBox.p.x, font->FontBBox.q.y, &m, &p1);
753
4.05M
            gs_point_transform(font->FontBBox.q.x, font->FontBBox.p.y, &m, &p2);
754
4.05M
            gs_point_transform(font->FontBBox.q.x, font->FontBBox.q.y, &m, &p3);
755
4.05M
            info_flags = GLYPH_INFO_WIDTH0 << WMode;
756
4.05M
        }
757
4.05M
    }
758
759
21.7M
    for (i = 0; i < pstr->size; ++i) {
760
18.0M
        byte c = pstr->data[i];
761
18.0M
        gs_rect bbox;
762
18.0M
        gs_point wanted, tpt;
763
18.0M
        gs_glyph glyph = font->procs.encode_char((gs_font *)font, c,
764
18.0M
                                        GLYPH_SPACE_NAME);
765
18.0M
        gs_glyph_info_t info;
766
18.0M
        int code;
767
768
18.0M
        if (glyph == GS_NO_GLYPH)
769
53
            return_error (gs_error_invalidfont);
770
771
18.0M
        memset(&info, 0x00, sizeof(gs_glyph_info_t));
772
18.0M
        code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
773
18.0M
                                            info_flags,
774
18.0M
                                            &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
18.0M
        if (code < 0) {
786
677k
            if ((font->FontType == ft_encrypted ||
787
677k
            font->FontType == ft_encrypted2)) {
788
326k
                int index;
789
790
326k
                for (index = 0;
791
326k
                    (font->procs.enumerate_glyph((gs_font *)font, &index,
792
326k
                    (GLYPH_SPACE_NAME), &glyph)) >= 0 &&
793
326k
                    index != 0;) {
794
795
326k
                    if (gs_font_glyph_is_notdef(font, glyph)) {
796
2.63k
                        code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
797
2.63k
                                            info_flags,
798
2.63k
                                            &info);
799
800
2.63k
                    if (code < 0)
801
0
                        return code;
802
2.63k
                    }
803
326k
                    break;
804
326k
                }
805
326k
            }
806
677k
            if (code < 0)
807
674k
                return code;
808
677k
        }
809
17.3M
        if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
810
9.55M
            code = gs_text_replaced_width(&pte->text, xy_index++, &tpt);
811
9.55M
            if (code < 0)
812
0
                return code;
813
814
9.55M
            gs_distance_transform(tpt.x, tpt.y, &ctm_only(pte->pgs), &wanted);
815
9.55M
        } else {
816
7.84M
            gs_distance_transform(info.width[WMode].x,
817
7.84M
                                  info.width[WMode].y,
818
7.84M
                                  &m, &wanted);
819
7.84M
            if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
820
926k
                gs_distance_transform(pte->text.delta_all.x,
821
926k
                                      pte->text.delta_all.y,
822
926k
                                      &ctm_only(pte->pgs), &tpt);
823
926k
                wanted.x += tpt.x;
824
926k
                wanted.y += tpt.y;
825
926k
            }
826
7.84M
            if (pstr->data[i] == space_char && pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
827
10.6k
                gs_distance_transform(pte->text.delta_space.x,
828
10.6k
                                      pte->text.delta_space.y,
829
10.6k
                                      &ctm_only(pte->pgs), &tpt);
830
10.6k
                wanted.x += tpt.x;
831
10.6k
                wanted.y += tpt.y;
832
10.6k
            }
833
7.84M
        }
834
835
17.3M
        if (info_flags & GLYPH_INFO_BBOX) {
836
184k
            gs_point_transform(info.bbox.p.x, info.bbox.p.x, &m, &p0);
837
184k
            gs_point_transform(info.bbox.p.x, info.bbox.q.y, &m, &p1);
838
184k
            gs_point_transform(info.bbox.q.x, info.bbox.p.y, &m, &p2);
839
184k
            gs_point_transform(info.bbox.q.x, info.bbox.q.y, &m, &p3);
840
184k
        }
841
842
17.3M
        bbox.p.x = min(min(p0.x, p1.x), min(p2.x, p3.x));
843
17.3M
        bbox.p.y = min(min(p0.y, p1.y), min(p2.y, p3.y));
844
17.3M
        bbox.q.x = max(max(p0.x, p1.x), max(p2.x, p3.x));
845
17.3M
        bbox.q.y = max(max(p0.y, p1.y), max(p2.y, p3.y));
846
847
17.3M
        bbox.q.x = bbox.p.x + max(bbox.q.x - bbox.p.x, wanted.x);
848
17.3M
        bbox.q.y = bbox.p.y + max(bbox.q.y - bbox.p.y, wanted.y);
849
17.3M
        bbox.p.x += total.x;
850
17.3M
        bbox.p.y += total.y;
851
17.3M
        bbox.q.x += total.x;
852
17.3M
        bbox.q.y += total.y;
853
854
17.3M
        total.x += wanted.x;
855
17.3M
        total.y += wanted.y;
856
857
17.3M
        if (i == 0)
858
3.73M
            *text_bbox = bbox;
859
13.6M
        else
860
17.3M
            rect_merge(*text_bbox, bbox);
861
17.3M
    }
862
3.68M
    *pdpt = total;
863
3.68M
    return 0;
864
4.35M
}
865
866
void
867
adjust_first_last_char(pdf_font_resource_t *pdfont, byte *str, int size)
868
4.33M
{
869
4.33M
    int i;
870
871
22.9M
    for (i = 0; i < size; ++i) {
872
18.6M
        int chr = str[i];
873
874
18.6M
        if (chr < pdfont->u.simple.FirstChar)
875
49.9k
            pdfont->u.simple.FirstChar = chr;
876
18.6M
        if (chr > pdfont->u.simple.LastChar)
877
208k
            pdfont->u.simple.LastChar = chr;
878
18.6M
    }
879
4.33M
}
880
881
int
882
pdf_shift_text_currentpoint(pdf_text_enum_t *penum, gs_point *wpt)
883
4.43M
{
884
4.43M
    return gs_moveto_aux(penum->pgs, gx_current_path(penum->pgs),
885
4.43M
                              fixed2float(penum->origin.x) + wpt->x,
886
4.43M
                              fixed2float(penum->origin.y) + wpt->y);
887
4.43M
}
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.98M
{
909
4.98M
    gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
910
4.98M
    gs_font_base *font = (gs_font_base *)penum->current_font;
911
4.98M
    pdf_font_resource_t *pdfont;
912
4.98M
    gs_text_params_t *text = &penum->text;
913
4.98M
    int code = 0, mask;
914
4.98M
    gs_point width_pt;
915
4.98M
    int accepted;
916
4.98M
    gs_rect text_bbox = {{0, 0}, {0, 0}}, glyphs_bbox = {{10000,10000}, {0,0}};
917
4.98M
    unsigned int operation = text->operation;
918
4.98M
    gx_path *path = gs_text_enum_path(penum);
919
920
4.98M
    code = pdf_obtain_font_resource(penum, pstr, &pdfont);
921
4.98M
    if (code < 0)
922
578k
        return code;
923
4.40M
    if (pfmat == 0)
924
4.40M
        pfmat = &font->FontMatrix;
925
4.40M
    if (text->operation & TEXT_RETURN_WIDTH) {
926
4.40M
        code = gx_path_current_point(path, &penum->origin);
927
4.40M
        if (code < 0)
928
1
            return code;
929
4.40M
    }
930
4.40M
    if (text->size == 0)
931
936
        return 0;
932
4.40M
    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.35M
        code = process_text_estimate_bbox(penum, font, (gs_const_string *)pstr, pfmat,
940
4.35M
                                          &text_bbox, &width_pt);
941
4.35M
        if (code == 0) {
942
3.68M
            gs_fixed_rect clip_bbox;
943
3.68M
            gs_rect rect;
944
945
3.68M
            if (penum->pcpath) {
946
3.68M
                gx_cpath_outer_box(penum->pcpath, &clip_bbox);
947
3.68M
                rect.p.x = fixed2float(clip_bbox.p.x);
948
3.68M
                rect.p.y = fixed2float(clip_bbox.p.y);
949
3.68M
                rect.q.x = fixed2float(clip_bbox.q.x);
950
3.68M
                rect.q.y = fixed2float(clip_bbox.q.y);
951
3.68M
                rect_intersect(rect, text_bbox);
952
3.68M
                if (rect.p.x > rect.q.x || rect.p.y > rect.q.y && penum->pgs->text_rendering_mode < 3) {
953
70.2k
                    penum->index += pstr->size;
954
70.2k
                    text->operation &= ~TEXT_DO_DRAW;
955
70.2k
                    penum->text_clipped = true;
956
70.2k
                }
957
3.68M
            }
958
3.68M
        } else {
959
674k
            gs_matrix m;
960
674k
            gs_fixed_point origin;
961
674k
            gs_point p0, p1, p2, p3;
962
963
674k
            code = gx_path_current_point(path, &origin);
964
674k
            if (code < 0)
965
0
                goto done;
966
967
674k
            m = ctm_only(penum->pgs);
968
674k
            m.tx = fixed2float(origin.x);
969
674k
            m.ty = fixed2float(origin.y);
970
674k
            gs_matrix_multiply(pfmat, &m, &m);
971
972
674k
            if (font->FontBBox.p.x != font->FontBBox.q.x) {
973
435k
                text_bbox.p.x = font->FontBBox.p.x;
974
435k
                text_bbox.q.x = font->FontBBox.q.x;
975
435k
            } else {
976
239k
                text_bbox.p.x = 0;
977
239k
                text_bbox.q.x = 1000;
978
239k
            }
979
674k
            if (font->FontBBox.p.y != font->FontBBox.q.y) {
980
436k
                text_bbox.p.y = font->FontBBox.p.y;
981
436k
                text_bbox.q.y = font->FontBBox.q.y;
982
436k
            } else {
983
238k
                text_bbox.p.y = 0;
984
238k
                text_bbox.q.y = 1000;
985
238k
            }
986
674k
            gs_point_transform(text_bbox.p.x, text_bbox.p.y, &m, &p0);
987
674k
            gs_point_transform(text_bbox.p.x, text_bbox.q.y, &m, &p1);
988
674k
            gs_point_transform(text_bbox.q.x, text_bbox.p.y, &m, &p2);
989
674k
            gs_point_transform(text_bbox.q.x, text_bbox.q.y, &m, &p3);
990
674k
            text_bbox.p.x = min(min(p0.x, p1.x), min(p1.x, p2.x));
991
674k
            text_bbox.p.y = min(min(p0.y, p1.y), min(p1.y, p2.y));
992
674k
            text_bbox.q.x = max(max(p0.x, p1.x), max(p1.x, p2.x));
993
674k
            text_bbox.q.y = max(max(p0.y, p1.y), max(p1.y, p2.y));
994
674k
        }
995
4.35M
    } else {
996
        /* We have no penum->pcpath. */
997
50.7k
    }
998
999
    /*
1000
     * Note that pdf_update_text_state sets all the members of ppts->values
1001
     * to their current values.
1002
     */
1003
4.40M
    code = pdf_update_text_state(ppts, penum, pdfont, pfmat);
1004
4.40M
    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.40M
    if (code < 0)
1012
0
        goto done;
1013
4.40M
    mask = code;
1014
1015
4.40M
    if (text->operation & TEXT_REPLACE_WIDTHS)
1016
2.64M
        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.40M
    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.76M
        if (!(text->operation & (TEXT_DO_DRAW | TEXT_RETURN_WIDTH))) {
1029
0
            code = 0;
1030
0
            goto done;
1031
0
        }
1032
1.76M
        code = process_text_return_width(penum, font, ppts,
1033
1.76M
                                         (gs_const_string *)pstr, gdata,
1034
1.76M
                                         &width_pt, &accepted, &glyphs_bbox);
1035
1.76M
        if (code < 0)
1036
9.05k
            goto done;
1037
1.75M
        if (code == 0) {
1038
            /* No characters with redefined widths -- the fast case. */
1039
1.71M
            if (text->operation & TEXT_DO_DRAW || penum->pgs->text_rendering_mode == 3) {
1040
1.65M
                code = pdf_append_chars(pdev, pstr->data, accepted,
1041
1.65M
                                        width_pt.x, width_pt.y, false);
1042
1.65M
                if (code < 0)
1043
0
                    goto done;
1044
1.65M
                adjust_first_last_char(pdfont, pstr->data, accepted);
1045
1.65M
                penum->index += accepted;
1046
1.65M
            } else if (text->operation & TEXT_DO_NONE)
1047
21.3k
                penum->index += accepted;
1048
1.71M
        } 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.75M
    }
1053
4.39M
    if (mask) {
1054
        /* process_text_modify_width destroys text parameters, save them now. */
1055
2.68M
        int index0 = penum->index, xy_index = penum->xy_index;
1056
2.68M
        gs_text_params_t text = penum->text;
1057
2.68M
        int xy_index_step = (!(penum->text.operation & TEXT_REPLACE_WIDTHS) ? 0 :
1058
2.68M
                             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
2.68M
        gs_glyph gdata_i, *gdata_p = (gs_glyph *)gdata;
1067
2.68M
        if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
1068
0
            gdata_i = *gdata;
1069
0
            gdata_p = &gdata_i;
1070
0
        }
1071
1072
2.68M
        if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
1073
2.64M
            if (penum->text.x_widths != NULL)
1074
2.64M
                penum->text.x_widths += xy_index * xy_index_step;
1075
2.64M
            if (penum->text.y_widths != NULL)
1076
2.64M
                penum->text.y_widths += xy_index * xy_index_step;
1077
2.64M
        }
1078
2.68M
        penum->xy_index = 0;
1079
2.68M
        code = process_text_modify_width(penum, (gs_font *)font, ppts,
1080
2.68M
                                         (gs_const_string *)pstr,
1081
2.68M
                                         &width_pt, (const gs_glyph *)gdata_p, false, 1);
1082
2.68M
        if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
1083
2.64M
            if (penum->text.x_widths != NULL)
1084
2.64M
                penum->text.x_widths -= xy_index * xy_index_step;
1085
2.64M
            if (penum->text.y_widths != NULL)
1086
2.64M
                penum->text.y_widths -= xy_index * xy_index_step;
1087
2.64M
        }
1088
2.68M
        penum->xy_index += xy_index;
1089
2.68M
        adjust_first_last_char(pdfont, pstr->data, penum->index);
1090
2.68M
        penum->text = text;
1091
2.68M
        penum->index += index0;
1092
2.68M
        if (code < 0)
1093
14.4k
            goto done;
1094
2.68M
    }
1095
1096
    /* Finally, return the total width if requested. */
1097
4.38M
    if (pdev->Eps2Write && penum->pcpath) {
1098
1.49M
        gx_device_clip cdev;
1099
1.49M
        gx_drawing_color devc;
1100
1.49M
        fixed x0, y0, bx2, by2;
1101
1102
1.49M
        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
1.49M
        x0 = float2fixed(text_bbox.p.x);
1139
1.49M
        y0 = float2fixed(text_bbox.p.y);
1140
1.49M
        bx2 = float2fixed(text_bbox.q.x) - x0;
1141
1.49M
        by2 = float2fixed(text_bbox.q.y) - y0;
1142
1143
1.49M
        pdev->AccumulatingBBox++;
1144
1.49M
        gx_make_clip_device_on_stack(&cdev, penum->pcpath, (gx_device *)pdev);
1145
1.49M
        set_nonclient_dev_color(&devc, gx_device_black((gx_device *)pdev));  /* any non-white color will do */
1146
1.49M
        gx_default_fill_triangle((gx_device *) pdev, x0, y0,
1147
1.49M
                                 float2fixed(text_bbox.p.x) - x0,
1148
1.49M
                                 float2fixed(text_bbox.q.y) - y0,
1149
1.49M
                                 bx2, by2, &devc, lop_default);
1150
1.49M
        gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
1151
1.49M
                                 float2fixed(text_bbox.q.x) - x0,
1152
1.49M
                                 float2fixed(text_bbox.p.y) - y0,
1153
1.49M
                                 bx2, by2, &devc, lop_default);
1154
1.49M
        gx_destroy_clip_device_on_stack(&cdev);
1155
1.49M
        pdev->AccumulatingBBox--;
1156
1.49M
    }
1157
4.38M
    if (!(operation & TEXT_RETURN_WIDTH)) {
1158
0
        code = 0;
1159
0
        goto done;
1160
0
    }
1161
4.38M
    if (operation & TEXT_DO_NONE) {
1162
        /* stringwidth needs to transform to user space. */
1163
50.6k
        gs_point p;
1164
1165
50.6k
        gs_distance_transform_inverse(width_pt.x, width_pt.y, &ctm_only(penum->pgs), &p);
1166
50.6k
        penum->returned.total_width.x += p.x;
1167
50.6k
        penum->returned.total_width.y += p.y;
1168
50.6k
    } else
1169
4.33M
        penum->returned.total_width = width_pt;
1170
4.38M
    code = pdf_shift_text_currentpoint(penum, &width_pt);
1171
1172
4.40M
done:
1173
4.40M
    text->operation = operation;
1174
4.40M
    return code;
1175
4.38M
}
1176
1177
/*
1178
 * Get the widths (unmodified and possibly modified) of a given character
1179
 * in a simple font.  May add the widths to the widths cache (pdfont->Widths
1180
 * and pdf_font_cache_elem::real_widths).  Return 1 if the widths were not cached.
1181
 */
1182
static int
1183
pdf_char_widths(gx_device_pdf *const pdev,
1184
                pdf_font_resource_t *pdfont, int ch, gs_font_base *font,
1185
                pdf_glyph_widths_t *pwidths /* may be NULL */)
1186
19.1M
{
1187
19.1M
    pdf_glyph_widths_t widths;
1188
19.1M
    int code;
1189
19.1M
    byte *glyph_usage;
1190
19.1M
    double *real_widths;
1191
19.1M
    int char_cache_size, width_cache_size;
1192
19.1M
    pdf_font_resource_t *pdfont1;
1193
1194
19.1M
    code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont1,
1195
19.1M
                                &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1196
19.1M
    if (code < 0)
1197
0
        return code;
1198
19.1M
    if (pdfont1 != pdfont)
1199
0
        return_error(gs_error_unregistered); /* Must not happen. */
1200
19.1M
    if (ch < 0 || ch > 255)
1201
0
        return_error(gs_error_rangecheck);
1202
19.1M
    if (ch >= width_cache_size)
1203
0
        return_error(gs_error_unregistered); /* Must not happen. */
1204
19.1M
    if (pwidths == 0)
1205
0
        pwidths = &widths;
1206
19.1M
    if ((font->FontType != ft_user_defined &&
1207
19.1M
        font->FontType != ft_PDF_user_defined &&
1208
19.1M
        font->FontType != ft_PCL_user_defined &&
1209
19.1M
        font->FontType != ft_MicroType &&
1210
19.1M
        font->FontType != ft_GL2_stick_user_defined &&
1211
19.1M
        font->FontType != ft_GL2_531) && real_widths[ch] == 0) {
1212
        /* Might be an unused char, or just not cached. */
1213
1.41M
        gs_glyph glyph = pdfont->u.simple.Encoding[ch].glyph;
1214
1215
1.41M
        code = pdf_glyph_widths(pdfont, font->WMode, glyph, (gs_font *)font, pwidths, NULL);
1216
1.41M
        if (code < 0)
1217
0
            return code;
1218
1.41M
        pwidths->BBox.p.x = pwidths->BBox.p.y = pwidths->BBox.q.x = pwidths->BBox.q.y = 0;
1219
1.41M
        if (font->WMode != 0 && code > 0 && !pwidths->replaced_v) {
1220
            /*
1221
             * The font has no Metrics2, so it must write
1222
             * horizontally due to PS spec.
1223
             * Therefore we need to fill the Widths array,
1224
             * which is required by PDF spec.
1225
             * Take it from WMode==0.
1226
             */
1227
0
            code = pdf_glyph_widths(pdfont, 0, glyph, (gs_font *)font, pwidths, NULL);
1228
0
        }
1229
1.41M
        if (pwidths->replaced_v) {
1230
1.34M
            pdfont->u.simple.v[ch].x = pwidths->real_width.v.x - pwidths->Width.v.x;
1231
1.34M
            pdfont->u.simple.v[ch].y = pwidths->real_width.v.y - pwidths->Width.v.y;
1232
1.34M
        } else
1233
68.9k
            pdfont->u.simple.v[ch].x = pdfont->u.simple.v[ch].y = 0;
1234
1.41M
        if (code == 0) {
1235
1.41M
            pdfont->Widths[ch] = pwidths->Width.w;
1236
1.41M
            real_widths[ch] = pwidths->real_width.w;
1237
1.41M
        } else {
1238
243
            if ((font->WMode == 0 || pwidths->ignore_wmode) && !pwidths->replaced_v)
1239
217
                pdfont->Widths[ch] = pwidths->real_width.w;
1240
243
        }
1241
17.7M
    } else {
1242
17.7M
        if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
1243
17.7M
            font->FontType == ft_MicroType || font->FontType == ft_GL2_stick_user_defined ||
1244
17.7M
            font->FontType == ft_GL2_531 || font->FontType == ft_PDF_user_defined ) {
1245
470k
            if (!(pdfont->used[ch >> 3] & 0x80 >> (ch & 7)))
1246
10.6k
        return_error(gs_error_undefined); /* The charproc was not accumulated. */
1247
459k
            if (!pdev->charproc_just_accumulated &&
1248
459k
                !(pdfont->u.simple.s.type3.cached[ch >> 3] & 0x80 >> (ch & 7))) {
1249
                 /* The charproc uses setcharwidth.
1250
                    Need to accumulate again to check for a glyph variation. */
1251
11.5k
        return_error(gs_error_undefined);
1252
11.5k
            }
1253
459k
        }
1254
17.6M
        if (pdev->charproc_just_accumulated && (font->FontType == ft_user_defined || font->FontType == ft_PDF_user_defined)) {
1255
99.3k
            pwidths->BBox.p.x = pdev->charproc_BBox.p.x;
1256
99.3k
            pwidths->BBox.p.y = pdev->charproc_BBox.p.y;
1257
99.3k
            pwidths->BBox.q.x = pdev->charproc_BBox.q.x;
1258
99.3k
            pwidths->BBox.q.y = pdev->charproc_BBox.q.y;
1259
99.3k
        }
1260
17.6M
        pwidths->Width.w = pdfont->Widths[ch];
1261
17.6M
        pwidths->Width.v = pdfont->u.simple.v[ch];
1262
17.6M
        pwidths->real_width.v.x = pwidths->real_width.v.y = 0;
1263
17.6M
        pwidths->ignore_wmode = false;
1264
17.6M
        if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
1265
17.6M
            font->FontType == ft_MicroType || font->FontType == ft_GL2_stick_user_defined ||
1266
17.6M
            font->FontType == ft_GL2_531 || font->FontType == ft_PDF_user_defined) {
1267
448k
            pwidths->real_width.w = real_widths[ch * 2];
1268
448k
            pwidths->Width.xy.x = pwidths->Width.w;
1269
448k
            pwidths->Width.xy.y = 0;
1270
448k
            pwidths->real_width.xy.x = real_widths[ch * 2 + 0];
1271
448k
            pwidths->real_width.xy.y = real_widths[ch * 2 + 1];
1272
448k
            pwidths->replaced_v = 0;
1273
17.2M
        } else if (font->WMode) {
1274
0
            pwidths->real_width.w = real_widths[ch];
1275
0
            pwidths->Width.xy.x = 0;
1276
0
            pwidths->Width.xy.y = pwidths->Width.w;
1277
0
            pwidths->real_width.xy.x = 0;
1278
0
            pwidths->real_width.xy.y = pwidths->real_width.w;
1279
17.2M
        } else {
1280
17.2M
            pwidths->real_width.w = real_widths[ch];
1281
17.2M
            pwidths->Width.xy.x = pwidths->Width.w;
1282
17.2M
            pwidths->Width.xy.y = 0;
1283
17.2M
            pwidths->real_width.xy.x = pwidths->real_width.w;
1284
17.2M
            pwidths->real_width.xy.y = 0;
1285
17.2M
        }
1286
17.6M
        code = 0;
1287
17.6M
    }
1288
19.1M
    return code;
1289
19.1M
}
1290
1291
/*
1292
 * Convert glyph widths (.Width.xy and .real_widths.xy) from design to PDF text space
1293
 * Zero-out one of Width.xy.x/y per PDF Ref 5.3.3 "Text Space Details"
1294
 */
1295
static void
1296
pdf_char_widths_to_uts(pdf_font_resource_t *pdfont /* may be NULL for non-Type3 */,
1297
                       pdf_glyph_widths_t *pwidths)
1298
19.1M
{
1299
19.1M
    if (pdfont && (pdfont->FontType == ft_user_defined ||
1300
8.49M
        pdfont->FontType == ft_PDF_user_defined ||
1301
8.49M
        pdfont->FontType == ft_PCL_user_defined ||
1302
8.49M
        pdfont->FontType == ft_MicroType ||
1303
8.49M
        pdfont->FontType == ft_GL2_stick_user_defined ||
1304
8.49M
        pdfont->FontType == ft_GL2_531)) {
1305
448k
        gs_matrix *pmat = &pdfont->u.simple.s.type3.FontMatrix;
1306
1307
448k
        pwidths->Width.xy.x *= pmat->xx; /* formula simplified based on wy in glyph space == 0 */
1308
448k
        pwidths->Width.xy.y  = 0.0; /* WMode == 0 for PDF Type 3 fonts */
1309
448k
        gs_distance_transform(pwidths->real_width.xy.x, pwidths->real_width.xy.y, pmat, &pwidths->real_width.xy);
1310
18.7M
    } else {
1311
        /*
1312
         * For other font types:
1313
         * - PDF design->text space is a simple scaling by 0.001.
1314
         * - The Width.xy.x/y that should be zeroed-out per 5.3.3 "Text Space Details" is already 0.
1315
         */
1316
18.7M
        pwidths->Width.xy.x /= 1000.0;
1317
18.7M
        pwidths->Width.xy.y /= 1000.0;
1318
18.7M
        pwidths->real_width.xy.x /= 1000.0;
1319
18.7M
        pwidths->real_width.xy.y /= 1000.0;
1320
18.7M
    }
1321
19.1M
}
1322
1323
/*
1324
 * Compute the total text width (in user space).  Return 1 if any
1325
 * character had real_width != Width, otherwise 0.
1326
 */
1327
static int
1328
process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font,
1329
                          pdf_text_process_state_t *ppts,
1330
                          const gs_const_string *pstr, const gs_glyph *gdata,
1331
                          gs_point *pdpt, int *accepted, gs_rect *bbox)
1332
1.76M
{
1333
1.76M
    int i;
1334
1.76M
    gs_point w;
1335
1.76M
    gs_point dpt;
1336
1.76M
    int num_spaces = 0;
1337
1.76M
    int space_char =
1338
1.76M
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
1339
1.71M
         pte->text.space.s_char : -1);
1340
1.76M
    int widths_differ = 0, code;
1341
1.76M
    gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
1342
1.76M
    pdf_font_resource_t *pdfont;
1343
1344
1.76M
    code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont, NULL, NULL, NULL, NULL);
1345
1.76M
    if (code < 0)
1346
0
        return code;
1347
10.1M
    for (i = 0, w.x = w.y = 0; i < pstr->size; ++i) {
1348
8.44M
        pdf_glyph_widths_t cw; /* in PDF text space */
1349
8.44M
        gs_char ch = pstr->data[i];
1350
1351
        /* Initialise some variables */
1352
8.44M
        cw.real_width.xy.x = cw.real_width.xy.y = cw.Width.xy.x = cw.Width.xy.y = 0;
1353
8.44M
        cw.BBox.p.x = cw.BBox.p.y = cw.BBox.q.x = cw.BBox.q.y = 0;
1354
1355
8.44M
        {  const gs_glyph *gdata_i = (gdata != NULL ? gdata + i : 0);
1356
1357
8.44M
            code = pdf_encode_string_element(pdev, (gs_font *)font, pdfont, ch, gdata_i);
1358
1359
8.44M
            if (code < 0)
1360
68
                return code;
1361
8.44M
        }
1362
8.44M
        if ((font->FontType == ft_user_defined ||
1363
8.44M
            font->FontType == ft_PDF_user_defined ||
1364
8.44M
            font->FontType == ft_PCL_user_defined ||
1365
8.44M
            font->FontType == ft_GL2_stick_user_defined ||
1366
8.44M
            font->FontType == ft_MicroType ||
1367
8.44M
            font->FontType == ft_GL2_531) &&
1368
8.44M
            (i > 0 || !pdev->charproc_just_accumulated) &&
1369
8.44M
            !(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))){
1370
76.4k
            code = gs_error_undefined;
1371
76.4k
        }
1372
8.36M
        else {
1373
8.36M
            if (font->FontType == ft_PCL_user_defined) {
1374
                /* Check the cache, if the glyph has been flushed, assume that
1375
                 * it has been redefined, and do not use the current glyph.
1376
                 * Additional code in pdf_text_process will also spot this
1377
                 * condition and will not capture the glyph in this font.
1378
                 */
1379
                /* Cache checking code copied from gxchar.c, show_proceed,
1380
                 * case 0, 'plain char'.
1381
                 */
1382
0
                gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
1383
0
                gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
1384
0
                    pte->fstack.items[pte->fstack.depth].font);
1385
0
                int wmode = rfont->WMode;
1386
0
                gs_log2_scale_point log2_scale = {0,0};
1387
0
                gs_fixed_point subpix_origin = {0,0};
1388
0
                cached_fm_pair *pair;
1389
1390
0
                code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pgs), &log2_scale,
1391
0
                    false, &pair);
1392
0
                if (code < 0)
1393
0
                    return code;
1394
0
                if (gx_lookup_cached_char(pfont, pair, ch, wmode,
1395
0
                    1, &subpix_origin) == 0) {
1396
                        /* Character is not in cache, must have been redefined. */
1397
0
                    code = gs_error_undefined;
1398
0
                }
1399
0
                else {
1400
                    /* Character is in cache, go ahead and use it */
1401
0
                    code = pdf_char_widths((gx_device_pdf *)pte->dev,
1402
0
                                   ppts->values.pdfont, ch, font, &cw);
1403
0
                }
1404
0
            } else
1405
                /* Not a PCL bitmap font, we don't need to worry about redefined glyphs */
1406
8.36M
                code = pdf_char_widths((gx_device_pdf *)pte->dev,
1407
8.36M
                                   ppts->values.pdfont, ch, font, &cw);
1408
8.36M
        }
1409
8.44M
        if (code < 0) {
1410
76.4k
            if (i)
1411
67.4k
                break;
1412
8.99k
            *accepted = 0;
1413
8.99k
            return code;
1414
76.4k
        }
1415
8.36M
        pdf_char_widths_to_uts(pdfont, &cw);
1416
8.36M
        w.x += cw.real_width.xy.x;
1417
8.36M
        w.y += cw.real_width.xy.y;
1418
8.36M
        if (cw.real_width.xy.x != cw.Width.xy.x ||
1419
8.36M
            cw.real_width.xy.y != cw.Width.xy.y
1420
8.36M
            )
1421
39.5k
            widths_differ = 1;
1422
8.36M
        if (pstr->data[i] == space_char)
1423
10.6k
            ++num_spaces;
1424
8.36M
        if (cw.BBox.p.x != 0 && cw.BBox.q.x != 0){
1425
1.18k
            if (cw.BBox.p.x < bbox->p.x)
1426
1.07k
                bbox->p.x = cw.BBox.p.x;
1427
1.18k
            if (cw.BBox.p.y < bbox->p.y)
1428
1.07k
                bbox->p.y = cw.BBox.p.y;
1429
1.18k
            if (cw.BBox.q.x > bbox->q.x)
1430
1.07k
                bbox->q.x = cw.BBox.q.x;
1431
1.18k
            if (cw.BBox.q.y > bbox->q.y)
1432
1.07k
                bbox->q.y = cw.BBox.q.y;
1433
1.18k
        }
1434
8.36M
    }
1435
1.75M
    *accepted = i;
1436
1.75M
    gs_distance_transform(w.x * ppts->values.size, w.y * ppts->values.size,
1437
1.75M
                          &ppts->values.matrix, &dpt);
1438
1.75M
    if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
1439
286k
        int num_chars = *accepted;
1440
286k
        gs_point tpt;
1441
1442
286k
        gs_distance_transform(pte->text.delta_all.x, pte->text.delta_all.y,
1443
286k
                              &ctm_only(pte->pgs), &tpt);
1444
286k
        dpt.x += tpt.x * num_chars;
1445
286k
        dpt.y += tpt.y * num_chars;
1446
286k
    }
1447
1.75M
    if (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
1448
50.1k
        gs_point tpt;
1449
1450
50.1k
        gs_distance_transform(pte->text.delta_space.x, pte->text.delta_space.y,
1451
50.1k
                              &ctm_only(pte->pgs), &tpt);
1452
50.1k
        dpt.x += tpt.x * num_spaces;
1453
50.1k
        dpt.y += tpt.y * num_spaces;
1454
50.1k
    }
1455
1.75M
    *pdpt = dpt;
1456
1457
1.75M
    return widths_differ;
1458
1.76M
}
1459
1460
/*
1461
 * Emulate TEXT_ADD_TO_ALL_WIDTHS and/or TEXT_ADD_TO_SPACE_WIDTH,
1462
 * and implement TEXT_REPLACE_WIDTHS if requested.
1463
 * Uses and updates ppts->values.matrix; uses ppts->values.pdfont.
1464
 *
1465
 * Destroys the text parameters in *pte.
1466
 * The caller must restore them.
1467
 */
1468
int
1469
process_text_modify_width(pdf_text_enum_t *pte, gs_font *font,
1470
                          pdf_text_process_state_t *ppts,
1471
                          const gs_const_string *pstr,
1472
                          gs_point *pdpt, const gs_glyph *gdata, bool composite, int decoded_bytes)
1473
2.73M
{
1474
2.73M
    gx_device_pdf *const pdev = (gx_device_pdf *)pte->dev;
1475
2.73M
    int space_char =
1476
2.73M
        (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
1477
2.60M
         pte->text.space.s_char : -1);
1478
2.73M
    gs_point start, total;
1479
2.73M
    pdf_font_resource_t *pdfont3 = NULL;
1480
2.73M
    int code;
1481
1482
2.73M
    if (font->FontType == ft_user_defined ||
1483
2.73M
        font->FontType == ft_PDF_user_defined ||
1484
2.73M
        font->FontType == ft_PCL_user_defined ||
1485
2.73M
        font->FontType == ft_MicroType ||
1486
2.73M
        font->FontType == ft_GL2_stick_user_defined ||
1487
2.73M
        font->FontType == ft_GL2_531) {
1488
85.8k
        code = pdf_attached_font_resource(pdev, font, &pdfont3, NULL, NULL, NULL, NULL);
1489
85.8k
        if (code < 0)
1490
0
            return code;
1491
1492
85.8k
    }
1493
2.73M
    pte->text.data.bytes = pstr->data;
1494
2.73M
    pte->text.size = pstr->size;
1495
2.73M
    pte->index = 0;
1496
2.73M
    pte->text.operation &= ~TEXT_FROM_ANY;
1497
2.73M
    pte->text.operation |= TEXT_FROM_STRING;
1498
2.73M
    start.x = ppts->values.matrix.tx;
1499
2.73M
    start.y = ppts->values.matrix.ty;
1500
2.73M
    total.x = total.y = 0;  /* user space */
1501
    /*
1502
     * Note that character widths are in design space, but text.delta_*
1503
     * values and the width value returned in *pdpt are in user space,
1504
     * and the width values for pdf_append_chars are in device space.
1505
     */
1506
13.5M
    for (;;) {
1507
13.5M
        pdf_glyph_widths_t cw;  /* design space, then converted to PDF text space */
1508
13.5M
        gs_point did, wanted, tpt;  /* user space */
1509
13.5M
        gs_point v = {0, 0}; /* design space */
1510
13.5M
        gs_char chr;
1511
13.5M
        gs_glyph glyph;
1512
13.5M
        int index = pte->index;
1513
13.5M
        gs_text_enum_t pte1 = *(gs_text_enum_t *)pte;
1514
13.5M
        int FontType;
1515
13.5M
        bool use_cached_v = true;
1516
13.5M
        byte composite_type3_text[1];
1517
1518
13.5M
        code = pte1.orig_font->procs.next_char_glyph(&pte1, &chr, &glyph);
1519
13.5M
        if (code == 2) { /* end of string */
1520
2.70M
            gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true);
1521
2.70M
            break;
1522
2.70M
        }
1523
10.8M
        if (code < 0)
1524
0
            return code;
1525
10.8M
        if (composite) { /* from process_cmap_text */
1526
86.9k
            gs_font *subfont = pte1.fstack.items[pte1.fstack.depth].font;
1527
1528
86.9k
            if (subfont->FontType == ft_user_defined || subfont->FontType == ft_PDF_user_defined ) {
1529
0
                pdf_font_resource_t *pdfont;
1530
1531
0
                FontType = subfont->FontType;
1532
0
                code = pdf_attached_font_resource(pdev, subfont,
1533
0
                            &pdfont, NULL, NULL, NULL, NULL);
1534
0
                if (code < 0)
1535
0
                    return code;
1536
0
                chr = pdf_find_glyph(pdfont, glyph);
1537
0
                composite_type3_text[0] = (byte)chr;
1538
0
                code = pdf_char_widths((gx_device_pdf *)pte->dev,
1539
0
                                       ppts->values.pdfont, chr, (gs_font_base *)subfont,
1540
0
                                       &cw);
1541
86.9k
            } else {
1542
86.9k
                pdf_font_resource_t *pdsubf = ppts->values.pdfont->u.type0.DescendantFont;
1543
1544
86.9k
                FontType = pdsubf->FontType;
1545
86.9k
                code = pdf_glyph_widths(pdsubf, font->WMode, glyph, subfont, &cw,
1546
86.9k
                    pte->cdevproc_callout ? pte->cdevproc_result : NULL);
1547
86.9k
            }
1548
10.7M
        } else {/* must be a base font */
1549
10.7M
            const gs_glyph *gdata_i = (gdata != NULL ? gdata + pte->index : 0);
1550
1551
                /* gdata is NULL when composite == true, or the text isn't a single byte.  */
1552
10.7M
            code = pdf_encode_string_element(pdev, font, ppts->values.pdfont, chr, gdata_i);
1553
10.7M
            FontType = font->FontType;
1554
10.7M
            if (code >= 0) {
1555
10.7M
                if (chr == GS_NO_CHAR && glyph != GS_NO_GLYPH) {
1556
                    /* glyphshow, we have no char code. Bug 686988.*/
1557
0
                    code = pdf_glyph_widths(ppts->values.pdfont, font->WMode, glyph, font, &cw, NULL);
1558
0
                    use_cached_v = false; /* Since we have no chr and don't call pdf_char_widths. */
1559
10.7M
                } else {
1560
10.7M
                    code = pdf_char_widths((gx_device_pdf *)pte->dev,
1561
10.7M
                                       ppts->values.pdfont, chr, (gs_font_base *)font,
1562
10.7M
                                       &cw);
1563
10.7M
                    if (code == 0 && font->FontType == ft_PCL_user_defined) {
1564
                        /* Check the cache, if the glyph has been flushed, assume that
1565
                         * it has been redefined, and do not use the current glyph.
1566
                         * Additional code in pdf_text_process will also spot this
1567
                         * condition and will not capture the glyph in this font.
1568
                         */
1569
                        /* Cache checking code copied from gxchar.c, show_proceed,
1570
                         * case 0, 'plain char'.
1571
                         */
1572
0
                        gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
1573
0
                        gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
1574
0
                            pte->fstack.items[pte->fstack.depth].font);
1575
0
                        int wmode = rfont->WMode;
1576
0
                        gs_log2_scale_point log2_scale = {0,0};
1577
0
                        gs_fixed_point subpix_origin = {0,0};
1578
0
                        cached_fm_pair *pair;
1579
1580
0
                        code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pgs), &log2_scale,
1581
0
                            false, &pair);
1582
0
                        if (code < 0)
1583
0
                            return code;
1584
0
                        if (gx_lookup_cached_char(pfont, pair, chr, wmode,
1585
0
                            1, &subpix_origin) == 0) {
1586
                        /* Character is not in cache, must have been redefined. */
1587
0
                            code = gs_error_undefined;
1588
0
                        }
1589
0
                    }
1590
10.7M
                }
1591
10.7M
            }
1592
10.7M
        }
1593
10.8M
        if (code < 0) {
1594
29.7k
            if (index > 0)
1595
15.2k
                break;
1596
14.4k
            return code;
1597
29.7k
        }
1598
        /* TrueType design grid is 2048x2048 against the nominal PS/PDF grid of
1599
         * 1000x1000. This can lead to rounding errors when converting to text space
1600
         * and comparing against any entries in /W or /Widths arrays. We fix the
1601
         * TrueType widths to the nearest integer here to avoid this.
1602
         * See Bug #693825
1603
         */
1604
10.8M
        if (FontType == ft_CID_TrueType || FontType == ft_TrueType) {
1605
573k
            cw.Width.w = floor(cw.Width.w + 0.5);
1606
573k
            cw.Width.xy.x = floor(cw.Width.xy.x + 0.5);
1607
573k
            cw.Width.xy.y = floor(cw.Width.xy.y + 0.5);
1608
573k
            cw.Width.v.x = floor(cw.Width.v.x + 0.5);
1609
573k
            cw.Width.v.y = floor(cw.Width.v.y + 0.5);
1610
573k
            cw.real_width.w = floor(cw.real_width.w + 0.5);
1611
573k
            cw.real_width.xy.x = floor(cw.real_width.xy.x + 0.5);
1612
573k
            cw.real_width.xy.y = floor(cw.real_width.xy.y + 0.5);
1613
573k
            cw.real_width.v.x = floor(cw.real_width.v.x + 0.5);
1614
573k
            cw.real_width.v.y = floor(cw.real_width.v.y + 0.5);
1615
573k
        }
1616
1617
10.8M
        gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true);
1618
10.8M
        if (composite || !use_cached_v) {
1619
86.9k
            if (cw.replaced_v) {
1620
452
                v.x = cw.real_width.v.x - cw.Width.v.x;
1621
452
                v.y = cw.real_width.v.y - cw.Width.v.y;
1622
452
            }
1623
86.9k
        } else
1624
10.7M
            v = ppts->values.pdfont->u.simple.v[chr];
1625
10.8M
        if (font->WMode && !cw.ignore_wmode) {
1626
            /* With WMode 1 v-vector is (WMode 1 origin) - (WMode 0 origin).
1627
               The glyph shifts in the opposite direction.  */
1628
704
            v.x = - v.x;
1629
704
            v.y = - v.y;
1630
10.8M
        } else {
1631
            /* With WMode 0 v-vector is (Metrics sb) - (native sb).
1632
               The glyph shifts in same direction.  */
1633
10.8M
        }
1634
        /* pdf_glyph_origin is not longer used. */
1635
10.8M
        if (v.x != 0 || v.y != 0) {
1636
32.6k
            gs_point glyph_origin_shift;
1637
32.6k
            double scale0;
1638
1639
32.6k
            if (FontType == ft_TrueType || FontType == ft_CID_TrueType)
1640
32.4k
                scale0 = (float)0.001;
1641
234
            else
1642
234
                scale0 = 1;
1643
32.6k
            glyph_origin_shift.x = v.x * scale0;
1644
32.6k
            glyph_origin_shift.y = v.y * scale0;
1645
32.6k
            if (composite) {
1646
262
                gs_font *subfont = pte->fstack.items[pte->fstack.depth].font;
1647
1648
262
                gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1649
262
                                      &subfont->FontMatrix, &glyph_origin_shift);
1650
262
            }
1651
32.6k
            gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1652
32.6k
                                  &font->FontMatrix, &glyph_origin_shift);
1653
32.6k
            gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1654
32.6k
                                  &ctm_only(pte->pgs), &glyph_origin_shift);
1655
32.6k
            if (glyph_origin_shift.x != 0 || glyph_origin_shift.y != 0) {
1656
32.6k
                ppts->values.matrix.tx = start.x + total.x + glyph_origin_shift.x;
1657
32.6k
                ppts->values.matrix.ty = start.y + total.y + glyph_origin_shift.y;
1658
32.6k
                code = pdf_set_text_state_values(pdev, &ppts->values);
1659
32.6k
                if (code < 0)
1660
0
                    break;
1661
32.6k
            }
1662
32.6k
        }
1663
10.8M
        pdf_char_widths_to_uts(pdfont3, &cw); /* convert design->text space */
1664
10.8M
        if (pte->text.operation & (TEXT_DO_DRAW | TEXT_RENDER_MODE_3)) {
1665
10.2M
            gs_distance_transform(cw.Width.xy.x * ppts->values.size,
1666
10.2M
                                  cw.Width.xy.y * ppts->values.size,
1667
10.2M
                                  &ppts->values.matrix, &did);
1668
10.2M
            gs_distance_transform(((font->WMode && !cw.ignore_wmode) ? 0 : ppts->values.character_spacing),
1669
10.2M
                                  ((font->WMode && !cw.ignore_wmode) ? ppts->values.character_spacing : 0),
1670
10.2M
                                  &ppts->values.matrix, &tpt);
1671
10.2M
            did.x += tpt.x;
1672
10.2M
            did.y += tpt.y;
1673
            /* If pte->single_byte_space == 0 then we had a widthshow or awidthshow from
1674
             * PostScript, so we apply the PostScript rules. Otherwise it was from PDF
1675
             * in which case if the number of bytes in the character code was 1 we apply
1676
             * word spacing. If it was PDF and we had a multi-byte decode, do not apply
1677
             * word spacing (how ugly!). Note tht its important this is applied the same to
1678
             * both the 'did' and 'wanted' calculations (see below).
1679
             */
1680
10.2M
            if (chr == space_char && (!pte->single_byte_space || decoded_bytes == 1)) {
1681
33.2k
                gs_distance_transform(((font->WMode && !cw.ignore_wmode)? 0 : ppts->values.word_spacing),
1682
33.2k
                                      ((font->WMode && !cw.ignore_wmode) ? ppts->values.word_spacing : 0),
1683
33.2k
                                      &ppts->values.matrix, &tpt);
1684
33.2k
                did.x += tpt.x;
1685
33.2k
                did.y += tpt.y;
1686
33.2k
            }
1687
10.2M
            if (composite && (FontType == ft_user_defined || FontType == ft_PDF_user_defined))
1688
0
                code = pdf_append_chars(pdev, composite_type3_text, 1, did.x, did.y, composite);
1689
10.2M
            else
1690
10.2M
                code = pdf_append_chars(pdev, pstr->data + index, pte->index - index, did.x, did.y, composite);
1691
10.2M
            if (code < 0)
1692
0
                break;
1693
10.2M
        } else
1694
615k
            did.x = did.y = 0;
1695
10.8M
        if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
1696
10.6M
            gs_point dpt;
1697
1698
            /* We are applying a width override, from x/y/xyshow. This coudl be from
1699
             * a PostScript file, or it could be from a PDF file where we have a font
1700
             * with a FontMatrix which is neither horizontal nor vertical. If we use TJ
1701
             * for that, then we end up applying the displacement twice, once here where
1702
             * we add a TJ, and once when we actually draw the glyph (TJ is added *after*
1703
             * the glyph is drawn, unlike xshow). So in this case we don't want to try
1704
             * and use a TJ, we need to position the glyphs using text positioning
1705
             * operators.
1706
             */
1707
10.6M
            if(cw.Width.xy.x != cw.real_width.xy.x || cw.Width.xy.y != cw.real_width.xy.y)
1708
35
                pdev->text->text_state->can_use_TJ = false;
1709
1710
10.6M
            code = gs_text_replaced_width(&pte->text, pte->xy_index++, &dpt);
1711
10.6M
            if (code < 0)
1712
0
                return_error(gs_error_unregistered);
1713
10.6M
            gs_distance_transform(dpt.x, dpt.y, &ctm_only(pte->pgs), &wanted);
1714
1715
10.6M
            gs_distance_transform(((font->WMode && !cw.ignore_wmode) ? 0 : ppts->values.character_spacing),
1716
10.6M
                                  ((font->WMode && !cw.ignore_wmode) ? ppts->values.character_spacing : 0),
1717
10.6M
                                  &ppts->values.matrix, &tpt);
1718
10.6M
            wanted.x += tpt.x;
1719
10.6M
            wanted.y += tpt.y;
1720
1721
10.6M
            if (chr == space_char && (!pte->single_byte_space || decoded_bytes == 1)) {
1722
34.7k
                gs_distance_transform(((font->WMode && !cw.ignore_wmode)? 0 : ppts->values.word_spacing),
1723
34.7k
                                      ((font->WMode && !cw.ignore_wmode) ? ppts->values.word_spacing : 0),
1724
34.7k
                                      &ppts->values.matrix, &tpt);
1725
34.7k
                wanted.x += tpt.x;
1726
34.7k
                wanted.y += tpt.y;
1727
34.7k
            }
1728
10.6M
        } else {
1729
138k
            pdev->text->text_state->can_use_TJ = true;
1730
138k
            gs_distance_transform(cw.real_width.xy.x * ppts->values.size,
1731
138k
                                  cw.real_width.xy.y * ppts->values.size,
1732
138k
                                  &ppts->values.matrix, &wanted);
1733
138k
            if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
1734
32.8k
                gs_distance_transform(pte->text.delta_all.x,
1735
32.8k
                                      pte->text.delta_all.y,
1736
32.8k
                                      &ctm_only(pte->pgs), &tpt);
1737
32.8k
                wanted.x += tpt.x;
1738
32.8k
                wanted.y += tpt.y;
1739
32.8k
            }
1740
            /* See comment above for 'did' calculations, the application of word spacing must
1741
             * be the same for did and wanted.
1742
             */
1743
138k
            if (chr == space_char && (!pte->single_byte_space || decoded_bytes == 1)) {
1744
0
                gs_distance_transform(pte->text.delta_space.x,
1745
0
                                      pte->text.delta_space.y,
1746
0
                                      &ctm_only(pte->pgs), &tpt);
1747
0
                wanted.x += tpt.x;
1748
0
                wanted.y += tpt.y;
1749
0
            }
1750
138k
        }
1751
10.8M
        total.x += wanted.x;
1752
10.8M
        total.y += wanted.y;
1753
10.8M
        if (wanted.x != did.x || wanted.y != did.y) {
1754
10.6M
            ppts->values.matrix.tx = start.x + total.x;
1755
10.6M
            ppts->values.matrix.ty = start.y + total.y;
1756
10.6M
            code = pdf_set_text_state_values(pdev, &ppts->values);
1757
10.6M
            if (code < 0)
1758
0
                break;
1759
10.6M
        }
1760
10.8M
        pdev->charproc_just_accumulated = false;
1761
10.8M
    }
1762
2.72M
    *pdpt = total;
1763
2.72M
    return 0;
1764
2.73M
}
1765
1766
/*
1767
 * Get character code from a glyph code.
1768
 * An usage of this function is very undesirable,
1769
 * because a glyph may be unlisted in Encoding.
1770
 */
1771
int
1772
pdf_encode_glyph(gs_font_base *bfont, gs_glyph glyph0,
1773
            byte *buf, int buf_size, int *char_code_length)
1774
0
{
1775
0
    gs_char c;
1776
1777
0
    *char_code_length = 1;
1778
0
    if (*char_code_length > buf_size)
1779
0
        return_error(gs_error_rangecheck); /* Must not happen. */
1780
0
    for (c = 0; c < 255; c++) {
1781
0
        gs_glyph glyph1 = bfont->procs.encode_char((gs_font *)bfont, c,
1782
0
                    GLYPH_SPACE_NAME);
1783
0
        if (glyph1 == glyph0) {
1784
0
            buf[0] = (byte)c;
1785
0
            return 0;
1786
0
        }
1787
0
    }
1788
0
    return_error(gs_error_rangecheck); /* Can't encode. */
1789
0
}
1790
1791
/* ---------------- Type 1 or TrueType font ---------------- */
1792
1793
/*
1794
 * Process a text string in a simple font.
1795
 */
1796
int
1797
process_plain_text(gs_text_enum_t *pte, void *vbuf, uint bsize)
1798
4.98M
{
1799
4.98M
    byte *const buf = vbuf;
1800
4.98M
    uint count;
1801
4.98M
    uint operation = pte->text.operation;
1802
4.98M
    pdf_text_enum_t *penum = (pdf_text_enum_t *)pte;
1803
4.98M
    int code;
1804
4.98M
    gs_string str;
1805
4.98M
    pdf_text_process_state_t text_state;
1806
4.98M
    const gs_glyph *gdata = NULL;
1807
1808
4.98M
    if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) {
1809
4.93M
        count = pte->text.size - pte->index;
1810
4.93M
        if (bsize < count)
1811
0
            return_error(gs_error_unregistered); /* Must not happen. */
1812
4.93M
        memcpy(buf, (const byte *)pte->text.data.bytes + pte->index, count);
1813
4.93M
    } else if (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR)) {
1814
        /* Check that all chars fit in a single byte. */
1815
49.0k
        const gs_char *cdata;
1816
49.0k
        int i;
1817
1818
49.0k
        if (operation & TEXT_FROM_CHARS) {
1819
49.0k
            cdata = pte->text.data.chars;
1820
49.0k
            count = (pte->text.size - pte->index);
1821
49.0k
        } else {
1822
0
            cdata = &pte->text.data.d_char;
1823
0
            count = 1;
1824
0
        }
1825
49.0k
        if (bsize < count * sizeof(gs_char))
1826
0
            return_error(gs_error_unregistered); /* Must not happen. */
1827
258k
        for (i = 0; i < count; ++i) {
1828
209k
            gs_char chr = cdata[pte->index + i];
1829
1830
209k
            if (chr & ~0xff)
1831
0
                return_error(gs_error_rangecheck);
1832
209k
            buf[i] = (byte)chr;
1833
209k
        }
1834
49.0k
    } else if (operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH)) {
1835
        /*
1836
         * Since PDF has no analogue of 'glyphshow',
1837
         * we try to encode glyphs with the current
1838
         * font's encoding. If the current font has no encoding,
1839
         * or the encoding doesn't contain necessary glyphs,
1840
         * the text will be represented with a Type 3 font with
1841
         * bitmaps or outlines.
1842
         *
1843
         * When we fail with encoding (136-01.ps is an example),
1844
         * we could locate a PDF font resource or create a new one
1845
         * with same outlines and an appropriate encoding.
1846
         * Also we could change .notdef entries in the
1847
         * copied font (assuming that document designer didn't use
1848
         * .notdef for a meanful printing).
1849
         * fixme: Not implemented yet.
1850
         */
1851
0
        gs_font *font = pte->current_font;
1852
0
        uint size;
1853
0
        int i;
1854
1855
0
        if (operation & TEXT_FROM_GLYPHS) {
1856
0
            gdata = pte->text.data.glyphs;
1857
0
            size = pte->text.size - pte->index;
1858
0
        } else {
1859
0
            gdata = &pte->text.data.d_glyph;
1860
0
            size = 1;
1861
0
        }
1862
0
        if (!pdf_is_simple_font(font))
1863
0
            return_error(gs_error_unregistered); /* Must not happen. */
1864
0
        count = 0;
1865
0
        for (i = 0; i < size; ++i) {
1866
0
            pdf_font_resource_t *pdfont;
1867
0
            gs_glyph glyph = gdata[pte->index + i];
1868
0
            int char_code_length;
1869
1870
0
            code = pdf_encode_glyph((gs_font_base *)font, glyph,
1871
0
                         buf + count, size - count, &char_code_length);
1872
0
            if (code < 0)
1873
0
                break;
1874
            /* Even if we already have a glyph encoded at this position in the font
1875
             * it may not be the *right* glyph. We effectively use the first byte of
1876
             * the glyph name as the index when using glyphshow which means that
1877
             * /o and /omicron would be encoded at the same index. So we need
1878
             * to check the actual glyph to see if they are the same. To do
1879
             * that we need the PDF font resource which is attached to the font (if any).
1880
             * cf bugs #695259 and #695168
1881
             */
1882
0
            code = pdf_attached_font_resource((gx_device_pdf *)penum->dev, font,
1883
0
                            &pdfont, NULL, NULL, NULL, NULL);
1884
0
            if (code >= 0 && pdfont && pdfont->u.simple.Encoding[*(buf + count)].glyph != glyph)
1885
                /* the glyph doesn't match the glyph already encoded at this position.
1886
                 * Breaking out here will start a new PDF font resource in the code below.
1887
                 */
1888
0
                break;
1889
0
            count += char_code_length;
1890
0
            if (operation & TEXT_INTERVENE)
1891
0
                break; /* Just do one character. */
1892
0
        }
1893
0
        if (i < size) {
1894
0
            pdf_font_resource_t *pdfont;
1895
1896
0
            str.data = buf;
1897
0
            str.size = size;
1898
0
            code = pdf_obtain_font_resource_unencoded(penum, &str, &pdfont, gdata);
1899
0
            if (code < 0) {
1900
                /*
1901
                 * pdf_text_process will fall back
1902
                 * to default implementation.
1903
                 */
1904
0
                return code;
1905
0
            }
1906
0
            count = size;
1907
0
        }
1908
        /*  So far we will use TEXT_FROM_STRING instead
1909
            TEXT_FROM_*_GLYPH*. Since we used a single
1910
            byte encoding, the character index appears invariant
1911
            during this substitution.
1912
         */
1913
0
    } else
1914
0
        return_error(gs_error_rangecheck);
1915
4.98M
    str.data = buf;
1916
4.98M
    if (count > 1 && (operation & TEXT_INTERVENE)) {
1917
        /* Just do one character. */
1918
0
        str.size = 1;
1919
0
        code = pdf_process_string_aux(penum, &str, gdata, NULL, &text_state);
1920
0
        if (code >= 0) {
1921
0
            pte->returned.current_char = buf[0];
1922
0
            code = TEXT_PROCESS_INTERVENE;
1923
0
        }
1924
4.98M
    } else {
1925
4.98M
        str.size = count;
1926
4.98M
        code = pdf_process_string_aux(penum, &str, gdata, NULL, &text_state);
1927
4.98M
    }
1928
4.98M
    return code;
1929
4.98M
}