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 /* Bitmap font implementation for pdfwrite */
18 #include "memory_.h"
19 #include "gx.h"
20 #include "gxpath.h"
21 #include "gserrors.h"
22 #include "gsutil.h"
23 #include "gdevpdfx.h"
24 #include "gdevpdfg.h"
25 #include "gdevpdtf.h"
26 #include "gdevpdti.h"
27 #include "gdevpdts.h"
28 #include "gdevpdtw.h"
29 #include "gdevpdtt.h"
30 #include "gdevpdfo.h"
31 #include "gxchar.h"        /* For gs_show_enum */
32 
33 /* ---------------- Private ---------------- */
34 
35 /* Define the structure for a CharProc pseudo-resource. */
36 /*typedef struct pdf_char_proc_s pdf_char_proc_t;*/  /* gdevpdfx.h */
37 struct pdf_char_proc_s {
38     pdf_resource_common(pdf_char_proc_t);
39     pdf_char_proc_ownership_t *owner_fonts; /* fonts using this charproc. */
40     int y_offset;                /* of character (0,0) */
41     int x_offset;                /* of character (0,0) */
42     gs_point real_width;        /* Not used with synthesised bitmap fonts. */
43     gs_point v;                        /* Not used with synthesised bitmap fonts. */
44 };
45 
46 /* The descriptor is public for pdf_resource_type_structs. */
47 gs_public_st_suffix_add1(st_pdf_char_proc, pdf_char_proc_t,
48   "pdf_char_proc_t", pdf_char_proc_enum_ptrs, pdf_char_proc_reloc_ptrs,
49   st_pdf_resource, owner_fonts);
50 
51 struct pdf_char_proc_ownership_s {
52     pdf_char_proc_t *char_proc;
53     pdf_char_proc_ownership_t *font_next;        /* next char_proc for same font */
54     pdf_char_proc_ownership_t *char_next;        /* next char_proc for same charproc */
55     pdf_font_resource_t *font;
56     gs_char char_code;                /* Character code in PDF font. */
57     gs_glyph glyph;                /* Glyph id in Postscript font. */
58     gs_string char_name;
59     bool duplicate_char_name;
60 };
61 gs_private_st_strings1_ptrs4(st_pdf_char_proc_ownership, pdf_char_proc_ownership_t,
62   "pdf_char_proc_ownership_t", pdf_char_proc_ownership_enum_ptrs,
63   pdf_char_proc_ownership_reloc_ptrs, char_name, char_proc, char_next, font_next, font);
64 
65 gs_private_st_ptrs1(st_pdf_bitmap_fonts, pdf_bitmap_fonts_t,
66   "pdf_bitmap_fonts_t", pdf_bitmap_fonts_enum_ptrs,
67   pdf_bitmap_fonts_reloc_ptrs, open_font);
68 
69 static inline long
pdf_char_proc_id(const pdf_char_proc_t * pcp)70 pdf_char_proc_id(const pdf_char_proc_t *pcp)
71 {
72     return pdf_resource_id((const pdf_resource_t *)pcp);
73 }
74 
75 /* Assign a code for a char_proc. */
76 static int
assign_char_code(gx_device_pdf * pdev,gs_text_enum_t * pte)77 assign_char_code(gx_device_pdf * pdev, gs_text_enum_t *pte)
78 {
79     pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
80     pdf_font_resource_t *pdfont = pbfs->open_font; /* Type 3 */
81     int i, c = 0, code;
82     uint operation = pte->text.operation;
83 
84     if (pbfs->bitmap_encoding_id == 0)
85         pbfs->bitmap_encoding_id = pdf_obj_ref(pdev);
86     if (pdfont == 0 || pdfont->u.simple.LastChar == 255 ||
87         !pbfs->use_open_font
88         ) {
89         /* Start a new synthesized font. */
90         char *pc;
91 
92         code = pdf_font_type3_alloc(pdev, &pdfont, pdf_write_contents_bitmap);
93         if (code < 0)
94             return code;
95         pdfont->u.simple.s.type3.bitmap_font = true;
96         if (pbfs->open_font == 0)
97             pdfont->rname[0] = 0;
98         else
99             strcpy(pdfont->rname, pbfs->open_font->rname);
100         pdfont->u.simple.s.type3.FontBBox.p.x = 0;
101         pdfont->u.simple.s.type3.FontBBox.p.y = 0;
102         pdfont->u.simple.s.type3.FontBBox.q.x = 0;
103         pdfont->u.simple.s.type3.FontBBox.q.y = 0;
104         pdfont->mark_glyph = NULL;
105         gs_make_identity(&pdfont->u.simple.s.type3.FontMatrix);
106         /*
107          * We "increment" the font name as a radix-26 "number".
108          * This cannot possibly overflow.
109          */
110         for (pc = pdfont->rname; *pc == 'Z'; ++pc)
111             *pc = '@';
112         if ((*pc)++ == 0)
113             *pc = 'A', pc[1] = 0;
114         pbfs->open_font = pdfont;
115         pbfs->use_open_font = true;
116         pdfont->u.simple.FirstChar = 255;
117     }
118     if ((operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) ||
119         (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR))) {
120         unsigned char p = *pte->text.data.bytes;
121         unsigned char index = p / 8, bit = 0x01 << (p % 8);
122 
123         if (pdfont->used[index] & bit) {
124             for (i = 0;i < 256;i++) {
125                 index = i / 8;
126                 bit = 0x01 << (i % 8);
127                 if (!(pdfont->used[index] & bit)) {
128                     c = i;
129                     break;
130                 }
131             }
132         } else
133             c = p;
134         pdfont->used[index] |= bit;
135         if (c > pdfont->u.simple.LastChar)
136             pdfont->u.simple.LastChar = c;
137 
138     } else {
139         unsigned char index, bit;
140         c = ++(pdfont->u.simple.LastChar);
141         index = c / 8;
142         bit = 0x01 << (c % 8);
143         pdfont->used[index] |= bit;
144     }
145     if (c < pdfont->u.simple.FirstChar)
146         pdfont->u.simple.FirstChar = c;
147 
148     pdfont->Widths[c] = psdf_round(pdev->char_width.x, 100, 10); /* See
149                         pdf_write_Widths about rounding. We need to provide
150                         a compatible data for Tj. */
151     if (c > pbfs->max_embedded_code)
152         pbfs->max_embedded_code = c;
153 
154     return c;
155 }
156 
157 /* Write the contents of a Type 3 bitmap or vector font resource. */
158 int
pdf_write_contents_bitmap(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)159 pdf_write_contents_bitmap(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
160 {
161     stream *s = pdev->strm;
162     const pdf_char_proc_ownership_t *pcpo;
163     long diff_id = 0;
164     int code;
165 
166     if (pdfont->u.simple.s.type3.bitmap_font)
167         diff_id = pdev->text->bitmap_fonts->bitmap_encoding_id;
168     else {
169         /* See comment in pdf_write_encoding. */
170         diff_id = pdf_obj_ref(pdev);
171     }
172     code = pdf_write_encoding_ref(pdev, pdfont, diff_id);
173     if (code < 0)
174         return code;
175     stream_puts(s, "/CharProcs <<");
176     /* Write real characters. */
177     for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo;
178          pcpo = pcpo->char_next
179          ) {
180         if (pdfont->u.simple.s.type3.bitmap_font)
181             pprintld2(s, "/a%ld %ld 0 R\n", (long)pcpo->char_code,
182                       pdf_char_proc_id(pcpo->char_proc));
183         else if (!pcpo-> duplicate_char_name) {
184             pdf_put_name(pdev, pcpo->char_name.data, pcpo->char_name.size);
185             pprintld1(s, " %ld 0 R\n", pdf_char_proc_id(pcpo->char_proc));
186         }
187         pdf_record_usage_by_parent(pdev, pdf_char_proc_id(pcpo->char_proc), pdfont->object->id);
188     }
189     stream_puts(s, ">>");
190     pprintg6(s, "/FontMatrix[%g %g %g %g %g %g]",
191             (float)pdfont->u.simple.s.type3.FontMatrix.xx,
192             (float)pdfont->u.simple.s.type3.FontMatrix.xy,
193             (float)pdfont->u.simple.s.type3.FontMatrix.yx,
194             (float)pdfont->u.simple.s.type3.FontMatrix.yy,
195             (float)pdfont->u.simple.s.type3.FontMatrix.tx,
196             (float)pdfont->u.simple.s.type3.FontMatrix.ty);
197     code = pdf_finish_write_contents_type3(pdev, pdfont);
198     if (code < 0)
199         return code;
200     if (!pdfont->u.simple.s.type3.bitmap_font && diff_id > 0) {
201         code = pdf_write_encoding(pdev, pdfont, diff_id, 0);
202         if (code < 0)
203             return code;
204     }
205     return 0;
206 }
207 
208 /* ---------------- Public ---------------- */
209 
210 /*
211  * Allocate and initialize bookkeeping for bitmap fonts.
212  */
213 pdf_bitmap_fonts_t *
pdf_bitmap_fonts_alloc(gs_memory_t * mem)214 pdf_bitmap_fonts_alloc(gs_memory_t *mem)
215 {
216     pdf_bitmap_fonts_t *pbfs =
217         gs_alloc_struct(mem, pdf_bitmap_fonts_t, &st_pdf_bitmap_fonts,
218                         "pdf_bitmap_fonts_alloc");
219 
220     if (pbfs == 0)
221         return 0;
222     memset(pbfs, 0, sizeof(*pbfs));
223     pbfs->max_embedded_code = -1;
224     return pbfs;
225 }
226 
227 /*
228  * Update text state at the end of a page.
229  */
230 void
pdf_close_text_page(gx_device_pdf * pdev)231 pdf_close_text_page(gx_device_pdf *pdev)
232 {
233     /*
234      * When Acrobat Reader 3 prints a file containing a Type 3 font with a
235      * non-standard Encoding, it apparently only emits the subset of the
236      * font actually used on the page.  Thus, if the "Download Fonts Once"
237      * option is selected, characters not used on the page where the font
238      * first appears will not be defined, and hence will print as blank if
239      * used on subsequent pages.  Thus, we can't allow a Type 3 font to
240      * add additional characters on subsequent pages.
241      */
242     if (pdev->CompatibilityLevel <= 1.2)
243         pdev->text->bitmap_fonts->use_open_font = false;
244 }
245 
246 int
pdf_charproc_y_offset(pdf_char_proc_t * pcp)247 pdf_charproc_y_offset(pdf_char_proc_t *pcp)
248 {
249     return pcp->y_offset;
250 }
251 
252 int
pdf_charproc_x_offset(pdf_char_proc_t * pcp)253 pdf_charproc_x_offset(pdf_char_proc_t *pcp)
254 {
255     return pcp->x_offset;
256 }
257 
258 /* Attach a CharProc to a font. */
259 static int
pdf_attach_charproc(gx_device_pdf * pdev,pdf_font_resource_t * pdfont,pdf_char_proc_t * pcp,gs_glyph glyph,gs_char char_code,const gs_const_string * gnstr)260 pdf_attach_charproc(gx_device_pdf * pdev, pdf_font_resource_t *pdfont, pdf_char_proc_t *pcp,
261                     gs_glyph glyph, gs_char char_code, const gs_const_string *gnstr)
262 {
263     pdf_char_proc_ownership_t *pcpo;
264     bool duplicate_char_name = false;
265 
266     for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
267         if (pcpo->glyph == glyph && pcpo->char_code == char_code)
268             return 0;
269     }
270     if (!pdfont->u.simple.s.type3.bitmap_font) {
271         for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
272             if (!bytes_compare(pcpo->char_name.data, pcpo->char_name.size, gnstr->data, gnstr->size)) {
273                 duplicate_char_name = true;
274                 break;
275             }
276         }
277     }
278     pcpo = gs_alloc_struct(pdev->pdf_memory,
279             pdf_char_proc_ownership_t, &st_pdf_char_proc_ownership, "pdf_attach_charproc");
280 
281     if (pcpo == NULL)
282         return_error(gs_error_VMerror);
283     pcpo->font = pdfont;
284     pcpo->char_next = pdfont->u.simple.s.type3.char_procs;
285     pdfont->u.simple.s.type3.char_procs = pcpo;
286     pcpo->char_proc = pcp;
287     pcpo->font_next = pcp->owner_fonts;
288     pcp->owner_fonts = pcpo;
289     pcpo->char_code = char_code;
290     pcpo->glyph = glyph;
291     if (gnstr == NULL) {
292         pcpo->char_name.data = 0;
293         pcpo->char_name.size = 0;
294     } else {
295         pcpo->char_name.data = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, gnstr->size, "storage for charproc name");
296         memcpy(pcpo->char_name.data, gnstr->data, gnstr->size);
297         pcpo->char_name.size = gnstr->size;
298 //        pcpo->char_name = *gnstr;
299     }
300     pcpo->duplicate_char_name = duplicate_char_name;
301     return 0;
302 }
303 
304 int
pdf_free_charproc_ownership(gx_device_pdf * pdev,pdf_resource_t * pres)305 pdf_free_charproc_ownership(gx_device_pdf * pdev, pdf_resource_t *pres)
306 {
307     pdf_char_proc_ownership_t *next, *pcpo = (pdf_char_proc_ownership_t *)pres;
308 
309     while (pcpo) {
310         next = pcpo->char_next;
311         if(pcpo->char_name.size != 0 && pcpo->char_name.data) {
312             gs_free_object(pdev->pdf_memory->non_gc_memory, pcpo->char_name.data, "free storage for charproc naem");
313             /* This causes PCL some trouble, don't know why yet FIXME-MEMORY
314             gs_free_string(pdev->pdf_memory, (byte *)pcpo->char_name.data, pcpo->char_name.size, "Free CharProc name");*/
315             pcpo->char_name.data = (byte *)0L;
316             pcpo->char_name.size = 0;
317         }
318         gs_free_object(pdev->pdf_memory, pcpo, "Free CharProc");
319         pcpo = next;
320     }
321     return 0;
322 }
323 
324 /* Begin a CharProc for a synthesized (bitmap) font. */
325 int
pdf_begin_char_proc(gx_device_pdf * pdev,int w,int h,int x_width,int y_offset,int x_offset,gs_id id,pdf_char_proc_t ** ppcp,pdf_stream_position_t * ppos)326 pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
327                     int y_offset, int x_offset, gs_id id, pdf_char_proc_t ** ppcp,
328                     pdf_stream_position_t * ppos)
329 {
330     gs_char char_code = 0;
331     pdf_bitmap_fonts_t *const pbfs = pdev->text->bitmap_fonts;
332     pdf_font_resource_t *font;
333     pdf_resource_t *pres;
334     pdf_char_proc_t *pcp;
335     int code;
336     /* This code added to store PCL bitmap glyphs in type 3 fonts where possible */
337     gs_glyph glyph = GS_NO_GLYPH;
338     gs_const_string *str = NULL;
339     gs_show_enum *show_enum = (gs_show_enum *)pdev->pte;
340     pdf_encoding_element_t *pet = 0;
341     /* Since this is for text searching, its only useful if the character code
342      * lies in an ASCII range, so we only handle some kinds of text layout.
343      */
344     int allowed_op = (show_enum->text.operation &
345         (TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR));
346 
347     /* Check to see the current font is a type 3. We can get here if pdfwrite decides
348      * it can't handle a font type, and renders to a bitmap instead. If that's the
349      * case then we can't add the bitmap to the existing font (its not a type 3 font)
350      * and must fall back to holding it in our fallback type 3 font 'collection'.
351      */
352     /* Because the bitmaps are stored directly in the cache they already have any
353      * effects caused by non-identity FontMatrix entries applied. So if the type 3
354      * font we created has a non-identity FontMatrix we can't use it and must
355      * go back to collecting the bitmap into our fallback font.
356      */
357     if ((show_enum->current_font->FontType == ft_user_defined ||
358         show_enum->current_font->FontType == ft_PDF_user_defined ||
359         show_enum->current_font->FontType == ft_PCL_user_defined ||
360         show_enum->current_font->FontType == ft_MicroType ||
361         show_enum->current_font->FontType == ft_GL2_stick_user_defined ||
362         show_enum->current_font->FontType == ft_GL2_531) && allowed_op &&
363         show_enum->current_font->FontMatrix.xx == 1 && show_enum->current_font->FontMatrix.xy == 0 &&
364         show_enum->current_font->FontMatrix.yx == 0 && show_enum->current_font->FontMatrix.yy == 1) {
365         pdf_char_proc_ownership_t *pcpo;
366 
367         gs_font_base *base = (gs_font_base *)show_enum->current_font;
368         code = pdf_attached_font_resource(pdev, show_enum->current_font, &font, NULL, NULL, NULL, NULL);
369         if (code < 0)
370             return code;
371         if (font == NULL)
372             return_error(gs_error_invalidfont);
373 
374         /* The text processing will have run past the glyph, so we need to 'back up'
375          * by one and get it again in order to get the character code and glyph, and update
376          * the pointer correctly.
377          */
378         show_enum->index--;
379         code = gs_default_next_char_glyph((gs_text_enum_t *)show_enum, (gs_char *)&char_code, &glyph);
380         if (code < 0)
381             return code;
382 
383         /* If the returned character code is outside the possible Encoding for
384          * a type 3 font, then set pet to NULL, this means we will fall back to
385          * the 'collection' font, as pet is checked below.
386          */
387         if ((int)char_code >= 0 && (int)char_code <= 255) {
388             pet = &font->u.simple.Encoding[char_code];
389             if (pet) {
390                 /* Check to see if we *already* have this glyph in this font. If
391                  * we do then we can't add it to this font. Setting pet to 0
392                  * falls back to the collection method.
393                  */
394                 for (pcpo = font->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
395                     if (pcpo->glyph == pet->glyph && pcpo->char_code == char_code) {
396                         pet = 0x00;
397                         break;
398                     }
399                 }
400             }
401         }
402         else
403             pet = 0x00;
404 
405         /* We need a glyph name for the type 3 font's Encoding, if we haven't got one
406          * then we need to give up, something about the font or text is not acceptable
407          * (see various comments above).
408          */
409         if (pet && pet->glyph != GS_NO_GLYPH && !(pet->str.size == 7 &&
410             !strncmp((const char *)pet->str.data, ".notdef", 7))) {
411             if (char_code < font->u.simple.FirstChar)
412                 font->u.simple.FirstChar = char_code;
413             if ((int)char_code > font->u.simple.LastChar)
414                 font->u.simple.LastChar = char_code;
415             base->FontBBox.q.x = max(base->FontBBox.q.x, w);
416             base->FontBBox.q.y = max(base->FontBBox.q.y, y_offset + h);
417             str = &pet->str;
418             glyph = pet->glyph;
419             /* This is to work around a weird Acrobat bug. If the Encoding of a type 3
420              * (possibly other types) is simply a standard encoding (eg WinAnsiEncoding)
421              * then Acrobat 4 & 8 just ignore the glyphs altogether. This forces us to write
422              * all the used glyphs as /Differencess, and that makes it work <sigh>
423              */
424             pet->is_difference = 1;
425             font->Widths[char_code] = psdf_round(pdev->char_width.x, 100, 10); /* See
426                         pdf_write_Widths about rounding. We need to provide
427                         a compatible data for Tj. */
428         } else {
429             char_code = assign_char_code(pdev, pdev->pte);
430             font = pbfs->open_font; /* Type 3 */
431         }
432     } else {
433         char_code = assign_char_code(pdev, pdev->pte);
434         font = pbfs->open_font; /* Type 3 */
435     }
436 
437     code = pdf_begin_resource(pdev, resourceCharProc, id, &pres);
438     if (code < 0)
439         return code;
440     pcp = (pdf_char_proc_t *) pres;
441     code = pdf_attach_charproc(pdev, font, pcp, glyph, char_code, str);
442     if (code < 0)
443         return code;
444     pres->object->written = true;
445     {
446         stream *s = pdev->strm;
447 
448         /*
449          * The resource file is positionable, so rather than use an
450          * object reference for the length, we'll go back and fill it in
451          * at the end of the definition.  Take 1M as the longest
452          * definition we can handle.  (This used to be 10K, but there was
453          * a real file that exceeded this limit.)
454          */
455         stream_puts(s, "<</Length       >>stream\n");
456         ppos->start_pos = stell(s);
457     }
458     code = pdf_begin_encrypt(pdev, &pdev->strm, pres->object->id);
459     if (code < 0)
460         return code;
461     pcp->y_offset = y_offset;
462     pcp->x_offset = x_offset;
463     font->u.simple.s.type3.FontBBox.q.x =
464         max(font->u.simple.s.type3.FontBBox.q.x, w);
465     font->u.simple.s.type3.FontBBox.q.y =
466         max(font->u.simple.s.type3.FontBBox.q.y, y_offset + h);
467     font->u.simple.s.type3.max_y_offset =
468         max(font->u.simple.s.type3.max_y_offset, h + (h >> 2));
469     pcp->real_width.x = w;
470     pcp->real_width.y = y_offset + h;
471     *ppcp = pcp;
472     return 0;
473 }
474 
475 /* End a CharProc. */
476 int
pdf_end_char_proc(gx_device_pdf * pdev,pdf_stream_position_t * ppos)477 pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos)
478 {
479     stream *s;
480     gs_offset_t start_pos, end_pos, length;
481 
482     pdf_end_encrypt(pdev);
483     s = pdev->strm;
484     start_pos = ppos->start_pos;
485     end_pos = stell(s);
486     length = end_pos - start_pos;
487     if (length > 999999)
488         return_error(gs_error_limitcheck);
489     sseek(s, start_pos - 15);
490     pprintd1(s, "%d", length);
491     sseek(s, end_pos);
492     if (pdev->PDFA != 0)
493         stream_puts(s, "\n");
494     stream_puts(s, "endstream\n");
495     pdf_end_separate(pdev, resourceCharProc);
496     return 0;
497 }
498 
499 /* Mark glyph names for garbager. */
500 void
pdf_mark_glyph_names(const pdf_font_resource_t * pdfont,const gs_memory_t * memory)501 pdf_mark_glyph_names(const pdf_font_resource_t *pdfont, const gs_memory_t *memory)
502 {
503     if (pdfont->mark_glyph == NULL) {
504         /* Synthesised bitmap fonts pass here. */
505         return;
506     }
507     if (pdfont->u.simple.Encoding != NULL) {
508          int i;
509 
510          for (i = 0; i < 256; i++)
511              if (pdfont->u.simple.Encoding[i].glyph != GS_NO_GLYPH)
512                 pdfont->mark_glyph(memory, pdfont->u.simple.Encoding[i].glyph, pdfont->mark_glyph_data);
513      }
514     if (pdfont->FontType == ft_user_defined ||
515         pdfont->FontType == ft_PDF_user_defined ||
516         pdfont->FontType == ft_PCL_user_defined ||
517         pdfont->FontType == ft_MicroType ||
518         pdfont->FontType == ft_GL2_stick_user_defined ||
519         pdfont->FontType == ft_GL2_531) {
520         const pdf_char_proc_ownership_t *pcpo = pdfont->u.simple.s.type3.char_procs;
521 
522         for (; pcpo != NULL; pcpo = pcpo->font_next)
523             pdfont->mark_glyph(memory, pcpo->glyph, pdfont->mark_glyph_data);
524     }
525 }
526 
527 /* Put out a reference to an image as a character in a synthesized font. */
528 int
pdf_do_char_image(gx_device_pdf * pdev,const pdf_char_proc_t * pcp,const gs_matrix * pimat)529 pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
530                   const gs_matrix * pimat)
531 {
532     /* We need to choose a font, which use the charproc.
533        In most cases it is the last font, which the charproc is attached to.
534        If the charproc is substituted, it causes a font change. */
535     const pdf_char_proc_ownership_t * pcpo = pcp->owner_fonts;
536     pdf_font_resource_t *pdfont = pcpo->font;
537     byte ch = pcpo->char_code;
538     pdf_text_state_values_t values;
539 
540     values.character_spacing = 0;
541     values.pdfont = pdfont;
542     values.size = 1;
543     values.matrix = *pimat;
544     values.render_mode = pdev->pte->pgs->text_rendering_mode;
545     values.word_spacing = 0;
546     pdf_set_text_state_values(pdev, &values);
547     pdf_bitmap_char_update_bbox(pdev, pcp->x_offset, pcp->y_offset, pcp->real_width.x, pcp->real_width.y);
548     pdf_append_chars(pdev, &ch, 1, pdfont->Widths[ch] * pimat->xx, 0.0, false);
549     return 0;
550 }
551 
552 /*
553  * Write the Encoding for bitmap fonts, if needed.
554  */
555 int
pdf_write_bitmap_fonts_Encoding(gx_device_pdf * pdev)556 pdf_write_bitmap_fonts_Encoding(gx_device_pdf *pdev)
557 {
558     pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
559 
560     if (pbfs->bitmap_encoding_id) {
561         stream *s;
562         int i;
563 
564         pdf_open_separate(pdev, pbfs->bitmap_encoding_id, resourceEncoding);
565         s = pdev->strm;
566         /*
567          * Even though the PDF reference documentation says that a
568          * BaseEncoding key is required unless the encoding is
569          * "based on the base font's encoding" (and there is no base
570          * font in this case), Acrobat 2.1 gives an error if the
571          * BaseEncoding key is present.
572          */
573         stream_puts(s, "<</Type/Encoding/Differences[0");
574         for (i = 0; i <= pbfs->max_embedded_code; ++i) {
575             if (!(i & 15))
576                 stream_puts(s, "\n");
577             pprintd1(s, "/a%d", i);
578         }
579         stream_puts(s, "\n] >>\n");
580         pdf_end_separate(pdev, resourceEncoding);
581         pbfs->bitmap_encoding_id = 0;
582     }
583     return 0;
584 }
585 
586 /*
587  * Start charproc accumulation for a Type 3 font.
588  */
589 int
pdf_start_charproc_accum(gx_device_pdf * pdev)590 pdf_start_charproc_accum(gx_device_pdf *pdev)
591 {
592     pdf_char_proc_t *pcp;
593     pdf_resource_t *pres;
594     int id = gs_next_ids(pdev->memory, 1);
595     int code = pdf_enter_substream(pdev, resourceCharProc, id,
596                                    &pres, false, pdev->CompressFonts);
597 
598     if (code < 0)
599        return code;
600     pres->rid = id;
601     pcp = (pdf_char_proc_t *)pres;
602     pcp->owner_fonts = NULL;
603     return 0;
604 }
605 
606 /*
607  * Install charproc accumulator for a Type 3 font.
608  */
609 int
pdf_set_charproc_attrs(gx_device_pdf * pdev,gs_font * font,double * pw,int narg,gs_text_cache_control_t control,gs_char ch,bool scale_100)610 pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, double *pw, int narg,
611                 gs_text_cache_control_t control, gs_char ch, bool scale_100)
612 {
613     pdf_font_resource_t *pdfont;
614     pdf_resource_t *pres = pdev->accumulating_substream_resource;
615     pdf_char_proc_t *pcp;
616     int code;
617 
618     code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
619     if (code < 0)
620         return code;
621     pcp = (pdf_char_proc_t *)pres;
622     pcp->owner_fonts = NULL;
623     pcp->real_width.x = pw[font->WMode && narg > 6 ? 6 : 0];
624     pcp->real_width.y = pw[font->WMode && narg > 6 ? 7 : 1];
625     pcp->v.x = (narg > 8 ? pw[8] : 0);
626     pcp->v.y = (narg > 8 ? pw[9] : 0);
627     if (control == TEXT_SET_CHAR_WIDTH) {
628         /* PLRM 5.7.1 "BuildGlyph" reads : "Normally, it is unnecessary and
629         undesirable to initialize the current color parameter, because show
630         is defined to paint glyphs with the current color."
631         However comparefiles/Bug687044.ps doesn't follow that. */
632         pdev->skip_colors = false;
633         pprintg1(pdev->strm, "%g 0 d0\n", (float)pw[0]);
634         /* The colour change described above can't affect PCL fonts and we need
635          * all glyphs to be noted as cached in order for the bitmap font cache
636          * probing to work properly.
637          */
638         if (font->FontType == ft_PCL_user_defined || font->FontType == ft_GL2_stick_user_defined
639             || font->FontType == ft_GL2_531 || font->FontType == ft_MicroType)
640             pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
641     } else {
642         double d;
643         pdev->skip_colors = true;
644         if (pw[4] < pw[2]) {
645             d = pw[2];
646             pw[2] = pw[4];
647             pw[4] = d;
648         }
649         if (pw[5] < pw[3]) {
650             d = pw[5];
651             pw[5] = pw[3];
652             pw[3] = d;
653         }
654         pprintg6(pdev->strm, "%g %g %g %g %g %g d1\n",
655             (float)pw[0], (float)0.0, (float)pw[2],
656             (float)pw[3], (float)pw[4], (float)pw[5]);
657         pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
658     }
659     /* See comments in pdf_text_process regarding type 3 CharProc accumulation
660      * Initially this matrix was emitted there, at the start of the accumulator
661      * but if we do that then GS incorrectly applied the matrix to the 'd1'
662      * operator. We write the scale matrix here because this is *after* the
663      * 'd1' has been emitted above, and so does not affect it.
664      */
665     if (scale_100) {
666     code = stream_puts(pdev->strm, "0.01 0 0 0.01 0 0 cm\n");
667     if (code < 0)
668         return code;
669     }
670     return 0;
671 }
672 
673 /*
674  * Open a stream object in the temporary file.
675  */
676 
677 int
pdf_open_aside(gx_device_pdf * pdev,pdf_resource_type_t rtype,gs_id id,pdf_resource_t ** ppres,bool reserve_object_id,int options)678 pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype,
679         gs_id id, pdf_resource_t **ppres, bool reserve_object_id, int options)
680 {
681     int code;
682     pdf_resource_t *pres;
683     stream *s, *save_strm = pdev->strm;
684     pdf_data_writer_t writer;
685     static const pdf_filter_names_t fnames = {
686         PDF_FILTER_NAMES
687     };
688 
689     pdev->streams.save_strm = pdev->strm;
690 
691     if (rtype >= NUM_RESOURCE_TYPES)
692         rtype = resourceOther;
693     code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, id),
694                 pdf_resource_type_structs[rtype], &pres, reserve_object_id ? 0 : -1);
695     if (code < 0)
696         return code;
697     cos_become(pres->object, cos_type_stream);
698     s = cos_write_stream_alloc((cos_stream_t *)pres->object, pdev, "pdf_enter_substream");
699     if (s == 0)
700         return_error(gs_error_VMerror);
701     pdev->strm = s;
702     code = pdf_append_data_stream_filters(pdev, &writer,
703                              options | DATA_STREAM_NOLENGTH, pres->object->id);
704     if (code < 0) {
705         pdev->strm = save_strm;
706         return code;
707     }
708     code = pdf_put_filters((cos_dict_t *)pres->object, pdev, writer.binary.strm, &fnames);
709     if (code < 0) {
710         pdev->strm = save_strm;
711         return code;
712     }
713     pdev->strm = writer.binary.strm;
714     *ppres = pres;
715     return 0;
716 }
717 
718 /*
719  * Close a stream object in the temporary file.
720  */
721 int
pdf_close_aside(gx_device_pdf * pdev)722 pdf_close_aside(gx_device_pdf *pdev)
723 {
724     /* We should call pdf_end_data here, but we don't want to put pdf_data_writer_t
725        into pdf_substream_save stack to simplify garbager descriptors.
726        Use a lower level functions instead that. */
727     stream *s = pdev->strm;
728     cos_stream_t *pcs = cos_stream_from_pipeline(s);
729     int status = s_close_filters(&s, NULL);
730 
731     pdev->strm = pdev->streams.save_strm;
732     if (status < 0)
733          return(gs_note_error(gs_error_ioerror));
734 
735     if (!pcs)
736         return gs_note_error(gs_error_ioerror);
737 
738     pcs->is_open = false;
739     return 0;
740 }
741 
742 /*
743  * Enter the substream accumulation mode.
744  */
745 int
pdf_enter_substream(gx_device_pdf * pdev,pdf_resource_type_t rtype,gs_id id,pdf_resource_t ** ppres,bool reserve_object_id,bool compress)746 pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype,
747         gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress)
748 {
749     int sbstack_ptr = pdev->sbstack_depth;
750     pdf_resource_t *pres;
751     stream *save_strm = pdev->strm;
752     int code;
753 
754     if (pdev->sbstack_depth >= pdev->sbstack_size)
755         return_error(gs_error_unregistered); /* Must not happen. */
756     if (pdev->sbstack[sbstack_ptr].text_state == 0) {
757         pdev->sbstack[sbstack_ptr].text_state = pdf_text_state_alloc(pdev->pdf_memory);
758         if (pdev->sbstack[sbstack_ptr].text_state == 0)
759             return_error(gs_error_VMerror);
760     }
761     code = pdf_open_aside(pdev, rtype, id, &pres, reserve_object_id,
762                     (compress ? DATA_STREAM_COMPRESS : 0));
763     if (code < 0)
764         return code;
765     code = pdf_save_viewer_state(pdev, NULL);
766     if (code < 0) {
767         pdev->strm = save_strm;
768         return code;
769     }
770     pdev->sbstack[sbstack_ptr].context = pdev->context;
771     pdf_text_state_copy(pdev->sbstack[sbstack_ptr].text_state, pdev->text->text_state);
772     pdf_set_text_state_default(pdev->text->text_state);
773     pdev->sbstack[sbstack_ptr].clip_path = pdev->clip_path;
774     pdev->clip_path = 0;
775     pdev->sbstack[sbstack_ptr].clip_path_id = pdev->clip_path_id;
776     pdev->clip_path_id = pdev->no_clip_path_id;
777     pdev->sbstack[sbstack_ptr].vgstack_bottom = pdev->vgstack_bottom;
778     pdev->vgstack_bottom = pdev->vgstack_depth;
779     pdev->sbstack[sbstack_ptr].strm = save_strm;
780     pdev->sbstack[sbstack_ptr].procsets = pdev->procsets;
781     pdev->sbstack[sbstack_ptr].substream_Resources = pdev->substream_Resources;
782     pdev->sbstack[sbstack_ptr].skip_colors = pdev->skip_colors;
783     pdev->sbstack[sbstack_ptr].font3 = pdev->font3;
784     pdev->sbstack[sbstack_ptr].accumulating_substream_resource = pdev->accumulating_substream_resource;
785     pdev->sbstack[sbstack_ptr].charproc_just_accumulated = pdev->charproc_just_accumulated;
786     pdev->sbstack[sbstack_ptr].accumulating_a_global_object = pdev->accumulating_a_global_object;
787     pdev->sbstack[sbstack_ptr].pres_soft_mask_dict = pdev->pres_soft_mask_dict;
788     pdev->sbstack[sbstack_ptr].objname = pdev->objname;
789     pdev->sbstack[sbstack_ptr].last_charpath_op = pdev->last_charpath_op;
790     pdev->skip_colors = false;
791     pdev->charproc_just_accumulated = false;
792     pdev->pres_soft_mask_dict = NULL;
793     pdev->objname.data = NULL;
794     pdev->objname.size = 0;
795     /* Do not reset pdev->accumulating_a_global_object - it inherits. */
796     pdev->sbstack_depth++;
797     pdev->procsets = 0;
798     pdev->font3 = 0;
799     pdev->context = PDF_IN_STREAM;
800     pdev->accumulating_substream_resource = pres;
801     pdev->last_charpath_op = 0;
802     /* Do not alter type3charpath, inherit the current value. We need to know if */
803     /* we are inside a charpath operation, and only reset this when the charpath */
804     /* is complete */
805     if (rtype != resourceXObject)
806         pdf_reset_graphics(pdev);
807     else {
808         if (pdev->vg_initial_set)
809             pdev->state.blend_mode = pdev->vg_initial.blend_mode;
810     }
811     *ppres = pres;
812     return 0;
813 }
814 
815 /*
816  * Exit the substream accumulation mode.
817  */
818 int
pdf_exit_substream(gx_device_pdf * pdev)819 pdf_exit_substream(gx_device_pdf *pdev)
820 {
821     int code, code1;
822     int sbstack_ptr;
823 
824     if (pdev->sbstack_depth <= 0)
825         return_error(gs_error_unregistered); /* Must not happen. */
826     code = pdf_open_contents(pdev, PDF_IN_STREAM);
827     sbstack_ptr = pdev->sbstack_depth - 1;
828     while (pdev->vgstack_depth > pdev->vgstack_bottom) {
829         code1 = pdf_restore_viewer_state(pdev, pdev->strm);
830         if (code >= 0)
831             code = code1;
832     }
833     if (pdev->clip_path != 0)
834         gx_path_free(pdev->clip_path, "pdf_end_charproc_accum");
835     code1 = pdf_close_aside(pdev);
836     if (code1 < 0 && code >= 0)
837         code = code1;
838     pdev->context = pdev->sbstack[sbstack_ptr].context;
839     pdf_text_state_copy(pdev->text->text_state, pdev->sbstack[sbstack_ptr].text_state);
840     gs_free_object(pdev->pdf_memory, pdev->sbstack[sbstack_ptr].text_state, "free text state for stream");
841     pdev->sbstack[sbstack_ptr].text_state = 0;
842     pdev->clip_path = pdev->sbstack[sbstack_ptr].clip_path;
843     pdev->sbstack[sbstack_ptr].clip_path = 0;
844     pdev->clip_path_id = pdev->sbstack[sbstack_ptr].clip_path_id;
845     pdev->vgstack_bottom = pdev->sbstack[sbstack_ptr].vgstack_bottom;
846     pdev->strm = pdev->sbstack[sbstack_ptr].strm;
847     pdev->sbstack[sbstack_ptr].strm = 0;
848     pdev->procsets = pdev->sbstack[sbstack_ptr].procsets;
849     pdev->substream_Resources = pdev->sbstack[sbstack_ptr].substream_Resources;
850     pdev->sbstack[sbstack_ptr].substream_Resources = 0;
851     pdev->skip_colors = pdev->sbstack[sbstack_ptr].skip_colors;
852     pdev->font3 = pdev->sbstack[sbstack_ptr].font3;
853     pdev->sbstack[sbstack_ptr].font3 = 0;
854     pdev->accumulating_substream_resource = pdev->sbstack[sbstack_ptr].accumulating_substream_resource;
855     pdev->sbstack[sbstack_ptr].accumulating_substream_resource = 0;
856     pdev->charproc_just_accumulated = pdev->sbstack[sbstack_ptr].charproc_just_accumulated;
857     pdev->accumulating_a_global_object = pdev->sbstack[sbstack_ptr].accumulating_a_global_object;
858     pdev->pres_soft_mask_dict = pdev->sbstack[sbstack_ptr].pres_soft_mask_dict;
859     pdev->objname = pdev->sbstack[sbstack_ptr].objname;
860     pdev->last_charpath_op = pdev->sbstack[sbstack_ptr].last_charpath_op;
861     pdev->sbstack_depth = sbstack_ptr;
862     code1 = pdf_restore_viewer_state(pdev, NULL);
863     if (code1 < 0 && code >= 0)
864         code = code1;
865     return code;
866 }
867 
868 static bool
pdf_is_same_charproc_attrs1(gx_device_pdf * pdev,pdf_char_proc_t * pcp0,pdf_char_proc_t * pcp1)869 pdf_is_same_charproc_attrs1(gx_device_pdf *pdev, pdf_char_proc_t *pcp0, pdf_char_proc_t *pcp1)
870 {
871     if (pcp0->real_width.x != pcp1->real_width.x)
872         return false;
873     if (pcp0->real_width.y != pcp1->real_width.y)
874         return false;
875     if (pcp0->v.x != pcp1->v.x)
876         return false;
877     if (pcp0->v.y != pcp1->v.y)
878         return false;
879     return true;
880 }
881 
882 typedef struct charproc_compatibility_data_s {
883     const pdf_char_glyph_pairs_t *cgp;
884     pdf_font_resource_t *pdfont;
885     gs_char char_code;
886     gs_glyph glyph;
887     gs_font *font;
888 } charproc_compatibility_data_t;
889 
890 static bool
is_char_code_used(pdf_font_resource_t * pdfont,gs_char char_code)891 is_char_code_used(pdf_font_resource_t *pdfont, gs_char char_code)
892 {
893     pdf_char_proc_ownership_t *pcpo;
894 
895     for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
896         if (pcpo->char_code == char_code) {
897             return true;
898         }
899     }
900     return false;
901 }
902 
903 static int
pdf_is_charproc_compatible(gx_device_pdf * pdev,pdf_resource_t * pres0,pdf_resource_t * pres1)904 pdf_is_charproc_compatible(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
905 {
906     charproc_compatibility_data_t *data = (charproc_compatibility_data_t *)pdev->find_resource_param;
907     pdf_char_proc_t *pcp0 = (pdf_char_proc_t *)pres0;
908     pdf_char_proc_t *pcp1 = (pdf_char_proc_t *)pres1;
909     pdf_font_resource_t *pdfont = data->pdfont;
910     pdf_char_proc_ownership_t *pcpo;
911     pdf_font_cache_elem_t **e;
912     bool can_add_to_current_font = false, computed_can_add_to_current_font = false;
913 
914     /* Does it have same attributes ? */
915     if (!pdf_is_same_charproc_attrs1(pdev, pcp0, pcp1))
916         return 0;
917     /* Is it from same font ? */
918     for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
919         if (pdfont == pcpo->font) {
920             /* Check for encoding conflict. */
921             if (pcpo->char_code == data->char_code && pcpo->glyph == data->glyph)
922                 return 1; /* Same char code. */
923             if (!computed_can_add_to_current_font) {
924                 can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
925                 computed_can_add_to_current_font = true;
926             }
927             if (can_add_to_current_font)
928                 return 1; /* No conflict. */
929         }
930     }
931     /* Look for another font with same encoding,
932        because we want to reduce the number of new fonts.
933        We also restrict with ones attached to same PS font,
934        otherwise it creates too mixed fonts and disturbs word breaks.
935      */
936     e = pdf_locate_font_cache_elem(pdev, data->font);
937     if (e != NULL) {
938         for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
939             if (pcpo->char_code != data->char_code || pcpo->glyph != data->glyph)
940                 continue; /* Need same Encoding to generate a proper ToUnicode. */
941             if (pdfont->u.simple.s.type3.bitmap_font != pcpo->font->u.simple.s.type3.bitmap_font)
942                 continue;
943             if (gs_matrix_compare(&pdfont->u.simple.s.type3.FontMatrix, &pcpo->font->u.simple.s.type3.FontMatrix))
944                 continue;
945             if (data->cgp != NULL) {
946                 if (!pdf_check_encoding_compatibility(pcpo->font, data->cgp->s, data->cgp->num_all_chars))
947                     continue;
948             }
949             if ((*e)->pdfont != pcpo->font)
950                 continue;
951             data->pdfont = pcpo->font; /* Switch to the other font. */
952             return 1;
953         }
954     }
955     /* Check whether it can be added into the current font. */
956     if (!computed_can_add_to_current_font)
957         can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
958     if (!can_add_to_current_font) {
959         /* Can't substitute due to encoding conflict. */
960         return 0;
961     }
962     /* The current font will share it with another font. */
963     return 1;
964 }
965 
966 static int
pdf_find_same_charproc_aux(gx_device_pdf * pdev,pdf_font_resource_t ** ppdfont,pdf_char_proc_t ** ppcp)967 pdf_find_same_charproc_aux(gx_device_pdf *pdev,
968             pdf_font_resource_t **ppdfont, pdf_char_proc_t **ppcp)
969 {
970     pdf_char_proc_ownership_t *pcpo;
971     int code;
972 
973     /* fixme: this passes parameters to pdf_is_charproc_compatible
974        through special gx_device_pdf field pdev->find_resource_param
975        due to prototype limitation of pdf_find_same_resource.
976        It would be better to change the client data argument type in there to void. */
977     for (pcpo = (*ppdfont)->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
978         pdf_char_proc_t *pcp = pcpo->char_proc;
979 
980         if (*ppcp != pcp && pdf_is_same_charproc_attrs1(pdev, *ppcp, pcp)) {
981             cos_object_t *pco0 = pcp->object;
982             cos_object_t *pco1 = (*ppcp)->object;
983 
984             code = pco0->cos_procs->equal(pco0, pco1, pdev);
985             if (code < 0) {
986                 return code;
987             }
988             if (code) {
989                 *ppcp = pcp;
990                 return 1;
991             }
992         }
993     }
994     return pdf_find_same_resource(pdev, resourceCharProc, (pdf_resource_t **)ppcp, pdf_is_charproc_compatible);
995 }
996 static int
pdf_find_same_charproc(gx_device_pdf * pdev,pdf_font_resource_t ** ppdfont,const pdf_char_glyph_pairs_t * cgp,pdf_char_proc_t ** ppcp,gs_glyph glyph,gs_char char_code,gs_font * font)997 pdf_find_same_charproc(gx_device_pdf *pdev,
998             pdf_font_resource_t **ppdfont, const pdf_char_glyph_pairs_t *cgp,
999             pdf_char_proc_t **ppcp, gs_glyph glyph, gs_char char_code,
1000             gs_font *font)
1001 {
1002     charproc_compatibility_data_t data;
1003     int code;
1004 
1005     data.cgp = cgp;
1006     data.pdfont = *ppdfont;
1007     data.char_code = char_code;
1008     data.glyph = glyph;
1009     data.font = font;
1010     pdev->find_resource_param = &data;
1011     code = pdf_find_same_charproc_aux(pdev, ppdfont, ppcp);
1012     pdev->find_resource_param = NULL;
1013     *ppdfont = data.pdfont;
1014     return code;
1015 }
1016 
1017 static bool
pdf_is_charproc_defined(gx_device_pdf * pdev,pdf_font_resource_t * pdfont,gs_char ch)1018 pdf_is_charproc_defined(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, gs_char ch)
1019 {
1020     pdf_char_proc_ownership_t *pcpo;
1021 
1022     for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
1023         if (pcpo->char_code == ch)
1024             return true;
1025     }
1026     return false;
1027 }
1028 
1029 static int
complete_adding_char(gx_device_pdf * pdev,gs_font * font,gs_glyph glyph,gs_char ch,pdf_char_proc_t * pcp,const gs_const_string * gnstr)1030 complete_adding_char(gx_device_pdf *pdev, gs_font *font,
1031                      gs_glyph glyph, gs_char ch, pdf_char_proc_t *pcp,
1032                      const gs_const_string *gnstr)
1033 {
1034     pdf_font_resource_t *pdfont;
1035     double *real_widths;
1036     byte *glyph_usage;
1037     int char_cache_size, width_cache_size;
1038     pdf_encoding_element_t *pet;
1039     int code;
1040 
1041     code = pdf_attached_font_resource(pdev, font, &pdfont,
1042                 &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1043     if (code < 0)
1044         return code;
1045     code = pdf_attach_charproc(pdev, pdfont, pcp, glyph, ch, gnstr);
1046     if (code < 0)
1047         return code;
1048     if (ch >= char_cache_size || ch >= width_cache_size)
1049         return_error(gs_error_unregistered); /* Must not happen. */
1050     pet = &pdfont->u.simple.Encoding[ch];
1051     pdfont->Widths[ch] = pcp->real_width.x;
1052     real_widths[ch * 2    ] = pcp->real_width.x;
1053     real_widths[ch * 2 + 1] = pcp->real_width.y;
1054     glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1055     pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
1056     if (pdfont->u.simple.v != NULL && font->WMode) {
1057         pdfont->u.simple.v[ch].x = pcp->v.x;
1058         pdfont->u.simple.v[ch].y = pcp->v.x;
1059     }
1060     pet->glyph = glyph;
1061     pet->str = *gnstr;
1062     pet->is_difference = true;
1063     if (pdfont->u.simple.LastChar < (int)ch)
1064         pdfont->u.simple.LastChar = (int)ch;
1065     if (pdfont->u.simple.FirstChar > (int)ch)
1066         pdfont->u.simple.FirstChar = (int)ch;
1067     return 0;
1068 }
1069 
1070 static int
pdf_char_widths_from_charprocs(gx_device_pdf * pdev,gs_font * font)1071 pdf_char_widths_from_charprocs(gx_device_pdf *pdev, gs_font *font)
1072 {
1073     pdf_font_resource_t *pdfont;
1074     double *real_widths;
1075     byte *glyph_usage;
1076     int char_cache_size, width_cache_size;
1077     pdf_char_proc_ownership_t *pcpo;
1078     int code;
1079 
1080     code = pdf_attached_font_resource(pdev, font, &pdfont,
1081                 &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1082     if (code < 0)
1083         return code;
1084     for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
1085         pdf_char_proc_t *pcp = pcpo->char_proc;
1086         gs_char ch = pcpo->char_code;
1087 
1088         real_widths[ch * 2    ] = pcp->real_width.x;
1089         real_widths[ch * 2 + 1] = pcp->real_width.y;
1090         glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1091     }
1092     return 0;
1093 }
1094 
1095 /*
1096  * Complete charproc accumulation for a Type 3 font.
1097  */
1098 int
pdf_end_charproc_accum(gx_device_pdf * pdev,gs_font * font,const pdf_char_glyph_pairs_t * cgp,gs_glyph glyph,gs_char output_char_code,const gs_const_string * gnstr)1099 pdf_end_charproc_accum(gx_device_pdf *pdev, gs_font *font, const pdf_char_glyph_pairs_t *cgp,
1100                        gs_glyph glyph, gs_char output_char_code, const gs_const_string *gnstr)
1101 {
1102     int code;
1103     pdf_resource_t *pres = (pdf_resource_t *)pdev->accumulating_substream_resource;
1104     /* We could use pdfont->u.simple.s.type3.char_procs insted the thing above
1105        unless the font is defined recursively.
1106        But we don't want such assumption. */
1107     pdf_char_proc_t *pcp = (pdf_char_proc_t *)pres;
1108     pdf_font_resource_t *pdfont;
1109     gs_char ch = output_char_code;
1110     bool checking_glyph_variation = false;
1111 
1112     if (ch == GS_NO_CHAR)
1113         return_error(gs_error_unregistered); /* Must not happen. */
1114     if (ch >= 256)
1115         return_error(gs_error_unregistered); /* Must not happen. */
1116     code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
1117     if (code < 0)
1118         return code;
1119     if (pdfont != (pdf_font_resource_t *)pdev->font3)
1120         return_error(gs_error_unregistered); /* Must not happen. */
1121     code = pdf_exit_substream(pdev);
1122     if (code < 0)
1123         return code;
1124     if (!(pdfont->used[ch >> 3] & (0x80 >> (ch & 7))) ||
1125         !(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))) {
1126         /* First appearence or not cached - check for duplicates. */
1127         pdf_font_resource_t *pdfont1 = pdfont;
1128 
1129         checking_glyph_variation = true;
1130         /* CAUTION : a possible font change. */
1131         code = pdf_find_same_charproc(pdev, &pdfont, cgp, &pcp, glyph, ch, font);
1132         if (code < 0)
1133             return code;
1134         if (code != 0) {
1135             code = pdf_cancel_resource(pdev, pres, resourceCharProc);
1136             if (code < 0)
1137                 return code;
1138             pdf_forget_resource(pdev, pres, resourceCharProc);
1139             if (pdfont1 != pdfont) {
1140                 code = pdf_attach_font_resource(pdev, font, pdfont);
1141                 if (code < 0)
1142                     return code;
1143                 code = pdf_char_widths_from_charprocs(pdev, font);
1144                 if (code < 0)
1145                     return code;
1146             }
1147             pdev->charproc_just_accumulated = true;
1148             return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
1149         }
1150         if (pdf_is_charproc_defined(pdev, pdfont, ch)) {
1151             /* Encoding conflict after a font change. */
1152             gs_font *base_font = font, *below;
1153 
1154             while ((below = base_font->base) != base_font &&
1155                     base_font->procs.same_font(base_font, below, FONT_SAME_OUTLINES))
1156                 base_font = below;
1157             code = pdf_make_font3_resource(pdev, base_font, &pdfont);
1158             if (code < 0)
1159                 return code;
1160             code = pdf_attach_font_resource(pdev, font, pdfont);
1161             if (code < 0)
1162                 return code;
1163         }
1164     }
1165     pdf_reserve_object_id(pdev, pres, 0);
1166     if (checking_glyph_variation)
1167         pdev->charproc_just_accumulated = true;
1168     return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
1169 }
1170 
1171 /* Add procsets to substream Resources. */
1172 int
pdf_add_procsets(cos_dict_t * pcd,pdf_procset_t procsets)1173 pdf_add_procsets(cos_dict_t *pcd, pdf_procset_t procsets)
1174 {
1175     char str[5 + 7 + 7 + 7 + 5 + 2];
1176     cos_value_t v;
1177 
1178     strcpy(str, "[/PDF");
1179     if (procsets & ImageB)
1180         strcat(str, "/ImageB");
1181     if (procsets & ImageC)
1182         strcat(str, "/ImageC");
1183     if (procsets & ImageI)
1184         strcat(str, "/ImageI");
1185     if (procsets & Text)
1186         strcat(str, "/Text");
1187     strcat(str, "]");
1188     cos_string_value(&v, (byte *)str, strlen(str));
1189     return cos_dict_put_c_key(pcd, "/ProcSet", &v);
1190 }
1191 
1192 /* Add a resource to substream Resources. */
1193 int
pdf_add_resource(gx_device_pdf * pdev,cos_dict_t * pcd,const char * key,pdf_resource_t * pres)1194 pdf_add_resource(gx_device_pdf *pdev, cos_dict_t *pcd, const char *key, pdf_resource_t *pres)
1195 {
1196     if (pcd != 0) {
1197         const cos_value_t *v = cos_dict_find(pcd, (const byte *)key, strlen(key));
1198         cos_dict_t *list;
1199         int code;
1200         char buf[10 + (sizeof(long) * 8 / 3 + 1)], buf1[sizeof(pres->rname) + 1];
1201 
1202         if (pdev->ForOPDFRead && !pres->global && pdev->accumulating_a_global_object) {
1203             pres->global = true;
1204             code = cos_dict_put_c_key_bool((cos_dict_t *)pres->object, "/.Global", true);
1205             if (code < 0)
1206                 return code;
1207         }
1208         gs_sprintf(buf, "%ld 0 R\n", pres->object->id);
1209         if (v != NULL) {
1210             if (v->value_type != COS_VALUE_OBJECT &&
1211                 v->value_type != COS_VALUE_RESOURCE)
1212                 return_error(gs_error_unregistered); /* Must not happen. */
1213             list = (cos_dict_t *)v->contents.object;
1214             if (list->cos_procs != &cos_dict_procs)
1215                 return_error(gs_error_unregistered); /* Must not happen. */
1216         } else {
1217             list = cos_dict_alloc(pdev, "pdf_add_resource");
1218             if (list == NULL)
1219                 return_error(gs_error_VMerror);
1220             code = cos_dict_put_c_key_object((cos_dict_t *)pcd, key, (cos_object_t *)list);
1221             if (code < 0)
1222                 return code;
1223         }
1224         buf1[0] = '/';
1225         strcpy(buf1 + 1, pres->rname);
1226         return cos_dict_put_string(list, (const byte *)buf1, strlen(buf1),
1227                         (const byte *)buf, strlen(buf));
1228     }
1229     return 0;
1230 }
1231