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