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