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