1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
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.
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.
17
/* Bitmap font implementation for pdfwrite */
31
#include "gxchar.h" /* For gs_show_enum */
33
/* ---------------- Private ---------------- */
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. */
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);
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;
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);
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);
70
pdf_char_proc_id(const pdf_char_proc_t *pcp)
72
return pdf_resource_id((const pdf_resource_t *)pcp);
75
/* Assign a code for a char_proc. */
77
assign_char_code(gx_device_pdf * pdev, gs_text_enum_t *pte)
79
pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
80
pdf_font_resource_t *pdfont = pbfs->open_font; /* Type 3 */
82
uint operation = pte->text.operation;
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 ||
89
/* Start a new synthesized font. */
92
code = pdf_font_type3_alloc(pdev, &pdfont, pdf_write_contents_bitmap);
95
pdfont->u.simple.s.type3.bitmap_font = true;
96
if (pbfs->open_font == 0)
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);
107
* We "increment" the font name as a radix-26 "number".
108
* This cannot possibly overflow.
110
for (pc = pdfont->rname; *pc == 'Z'; ++pc)
113
*pc = 'A', pc[1] = 0;
114
pbfs->open_font = pdfont;
115
pbfs->use_open_font = true;
116
pdfont->u.simple.FirstChar = 255;
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);
123
if (pdfont->used[index] & bit) {
124
for (i = 0;i < 256;i++) {
126
bit = 0x01 << (i % 8);
127
if (!(pdfont->used[index] & bit)) {
134
pdfont->used[index] |= bit;
135
if (c > pdfont->u.simple.LastChar)
136
pdfont->u.simple.LastChar = c;
139
unsigned char index, bit;
140
c = ++(pdfont->u.simple.LastChar);
142
bit = 0x01 << (c % 8);
143
pdfont->used[index] |= bit;
145
if (c < pdfont->u.simple.FirstChar)
146
pdfont->u.simple.FirstChar = c;
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;
157
/* Write the contents of a Type 3 bitmap or vector font resource. */
159
pdf_write_contents_bitmap(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
161
stream *s = pdev->strm;
162
const pdf_char_proc_ownership_t *pcpo;
166
if (pdfont->u.simple.s.type3.bitmap_font)
167
diff_id = pdev->text->bitmap_fonts->bitmap_encoding_id;
169
/* See comment in pdf_write_encoding. */
170
diff_id = pdf_obj_ref(pdev);
172
code = pdf_write_encoding_ref(pdev, pdfont, diff_id);
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
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));
187
pdf_record_usage_by_parent(pdev, pdf_char_proc_id(pcpo->char_proc), pdfont->object->id);
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);
200
if (!pdfont->u.simple.s.type3.bitmap_font && diff_id > 0) {
201
code = pdf_write_encoding(pdev, pdfont, diff_id, 0);
208
/* ---------------- Public ---------------- */
211
* Allocate and initialize bookkeeping for bitmap fonts.
214
pdf_bitmap_fonts_alloc(gs_memory_t *mem)
216
pdf_bitmap_fonts_t *pbfs =
217
gs_alloc_struct(mem, pdf_bitmap_fonts_t, &st_pdf_bitmap_fonts,
218
"pdf_bitmap_fonts_alloc");
222
memset(pbfs, 0, sizeof(*pbfs));
223
pbfs->max_embedded_code = -1;
228
* Update text state at the end of a page.
231
pdf_close_text_page(gx_device_pdf *pdev)
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.
242
if (pdev->CompatibilityLevel <= 1.2)
243
pdev->text->bitmap_fonts->use_open_font = false;
247
pdf_charproc_y_offset(pdf_char_proc_t *pcp)
249
return pcp->y_offset;
253
pdf_charproc_x_offset(pdf_char_proc_t *pcp)
255
return pcp->x_offset;
258
/* Attach a CharProc to a font. */
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)
263
pdf_char_proc_ownership_t *pcpo;
264
bool duplicate_char_name = false;
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)
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;
278
pcpo = gs_alloc_struct(pdev->pdf_memory,
279
pdf_char_proc_ownership_t, &st_pdf_char_proc_ownership, "pdf_attach_charproc");
282
return_error(gs_error_VMerror);
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;
292
pcpo->char_name.data = 0;
293
pcpo->char_name.size = 0;
295
pcpo->char_name = *gnstr;
296
pcpo->duplicate_char_name = duplicate_char_name;
301
pdf_free_charproc_ownership(gx_device_pdf * pdev, pdf_resource_t *pres)
303
pdf_char_proc_ownership_t *next, *pcpo = (pdf_char_proc_ownership_t *)pres;
306
next = pcpo->char_next;
307
if(pcpo->char_name.size != 0 && pcpo->char_name.data) {
308
/* This causes PCL some trouble, don't know why yet FIXME-MEMORY
309
gs_free_string(pdev->pdf_memory, (byte *)pcpo->char_name.data, pcpo->char_name.size, "Free CharProc name");*/
310
pcpo->char_name.data = (byte *)0L;
311
pcpo->char_name.size = 0;
313
gs_free_object(pdev->pdf_memory, pcpo, "Free CharProc");
319
/* Begin a CharProc for a synthesized (bitmap) font. */
321
pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
322
int y_offset, int x_offset, gs_id id, pdf_char_proc_t ** ppcp,
323
pdf_stream_position_t * ppos)
325
gs_char char_code = 0;
326
pdf_bitmap_fonts_t *const pbfs = pdev->text->bitmap_fonts;
327
pdf_font_resource_t *font;
328
pdf_resource_t *pres;
329
pdf_char_proc_t *pcp;
331
/* This code added to store PCL bitmap glyphs in type 3 fonts where possible */
332
gs_glyph glyph = GS_NO_GLYPH;
333
gs_const_string *str = NULL;
334
gs_show_enum *show_enum = (gs_show_enum *)pdev->pte;
335
pdf_encoding_element_t *pet = 0;
336
/* Since this is for text searching, its only useful if the character code
337
* lies in an ASCII range, so we only handle some kinds of text layout.
339
int allowed_op = (show_enum->text.operation &
340
(TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR));
342
/* Check to see the current font is a type 3. We can get here if pdfwrite decides
343
* it can't handle a font type, and renders to a bitmap instead. If that's the
344
* case then we can't add the bitmap to the existing font (its not a type 3 font)
345
* and must fall back to holding it in our fallback type 3 font 'collection'.
347
/* Because the bitmaps are stored directly in the cache they already have any
348
* effects caused by non-identity FontMatrix entries applied. So if the type 3
349
* font we created has a non-identity FontMatrix we can't use it and must
350
* go back to collecting the bitmap into our fallback font.
352
if ((show_enum->current_font->FontType == ft_user_defined ||
353
show_enum->current_font->FontType == ft_PCL_user_defined ||
354
show_enum->current_font->FontType == ft_GL2_stick_user_defined ||
355
show_enum->current_font->FontType == ft_GL2_531) && allowed_op &&
356
show_enum->current_font->FontMatrix.xx == 1 && show_enum->current_font->FontMatrix.xy == 0 &&
357
show_enum->current_font->FontMatrix.yx == 0 && show_enum->current_font->FontMatrix.yy == 1) {
358
pdf_char_proc_ownership_t *pcpo;
360
gs_font_base *base = (gs_font_base *)show_enum->current_font;
361
code = pdf_attached_font_resource(pdev, show_enum->current_font, &font, NULL, NULL, NULL, NULL);
364
/* The text processing will have run past the glyph, so we need to 'back up'
365
* by one and get it again in order to get the character code and glyph, and update
366
* the pointer correctly.
369
code = gs_default_next_char_glyph((gs_text_enum_t *)show_enum, (gs_char *)&char_code, &glyph);
373
/* If the returned character code is outside the possible Encoding for
374
* a type 3 font, then set pet to NULL, this means we will fall back to
375
* the 'collection' font, as pet is checked below.
377
if (char_code >= 0 && char_code <= 255) {
378
pet = &font->u.simple.Encoding[char_code];
380
/* Check to see if we *already* have this glyph in this font. If
381
* we do then we can't add it to this font. Setting pet to 0
382
* falls back to the collection method.
384
for (pcpo = font->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
385
if (pcpo->glyph == pet->glyph && pcpo->char_code == char_code) {
395
/* We need a glyph name for the type 3 font's Encoding, if we haven't got one
396
* then we need to give up, something about the font or text is not acceptable
397
* (see various comments above).
399
if (pet && pet->glyph != GS_NO_GLYPH && !(pet->str.size == 7 &&
400
!strncmp((const char *)pet->str.data, ".notdef", 7))) {
401
if (char_code < font->u.simple.FirstChar)
402
font->u.simple.FirstChar = char_code;
403
if ((int)char_code > font->u.simple.LastChar)
404
font->u.simple.LastChar = char_code;
405
base->FontBBox.q.x = max(base->FontBBox.q.x, w);
406
base->FontBBox.q.y = max(base->FontBBox.q.y, y_offset + h);
409
/* This is to work around a weird Acrobat bug. If the Encoding of a type 3
410
* (possibly other types) is simply a standard encoding (eg WinAnsiEncoding)
411
* then Acrobat 4 & 8 just ignore the glyphs altogether. This forces us to write
412
* all the used glyphs as /Differencess, and that makes it work <sigh>
414
pet->is_difference = 1;
415
font->Widths[char_code] = psdf_round(pdev->char_width.x, 100, 10); /* See
416
pdf_write_Widths about rounding. We need to provide
417
a compatible data for Tj. */
419
char_code = assign_char_code(pdev, pdev->pte);
420
font = pbfs->open_font; /* Type 3 */
423
char_code = assign_char_code(pdev, pdev->pte);
424
font = pbfs->open_font; /* Type 3 */
427
code = pdf_begin_resource(pdev, resourceCharProc, id, &pres);
430
pcp = (pdf_char_proc_t *) pres;
431
code = pdf_attach_charproc(pdev, font, pcp, glyph, char_code, str);
434
pres->object->written = true;
436
stream *s = pdev->strm;
439
* The resource file is positionable, so rather than use an
440
* object reference for the length, we'll go back and fill it in
441
* at the end of the definition. Take 1M as the longest
442
* definition we can handle. (This used to be 10K, but there was
443
* a real file that exceeded this limit.)
445
stream_puts(s, "<</Length >>stream\n");
446
ppos->start_pos = stell(s);
448
code = pdf_begin_encrypt(pdev, &pdev->strm, pres->object->id);
451
pcp->y_offset = y_offset;
452
pcp->x_offset = x_offset;
453
font->u.simple.s.type3.FontBBox.q.x =
454
max(font->u.simple.s.type3.FontBBox.q.x, w);
455
font->u.simple.s.type3.FontBBox.q.y =
456
max(font->u.simple.s.type3.FontBBox.q.y, y_offset + h);
457
font->u.simple.s.type3.max_y_offset =
458
max(font->u.simple.s.type3.max_y_offset, h + (h >> 2));
463
/* End a CharProc. */
465
pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos)
468
gs_offset_t start_pos, end_pos, length;
470
pdf_end_encrypt(pdev);
472
start_pos = ppos->start_pos;
474
length = end_pos - start_pos;
476
return_error(gs_error_limitcheck);
477
sseek(s, start_pos - 15);
478
pprintd1(s, "%d", length);
481
stream_puts(s, "\n");
482
stream_puts(s, "endstream\n");
483
pdf_end_separate(pdev, resourceCharProc);
487
/* Mark glyph names for garbager. */
489
pdf_mark_glyph_names(const pdf_font_resource_t *pdfont, const gs_memory_t *memory)
491
if (pdfont->mark_glyph == NULL) {
492
/* Synthesised bitmap fonts pass here. */
495
if (pdfont->u.simple.Encoding != NULL) {
498
for (i = 0; i < 256; i++)
499
if (pdfont->u.simple.Encoding[i].glyph != GS_NO_GLYPH)
500
pdfont->mark_glyph(memory, pdfont->u.simple.Encoding[i].glyph, pdfont->mark_glyph_data);
502
if (pdfont->FontType == ft_user_defined ||
503
pdfont->FontType == ft_PCL_user_defined ||
504
pdfont->FontType == ft_GL2_stick_user_defined ||
505
pdfont->FontType == ft_GL2_531) {
506
const pdf_char_proc_ownership_t *pcpo = pdfont->u.simple.s.type3.char_procs;
508
for (; pcpo != NULL; pcpo = pcpo->font_next)
509
pdfont->mark_glyph(memory, pcpo->glyph, pdfont->mark_glyph_data);
513
/* Put out a reference to an image as a character in a synthesized font. */
515
pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
516
const gs_matrix * pimat)
518
/* We need to choose a font, which use the charproc.
519
In most cases it is the last font, which the charproc is attached to.
520
If the charproc is substituted, it causes a font change. */
521
const pdf_char_proc_ownership_t * pcpo = pcp->owner_fonts;
522
pdf_font_resource_t *pdfont = pcpo->font;
523
byte ch = pcpo->char_code;
524
pdf_text_state_values_t values;
526
values.character_spacing = 0;
527
values.pdfont = pdfont;
529
values.matrix = *pimat;
530
values.render_mode = 0;
531
values.word_spacing = 0;
532
pdf_set_text_state_values(pdev, &values);
533
pdf_append_chars(pdev, &ch, 1, pdfont->Widths[ch] * pimat->xx, 0.0, false);
538
* Write the Encoding for bitmap fonts, if needed.
541
pdf_write_bitmap_fonts_Encoding(gx_device_pdf *pdev)
543
pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
545
if (pbfs->bitmap_encoding_id) {
549
pdf_open_separate(pdev, pbfs->bitmap_encoding_id, resourceEncoding);
552
* Even though the PDF reference documentation says that a
553
* BaseEncoding key is required unless the encoding is
554
* "based on the base font's encoding" (and there is no base
555
* font in this case), Acrobat 2.1 gives an error if the
556
* BaseEncoding key is present.
558
stream_puts(s, "<</Type/Encoding/Differences[0");
559
for (i = 0; i <= pbfs->max_embedded_code; ++i) {
561
stream_puts(s, "\n");
562
pprintd1(s, "/a%d", i);
564
stream_puts(s, "\n] >>\n");
565
pdf_end_separate(pdev, resourceEncoding);
566
pbfs->bitmap_encoding_id = 0;
572
* Start charproc accumulation for a Type 3 font.
575
pdf_start_charproc_accum(gx_device_pdf *pdev)
577
pdf_char_proc_t *pcp;
578
pdf_resource_t *pres;
579
int code = pdf_enter_substream(pdev, resourceCharProc, gs_next_ids(pdev->memory, 1),
580
&pres, false, pdev->CompressFonts);
584
pcp = (pdf_char_proc_t *)pres;
585
pcp->owner_fonts = NULL;
590
* Install charproc accumulator for a Type 3 font.
593
pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, double *pw, int narg,
594
gs_text_cache_control_t control, gs_char ch, bool scale_100)
596
pdf_font_resource_t *pdfont;
597
pdf_resource_t *pres = pdev->accumulating_substream_resource;
598
pdf_char_proc_t *pcp;
601
code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
604
pcp = (pdf_char_proc_t *)pres;
605
pcp->owner_fonts = NULL;
606
pcp->real_width.x = pw[font->WMode && narg > 6 ? 6 : 0];
607
pcp->real_width.y = pw[font->WMode && narg > 6 ? 7 : 1];
608
pcp->v.x = (narg > 8 ? pw[8] : 0);
609
pcp->v.y = (narg > 8 ? pw[9] : 0);
610
if (control == TEXT_SET_CHAR_WIDTH) {
611
/* PLRM 5.7.1 "BuildGlyph" reads : "Normally, it is unnecessary and
612
undesirable to initialize the current color parameter, because show
613
is defined to paint glyphs with the current color."
614
However comparefiles/Bug687044.ps doesn't follow that. */
615
pdev->skip_colors = false;
616
pprintg1(pdev->strm, "%g 0 d0\n", (float)pw[0]);
617
/* The colour change described above can't affect PCL fonts and we need
618
* all glyphs to be noted as cached in order for the bitmap font cache
619
* probing to work properly.
621
if (font->FontType == ft_PCL_user_defined || font->FontType == ft_GL2_stick_user_defined
622
|| font->FontType == ft_GL2_531)
623
pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
626
pdev->skip_colors = true;
637
pprintg6(pdev->strm, "%g %g %g %g %g %g d1\n",
638
(float)pw[0], (float)0.0, (float)pw[2],
639
(float)pw[3], (float)pw[4], (float)pw[5]);
640
pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
642
/* See comments in pdf_text_process regarding type 3 CharProc accumulation
643
* Initially this matrix was emitted there, at the start of the accumulator
644
* but if we do that then GS incorrectly applied the matrix to the 'd1'
645
* operator. We write the scale matrix here because this is *after* the
646
* 'd1' has been emitted above, and so does not affect it.
649
code = stream_puts(pdev->strm, "0.01 0 0 0.01 0 0 cm\n");
657
* Open a stream object in the temporary file.
661
pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype,
662
gs_id id, pdf_resource_t **ppres, bool reserve_object_id, int options)
665
pdf_resource_t *pres;
666
stream *s, *save_strm = pdev->strm;
667
pdf_data_writer_t writer;
668
static const pdf_filter_names_t fnames = {
672
pdev->streams.save_strm = pdev->strm;
674
if (rtype > NUM_RESOURCE_TYPES)
675
rtype = resourceOther;
676
code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, id),
677
pdf_resource_type_structs[rtype], &pres, reserve_object_id ? 0 : -1);
680
cos_become(pres->object, cos_type_stream);
681
s = cos_write_stream_alloc((cos_stream_t *)pres->object, pdev, "pdf_enter_substream");
683
return_error(gs_error_VMerror);
685
code = pdf_append_data_stream_filters(pdev, &writer,
686
options | DATA_STREAM_NOLENGTH, pres->object->id);
688
pdev->strm = save_strm;
691
code = pdf_put_filters((cos_dict_t *)pres->object, pdev, writer.binary.strm, &fnames);
693
pdev->strm = save_strm;
696
pdev->strm = writer.binary.strm;
702
* Close a stream object in the temporary file.
705
pdf_close_aside(gx_device_pdf *pdev)
707
/* We should call pdf_end_data here, but we don't want to put pdf_data_writer_t
708
into pdf_substream_save stack to simplify garbager descriptors.
709
Use a lower level functions instead that. */
710
stream *s = pdev->strm;
711
cos_stream_t *pcs = cos_stream_from_pipeline(s);
712
int status = s_close_filters(&s, NULL);
714
pdev->strm = pdev->streams.save_strm;
716
return(gs_note_error(gs_error_ioerror));
718
pcs->is_open = false;
723
* Enter the substream accumulation mode.
726
pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype,
727
gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress)
729
int sbstack_ptr = pdev->sbstack_depth;
730
pdf_resource_t *pres;
731
stream *save_strm = pdev->strm;
734
if (pdev->sbstack_depth >= pdev->sbstack_size)
735
return_error(gs_error_unregistered); /* Must not happen. */
736
if (pdev->sbstack[sbstack_ptr].text_state == 0) {
737
pdev->sbstack[sbstack_ptr].text_state = pdf_text_state_alloc(pdev->pdf_memory);
738
if (pdev->sbstack[sbstack_ptr].text_state == 0)
739
return_error(gs_error_VMerror);
741
code = pdf_open_aside(pdev, rtype, id, &pres, reserve_object_id,
742
(compress ? DATA_STREAM_COMPRESS : 0));
745
code = pdf_save_viewer_state(pdev, NULL);
747
pdev->strm = save_strm;
750
pdev->sbstack[sbstack_ptr].context = pdev->context;
751
pdf_text_state_copy(pdev->sbstack[sbstack_ptr].text_state, pdev->text->text_state);
752
pdf_set_text_state_default(pdev->text->text_state);
753
pdev->sbstack[sbstack_ptr].clip_path = pdev->clip_path;
755
pdev->sbstack[sbstack_ptr].clip_path_id = pdev->clip_path_id;
756
pdev->clip_path_id = pdev->no_clip_path_id;
757
pdev->sbstack[sbstack_ptr].vgstack_bottom = pdev->vgstack_bottom;
758
pdev->vgstack_bottom = pdev->vgstack_depth;
759
pdev->sbstack[sbstack_ptr].strm = save_strm;
760
pdev->sbstack[sbstack_ptr].procsets = pdev->procsets;
761
pdev->sbstack[sbstack_ptr].substream_Resources = pdev->substream_Resources;
762
pdev->sbstack[sbstack_ptr].skip_colors = pdev->skip_colors;
763
pdev->sbstack[sbstack_ptr].font3 = pdev->font3;
764
pdev->sbstack[sbstack_ptr].accumulating_substream_resource = pdev->accumulating_substream_resource;
765
pdev->sbstack[sbstack_ptr].charproc_just_accumulated = pdev->charproc_just_accumulated;
766
pdev->sbstack[sbstack_ptr].accumulating_a_global_object = pdev->accumulating_a_global_object;
767
pdev->sbstack[sbstack_ptr].pres_soft_mask_dict = pdev->pres_soft_mask_dict;
768
pdev->sbstack[sbstack_ptr].objname = pdev->objname;
769
pdev->sbstack[sbstack_ptr].last_charpath_op = pdev->last_charpath_op;
770
pdev->skip_colors = false;
771
pdev->charproc_just_accumulated = false;
772
pdev->pres_soft_mask_dict = NULL;
773
pdev->objname.data = NULL;
774
pdev->objname.size = 0;
775
/* Do not reset pdev->accumulating_a_global_object - it inherits. */
776
pdev->sbstack_depth++;
779
pdev->context = PDF_IN_STREAM;
780
pdev->accumulating_substream_resource = pres;
781
pdev->last_charpath_op = 0;
782
/* Do not alter type3charpath, inherit the current value. We need to know if */
783
/* we are inside a charpath operation, and only reset this when the charpath */
785
pdf_reset_graphics(pdev);
791
* Exit the substream accumulation mode.
794
pdf_exit_substream(gx_device_pdf *pdev)
799
if (pdev->sbstack_depth <= 0)
800
return_error(gs_error_unregistered); /* Must not happen. */
801
code = pdf_open_contents(pdev, PDF_IN_STREAM);
802
sbstack_ptr = pdev->sbstack_depth - 1;
803
while (pdev->vgstack_depth > pdev->vgstack_bottom) {
804
code1 = pdf_restore_viewer_state(pdev, pdev->strm);
808
if (pdev->clip_path != 0)
809
gx_path_free(pdev->clip_path, "pdf_end_charproc_accum");
810
code1 = pdf_close_aside(pdev);
811
if (code1 < 0 && code >= 0)
813
pdev->context = pdev->sbstack[sbstack_ptr].context;
814
pdf_text_state_copy(pdev->text->text_state, pdev->sbstack[sbstack_ptr].text_state);
815
pdev->clip_path = pdev->sbstack[sbstack_ptr].clip_path;
816
pdev->sbstack[sbstack_ptr].clip_path = 0;
817
pdev->clip_path_id = pdev->sbstack[sbstack_ptr].clip_path_id;
818
pdev->vgstack_bottom = pdev->sbstack[sbstack_ptr].vgstack_bottom;
819
pdev->strm = pdev->sbstack[sbstack_ptr].strm;
820
pdev->sbstack[sbstack_ptr].strm = 0;
821
pdev->procsets = pdev->sbstack[sbstack_ptr].procsets;
822
pdev->substream_Resources = pdev->sbstack[sbstack_ptr].substream_Resources;
823
pdev->sbstack[sbstack_ptr].substream_Resources = 0;
824
pdev->skip_colors = pdev->sbstack[sbstack_ptr].skip_colors;
825
pdev->font3 = pdev->sbstack[sbstack_ptr].font3;
826
pdev->sbstack[sbstack_ptr].font3 = 0;
827
pdev->accumulating_substream_resource = pdev->sbstack[sbstack_ptr].accumulating_substream_resource;
828
pdev->sbstack[sbstack_ptr].accumulating_substream_resource = 0;
829
pdev->charproc_just_accumulated = pdev->sbstack[sbstack_ptr].charproc_just_accumulated;
830
pdev->accumulating_a_global_object = pdev->sbstack[sbstack_ptr].accumulating_a_global_object;
831
pdev->pres_soft_mask_dict = pdev->sbstack[sbstack_ptr].pres_soft_mask_dict;
832
pdev->objname = pdev->sbstack[sbstack_ptr].objname;
833
pdev->last_charpath_op = pdev->sbstack[sbstack_ptr].last_charpath_op;
834
pdev->sbstack_depth = sbstack_ptr;
835
code1 = pdf_restore_viewer_state(pdev, NULL);
836
if (code1 < 0 && code >= 0)
842
pdf_is_same_charproc_attrs1(gx_device_pdf *pdev, pdf_char_proc_t *pcp0, pdf_char_proc_t *pcp1)
844
if (pcp0->real_width.x != pcp1->real_width.x)
846
if (pcp0->real_width.y != pcp1->real_width.y)
848
if (pcp0->v.x != pcp1->v.x)
850
if (pcp0->v.y != pcp1->v.y)
855
typedef struct charproc_compatibility_data_s {
856
const pdf_char_glyph_pairs_t *cgp;
857
pdf_font_resource_t *pdfont;
861
} charproc_compatibility_data_t;
864
is_char_code_used(pdf_font_resource_t *pdfont, gs_char char_code)
866
pdf_char_proc_ownership_t *pcpo;
868
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
869
if (pcpo->char_code == char_code) {
877
pdf_is_charproc_compatible(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
879
charproc_compatibility_data_t *data = (charproc_compatibility_data_t *)pdev->find_resource_param;
880
pdf_char_proc_t *pcp0 = (pdf_char_proc_t *)pres0;
881
pdf_char_proc_t *pcp1 = (pdf_char_proc_t *)pres1;
882
pdf_font_resource_t *pdfont = data->pdfont;
883
pdf_char_proc_ownership_t *pcpo;
884
pdf_font_cache_elem_t **e;
885
bool can_add_to_current_font = false, computed_can_add_to_current_font = false;
887
/* Does it have same attributes ? */
888
if (!pdf_is_same_charproc_attrs1(pdev, pcp0, pcp1))
890
/* Is it from same font ? */
891
for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
892
if (pdfont == pcpo->font) {
893
/* Check for encoding conflict. */
894
if (pcpo->char_code == data->char_code && pcpo->glyph == data->glyph)
895
return 1; /* Same char code. */
896
if (!computed_can_add_to_current_font) {
897
can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
898
computed_can_add_to_current_font = true;
900
if (can_add_to_current_font)
901
return 1; /* No conflict. */
904
/* Look for another font with same encoding,
905
because we want to reduce the number of new fonts.
906
We also restrict with ones attached to same PS font,
907
otherwise it creates too mixed fonts and disturbs word breaks.
909
e = pdf_locate_font_cache_elem(pdev, data->font);
911
for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
912
if (pcpo->char_code != data->char_code || pcpo->glyph != data->glyph)
913
continue; /* Need same Encoding to generate a proper ToUnicode. */
914
if (pdfont->u.simple.s.type3.bitmap_font != pcpo->font->u.simple.s.type3.bitmap_font)
916
if (gs_matrix_compare(&pdfont->u.simple.s.type3.FontMatrix, &pcpo->font->u.simple.s.type3.FontMatrix))
918
if (data->cgp != NULL) {
919
if (!pdf_check_encoding_compatibility(pcpo->font, data->cgp->s, data->cgp->num_all_chars))
922
if ((*e)->pdfont != pcpo->font)
924
data->pdfont = pcpo->font; /* Switch to the other font. */
928
/* Check whether it can be added into the current font. */
929
if (!computed_can_add_to_current_font)
930
can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
931
if (!can_add_to_current_font) {
932
/* Can't substitute due to encoding conflict. */
935
/* The current font will share it with another font. */
940
pdf_find_same_charproc_aux(gx_device_pdf *pdev,
941
pdf_font_resource_t **ppdfont, pdf_char_proc_t **ppcp)
943
pdf_char_proc_ownership_t *pcpo;
946
/* fixme: this passes parameters to pdf_is_charproc_compatible
947
through special gx_device_pdf field pdev->find_resource_param
948
due to prototype limitation of pdf_find_same_resource.
949
It would be better to change the client data argument type in there to void. */
950
for (pcpo = (*ppdfont)->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
951
pdf_char_proc_t *pcp = pcpo->char_proc;
953
if (*ppcp != pcp && pdf_is_same_charproc_attrs1(pdev, *ppcp, pcp)) {
954
cos_object_t *pco0 = pcp->object;
955
cos_object_t *pco1 = (*ppcp)->object;
957
code = pco0->cos_procs->equal(pco0, pco1, pdev);
967
return pdf_find_same_resource(pdev, resourceCharProc, (pdf_resource_t **)ppcp, pdf_is_charproc_compatible);
970
pdf_find_same_charproc(gx_device_pdf *pdev,
971
pdf_font_resource_t **ppdfont, const pdf_char_glyph_pairs_t *cgp,
972
pdf_char_proc_t **ppcp, gs_glyph glyph, gs_char char_code,
975
charproc_compatibility_data_t data;
979
data.pdfont = *ppdfont;
980
data.char_code = char_code;
983
pdev->find_resource_param = &data;
984
code = pdf_find_same_charproc_aux(pdev, ppdfont, ppcp);
985
pdev->find_resource_param = NULL;
986
*ppdfont = data.pdfont;
991
pdf_is_charproc_defined(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, gs_char ch)
993
pdf_char_proc_ownership_t *pcpo;
995
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
996
if (pcpo->char_code == ch)
1003
complete_adding_char(gx_device_pdf *pdev, gs_font *font,
1004
gs_glyph glyph, gs_char ch, pdf_char_proc_t *pcp,
1005
const gs_const_string *gnstr)
1007
pdf_font_resource_t *pdfont;
1008
double *real_widths;
1010
int char_cache_size, width_cache_size;
1011
pdf_encoding_element_t *pet;
1014
code = pdf_attached_font_resource(pdev, font, &pdfont,
1015
&glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1018
code = pdf_attach_charproc(pdev, pdfont, pcp, glyph, ch, gnstr);
1021
if (ch >= char_cache_size || ch >= width_cache_size)
1022
return_error(gs_error_unregistered); /* Must not happen. */
1023
pet = &pdfont->u.simple.Encoding[ch];
1024
pdfont->Widths[ch] = pcp->real_width.x;
1025
real_widths[ch * 2 ] = pcp->real_width.x;
1026
real_widths[ch * 2 + 1] = pcp->real_width.y;
1027
glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1028
pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
1029
if (pdfont->u.simple.v != NULL && font->WMode) {
1030
pdfont->u.simple.v[ch].x = pcp->v.x;
1031
pdfont->u.simple.v[ch].y = pcp->v.x;
1035
pet->is_difference = true;
1036
if (pdfont->u.simple.LastChar < (int)ch)
1037
pdfont->u.simple.LastChar = (int)ch;
1038
if (pdfont->u.simple.FirstChar > (int)ch)
1039
pdfont->u.simple.FirstChar = (int)ch;
1044
pdf_char_widths_from_charprocs(gx_device_pdf *pdev, gs_font *font)
1046
pdf_font_resource_t *pdfont;
1047
double *real_widths;
1049
int char_cache_size, width_cache_size;
1050
pdf_char_proc_ownership_t *pcpo;
1053
code = pdf_attached_font_resource(pdev, font, &pdfont,
1054
&glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1057
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
1058
pdf_char_proc_t *pcp = pcpo->char_proc;
1059
gs_char ch = pcpo->char_code;
1061
real_widths[ch * 2 ] = pcp->real_width.x;
1062
real_widths[ch * 2 + 1] = pcp->real_width.y;
1063
glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1069
* Complete charproc accumulation for a Type 3 font.
1072
pdf_end_charproc_accum(gx_device_pdf *pdev, gs_font *font, const pdf_char_glyph_pairs_t *cgp,
1073
gs_glyph glyph, gs_char output_char_code, const gs_const_string *gnstr)
1076
pdf_resource_t *pres = (pdf_resource_t *)pdev->accumulating_substream_resource;
1077
/* We could use pdfont->u.simple.s.type3.char_procs insted the thing above
1078
unless the font is defined recursively.
1079
But we don't want such assumption. */
1080
pdf_char_proc_t *pcp = (pdf_char_proc_t *)pres;
1081
pdf_font_resource_t *pdfont;
1082
gs_char ch = output_char_code;
1083
bool checking_glyph_variation = false;
1085
if (ch == GS_NO_CHAR)
1086
return_error(gs_error_unregistered); /* Must not happen. */
1088
return_error(gs_error_unregistered); /* Must not happen. */
1089
code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
1092
if (pdfont != (pdf_font_resource_t *)pdev->font3)
1093
return_error(gs_error_unregistered); /* Must not happen. */
1094
code = pdf_exit_substream(pdev);
1097
if (!(pdfont->used[ch >> 3] & (0x80 >> (ch & 7))) ||
1098
!(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))) {
1099
/* First appearence or not cached - check for duplicates. */
1100
pdf_font_resource_t *pdfont1 = pdfont;
1102
checking_glyph_variation = true;
1103
/* CAUTION : a possible font change. */
1104
code = pdf_find_same_charproc(pdev, &pdfont, cgp, &pcp, glyph, ch, font);
1108
code = pdf_cancel_resource(pdev, pres, resourceCharProc);
1111
pdf_forget_resource(pdev, pres, resourceCharProc);
1112
if (pdfont1 != pdfont) {
1113
code = pdf_attach_font_resource(pdev, font, pdfont);
1116
code = pdf_char_widths_from_charprocs(pdev, font);
1120
pdev->charproc_just_accumulated = true;
1121
return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
1123
if (pdf_is_charproc_defined(pdev, pdfont, ch)) {
1124
/* Encoding conflict after a font change. */
1125
gs_font *base_font = font, *below;
1127
while ((below = base_font->base) != base_font &&
1128
base_font->procs.same_font(base_font, below, FONT_SAME_OUTLINES))
1130
code = pdf_make_font3_resource(pdev, base_font, &pdfont);
1133
code = pdf_attach_font_resource(pdev, font, pdfont);
1138
pdf_reserve_object_id(pdev, pres, 0);
1139
if (checking_glyph_variation)
1140
pdev->charproc_just_accumulated = true;
1141
return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
1144
/* Add procsets to substream Resources. */
1146
pdf_add_procsets(cos_dict_t *pcd, pdf_procset_t procsets)
1148
char str[5 + 7 + 7 + 7 + 5 + 2];
1151
strcpy(str, "[/PDF");
1152
if (procsets & ImageB)
1153
strcat(str, "/ImageB");
1154
if (procsets & ImageC)
1155
strcat(str, "/ImageC");
1156
if (procsets & ImageI)
1157
strcat(str, "/ImageI");
1158
if (procsets & Text)
1159
strcat(str, "/Text");
1161
cos_string_value(&v, (byte *)str, strlen(str));
1162
return cos_dict_put_c_key(pcd, "/ProcSet", &v);
1165
/* Add a resource to substream Resources. */
1167
pdf_add_resource(gx_device_pdf *pdev, cos_dict_t *pcd, const char *key, pdf_resource_t *pres)
1170
const cos_value_t *v = cos_dict_find(pcd, (const byte *)key, strlen(key));
1173
char buf[10 + (sizeof(long) * 8 / 3 + 1)], buf1[sizeof(pres->rname) + 1];
1175
if (pdev->ForOPDFRead && !pres->global && pdev->accumulating_a_global_object) {
1176
pres->global = true;
1177
code = cos_dict_put_c_key_bool((cos_dict_t *)pres->object, "/.Global", true);
1181
sprintf(buf, "%ld 0 R\n", pres->object->id);
1183
if (v->value_type != COS_VALUE_OBJECT &&
1184
v->value_type != COS_VALUE_RESOURCE)
1185
return_error(gs_error_unregistered); /* Must not happen. */
1186
list = (cos_dict_t *)v->contents.object;
1187
if (list->cos_procs != &cos_dict_procs)
1188
return_error(gs_error_unregistered); /* Must not happen. */
1190
list = cos_dict_alloc(pdev, "pdf_add_resource");
1192
return_error(gs_error_VMerror);
1193
code = cos_dict_put_c_key_object((cos_dict_t *)pcd, key, (cos_object_t *)list);
1198
strcpy(buf1 + 1, pres->rname);
1199
return cos_dict_put_string(list, (const byte *)buf1, strlen(buf1),
1200
(const byte *)buf, strlen(buf));