1
/* Copyright (C) 2001-2006 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, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gdevpdti.c 8611 2008-03-27 08:37:58Z ken $ */
15
/* Bitmap font implementation for pdfwrite */
31
/* ---------------- Private ---------------- */
33
/* Define the structure for a CharProc pseudo-resource. */
34
/*typedef struct pdf_char_proc_s pdf_char_proc_t;*/ /* gdevpdfx.h */
35
struct pdf_char_proc_s {
36
pdf_resource_common(pdf_char_proc_t);
37
pdf_char_proc_ownership_t *owner_fonts; /* fonts using this charproc. */
38
int y_offset; /* of character (0,0) */
39
gs_point real_width; /* Not used with synthesised bitmap fonts. */
40
gs_point v; /* Not used with synthesised bitmap fonts. */
43
/* The descriptor is public for pdf_resource_type_structs. */
44
gs_public_st_suffix_add1(st_pdf_char_proc, pdf_char_proc_t,
45
"pdf_char_proc_t", pdf_char_proc_enum_ptrs, pdf_char_proc_reloc_ptrs,
46
st_pdf_resource, owner_fonts);
48
struct pdf_char_proc_ownership_s {
49
pdf_char_proc_t *char_proc;
50
pdf_char_proc_ownership_t *font_next; /* next char_proc for same font */
51
pdf_char_proc_ownership_t *char_next; /* next char_proc for same charproc */
52
pdf_font_resource_t *font;
53
gs_char char_code; /* Character code in PDF font. */
54
gs_glyph glyph; /* Glyph id in Postscript font. */
55
gs_const_string char_name;
56
bool duplicate_char_name;
58
gs_private_st_strings1_ptrs4(st_pdf_char_proc_ownership, pdf_char_proc_ownership_t,
59
"pdf_char_proc_ownership_t", pdf_char_proc_ownership_enum_ptrs,
60
pdf_char_proc_ownership_reloc_ptrs, char_name, char_proc, char_next, font_next, font);
62
/* Define the state structure for tracking bitmap fonts. */
63
/*typedef struct pdf_bitmap_fonts_s pdf_bitmap_fonts_t;*/
64
struct pdf_bitmap_fonts_s {
65
pdf_font_resource_t *open_font; /* current Type 3 synthesized font */
66
bool use_open_font; /* if false, start new open_font */
67
long bitmap_encoding_id;
68
int max_embedded_code; /* max Type 3 code used */
70
gs_private_st_ptrs1(st_pdf_bitmap_fonts, pdf_bitmap_fonts_t,
71
"pdf_bitmap_fonts_t", pdf_bitmap_fonts_enum_ptrs,
72
pdf_bitmap_fonts_reloc_ptrs, open_font);
75
pdf_char_proc_id(const pdf_char_proc_t *pcp)
77
return pdf_resource_id((const pdf_resource_t *)pcp);
80
/* Assign a code for a char_proc. */
82
assign_char_code(gx_device_pdf * pdev, gs_text_enum_t *pte)
84
pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
85
pdf_font_resource_t *pdfont = pbfs->open_font; /* Type 3 */
88
if (pbfs->bitmap_encoding_id == 0)
89
pbfs->bitmap_encoding_id = pdf_obj_ref(pdev);
90
if (pdfont == 0 || pdfont->u.simple.LastChar == 255 ||
93
/* Start a new synthesized font. */
96
code = pdf_font_type3_alloc(pdev, &pdfont, pdf_write_contents_bitmap);
99
pdfont->u.simple.s.type3.bitmap_font = true;
100
if (pbfs->open_font == 0)
101
pdfont->rname[0] = 0;
103
strcpy(pdfont->rname, pbfs->open_font->rname);
104
pdfont->u.simple.s.type3.FontBBox.p.x = 0;
105
pdfont->u.simple.s.type3.FontBBox.p.y = 0;
106
pdfont->u.simple.s.type3.FontBBox.q.x = 1000;
107
pdfont->u.simple.s.type3.FontBBox.q.y = 1000;
108
pdfont->mark_glyph = NULL;
109
gs_make_identity(&pdfont->u.simple.s.type3.FontMatrix);
111
* We "increment" the font name as a radix-26 "number".
112
* This cannot possibly overflow.
114
for (pc = pdfont->rname; *pc == 'Z'; ++pc)
117
*pc = 'A', pc[1] = 0;
118
pbfs->open_font = pdfont;
119
pbfs->use_open_font = true;
120
pdfont->u.simple.FirstChar = 0;
122
c = ++(pdfont->u.simple.LastChar);
123
pdfont->Widths[c] = psdf_round(pdev->char_width.x, 100, 10); /* See
124
pdf_write_Widths about rounding. We need to provide
125
a compatible data for Tj. */
126
if (c > pbfs->max_embedded_code)
127
pbfs->max_embedded_code = c;
132
/* Write the contents of a Type 3 bitmap or vector font resource. */
134
pdf_write_contents_bitmap(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
136
stream *s = pdev->strm;
137
const pdf_char_proc_ownership_t *pcpo;
141
if (pdfont->u.simple.s.type3.bitmap_font)
142
diff_id = pdev->text->bitmap_fonts->bitmap_encoding_id;
144
/* See comment in pdf_write_encoding. */
145
diff_id = pdf_obj_ref(pdev);
147
code = pdf_write_encoding_ref(pdev, pdfont, diff_id);
150
stream_puts(s, "/CharProcs <<");
151
/* Write real characters. */
152
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo;
153
pcpo = pcpo->char_next
155
if (pdfont->u.simple.s.type3.bitmap_font)
156
pprintld2(s, "/a%ld %ld 0 R\n", (long)pcpo->char_code,
157
pdf_char_proc_id(pcpo->char_proc));
158
else if (!pcpo-> duplicate_char_name) {
159
pdf_put_name(pdev, pcpo->char_name.data, pcpo->char_name.size);
160
pprintld1(s, " %ld 0 R\n", pdf_char_proc_id(pcpo->char_proc));
163
stream_puts(s, ">>");
164
pprintg6(s, "/FontMatrix[%g %g %g %g %g %g]",
165
(float)pdfont->u.simple.s.type3.FontMatrix.xx,
166
(float)pdfont->u.simple.s.type3.FontMatrix.xy,
167
(float)pdfont->u.simple.s.type3.FontMatrix.yx,
168
(float)pdfont->u.simple.s.type3.FontMatrix.yy,
169
(float)pdfont->u.simple.s.type3.FontMatrix.tx,
170
(float)pdfont->u.simple.s.type3.FontMatrix.ty);
171
code = pdf_finish_write_contents_type3(pdev, pdfont);
174
s = pdev->strm; /* pdf_finish_write_contents_type3 changes pdev->strm . */
175
if (!pdfont->u.simple.s.type3.bitmap_font && diff_id > 0) {
176
code = pdf_write_encoding(pdev, pdfont, diff_id, 0);
183
/* ---------------- Public ---------------- */
186
* Allocate and initialize bookkeeping for bitmap fonts.
189
pdf_bitmap_fonts_alloc(gs_memory_t *mem)
191
pdf_bitmap_fonts_t *pbfs =
192
gs_alloc_struct(mem, pdf_bitmap_fonts_t, &st_pdf_bitmap_fonts,
193
"pdf_bitmap_fonts_alloc");
197
memset(pbfs, 0, sizeof(*pbfs));
198
pbfs->max_embedded_code = -1;
203
* Update text state at the end of a page.
206
pdf_close_text_page(gx_device_pdf *pdev)
209
* When Acrobat Reader 3 prints a file containing a Type 3 font with a
210
* non-standard Encoding, it apparently only emits the subset of the
211
* font actually used on the page. Thus, if the "Download Fonts Once"
212
* option is selected, characters not used on the page where the font
213
* first appears will not be defined, and hence will print as blank if
214
* used on subsequent pages. Thus, we can't allow a Type 3 font to
215
* add additional characters on subsequent pages.
217
if (pdev->CompatibilityLevel <= 1.2)
218
pdev->text->bitmap_fonts->use_open_font = false;
221
/* Return the Y offset for a bitmap character image. */
223
pdf_char_image_y_offset(const gx_device_pdf *pdev, int x, int y, int h)
225
const pdf_text_data_t *const ptd = pdev->text;
229
pdf_text_position(pdev, &pt);
232
max_off = (ptd->bitmap_fonts->open_font == 0 ? 0 :
233
ptd->bitmap_fonts->open_font->u.simple.s.type3.max_y_offset);
234
off = (y + h) - (int)(pt.y + 0.5);
235
if (off < -max_off || off > max_off)
240
/* Attach a CharProc to a font. */
242
pdf_attach_charproc(gx_device_pdf * pdev, pdf_font_resource_t *pdfont, pdf_char_proc_t *pcp,
243
gs_glyph glyph, gs_char char_code, const gs_const_string *gnstr)
245
pdf_char_proc_ownership_t *pcpo;
246
bool duplicate_char_name = false;
248
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
249
if (pcpo->glyph == glyph && pcpo->char_code == char_code)
252
if (!pdfont->u.simple.s.type3.bitmap_font) {
253
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
254
if (!bytes_compare(pcpo->char_name.data, pcpo->char_name.size, gnstr->data, gnstr->size)) {
255
duplicate_char_name = true;
260
pcpo = gs_alloc_struct(pdev->pdf_memory,
261
pdf_char_proc_ownership_t, &st_pdf_char_proc_ownership, "pdf_attach_charproc");
264
return_error(gs_error_VMerror);
266
pcpo->char_next = pdfont->u.simple.s.type3.char_procs;
267
pdfont->u.simple.s.type3.char_procs = pcpo;
268
pcpo->char_proc = pcp;
269
pcpo->font_next = pcp->owner_fonts;
270
pcp->owner_fonts = pcpo;
271
pcpo->char_code = char_code;
274
pcpo->char_name.data = 0;
275
pcpo->char_name.size = 0;
277
pcpo->char_name = *gnstr;
278
pcpo->duplicate_char_name = duplicate_char_name;
282
/* Begin a CharProc for a synthesized (bitmap) font. */
284
pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
285
int y_offset, gs_id id, pdf_char_proc_t ** ppcp,
286
pdf_stream_position_t * ppos)
288
int char_code = assign_char_code(pdev, pdev->pte);
289
pdf_bitmap_fonts_t *const pbfs = pdev->text->bitmap_fonts;
290
pdf_font_resource_t *font = pbfs->open_font; /* Type 3 */
291
pdf_resource_t *pres;
292
pdf_char_proc_t *pcp;
293
int code = pdf_begin_resource(pdev, resourceCharProc, id, &pres);
297
pcp = (pdf_char_proc_t *) pres;
298
code = pdf_attach_charproc(pdev, font, pcp, GS_NO_GLYPH, char_code, NULL);
301
pres->object->written = true;
303
stream *s = pdev->strm;
306
* The resource file is positionable, so rather than use an
307
* object reference for the length, we'll go back and fill it in
308
* at the end of the definition. Take 1M as the longest
309
* definition we can handle. (This used to be 10K, but there was
310
* a real file that exceeded this limit.)
312
stream_puts(s, "<</Length >>stream\n");
313
ppos->start_pos = stell(s);
315
code = pdf_begin_encrypt(pdev, &pdev->strm, pres->object->id);
320
pcp->y_offset = y_offset;
321
font->u.simple.s.type3.FontBBox.p.y =
322
min(font->u.simple.s.type3.FontBBox.p.y, y_offset);
323
font->u.simple.s.type3.FontBBox.q.x =
324
max(font->u.simple.s.type3.FontBBox.q.x, w);
325
font->u.simple.s.type3.FontBBox.q.y =
326
max(font->u.simple.s.type3.FontBBox.q.y, y_offset + h);
327
font->u.simple.s.type3.max_y_offset =
328
max(font->u.simple.s.type3.max_y_offset, h + (h >> 2));
333
/* End a CharProc. */
335
pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos)
338
long start_pos, end_pos, length;
340
pdf_end_encrypt(pdev);
342
start_pos = ppos->start_pos;
344
length = end_pos - start_pos;
346
return_error(gs_error_limitcheck);
347
sseek(s, start_pos - 15);
348
pprintd1(s, "%d", length);
351
stream_puts(s, "\n");
352
stream_puts(s, "endstream\n");
353
pdf_end_separate(pdev);
357
/* Mark glyph names for garbager. */
359
pdf_mark_glyph_names(const pdf_font_resource_t *pdfont, const gs_memory_t *memory)
361
if (pdfont->mark_glyph == NULL) {
362
/* Synthesised bitmap fonts pass here. */
365
if (pdfont->u.simple.Encoding != NULL) {
368
for (i = 0; i < 256; i++)
369
if (pdfont->u.simple.Encoding[i].glyph != GS_NO_GLYPH)
370
pdfont->mark_glyph(memory, pdfont->u.simple.Encoding[i].glyph, pdfont->mark_glyph_data);
372
if (pdfont->FontType == ft_user_defined) {
373
const pdf_char_proc_ownership_t *pcpo = pdfont->u.simple.s.type3.char_procs;
375
for (; pcpo != NULL; pcpo = pcpo->font_next)
376
pdfont->mark_glyph(memory, pcpo->glyph, pdfont->mark_glyph_data);
380
/* Put out a reference to an image as a character in a synthesized font. */
382
pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
383
const gs_matrix * pimat)
385
/* We need to choose a font, which use the charproc.
386
In most cases it is the last font, which the charproc is attached to.
387
If the charproc is substituted, it causes a font change. */
388
const pdf_char_proc_ownership_t * pcpo = pcp->owner_fonts;
389
pdf_font_resource_t *pdfont = pcpo->font;
390
byte ch = pcpo->char_code;
391
pdf_text_state_values_t values;
393
values.character_spacing = 0;
394
values.pdfont = pdfont;
396
values.matrix = *pimat;
397
values.matrix.ty -= pcp->y_offset;
398
values.render_mode = 0;
399
values.word_spacing = 0;
400
pdf_set_text_state_values(pdev, &values);
401
pdf_append_chars(pdev, &ch, 1, pdfont->Widths[ch] * pimat->xx, 0.0, false);
406
* Write the Encoding for bitmap fonts, if needed.
409
pdf_write_bitmap_fonts_Encoding(gx_device_pdf *pdev)
411
pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
413
if (pbfs->bitmap_encoding_id) {
417
pdf_open_separate(pdev, pbfs->bitmap_encoding_id);
420
* Even though the PDF reference documentation says that a
421
* BaseEncoding key is required unless the encoding is
422
* "based on the base font's encoding" (and there is no base
423
* font in this case), Acrobat 2.1 gives an error if the
424
* BaseEncoding key is present.
426
stream_puts(s, "<</Type/Encoding/Differences[0");
427
for (i = 0; i <= pbfs->max_embedded_code; ++i) {
429
stream_puts(s, "\n");
430
pprintd1(s, "/a%d", i);
432
stream_puts(s, "\n] >>\n");
433
pdf_end_separate(pdev);
434
pbfs->bitmap_encoding_id = 0;
440
* Start charproc accumulation for a Type 3 font.
443
pdf_start_charproc_accum(gx_device_pdf *pdev)
445
pdf_char_proc_t *pcp;
446
pdf_resource_t *pres;
447
int code = pdf_enter_substream(pdev, resourceCharProc, gs_next_ids(pdev->memory, 1),
448
&pres, false, pdev->CompressFonts);
452
pcp = (pdf_char_proc_t *)pres;
453
pcp->owner_fonts = NULL;
458
* Install charproc accumulator for a Type 3 font.
461
pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, const double *pw, int narg,
462
gs_text_cache_control_t control, gs_char ch)
464
pdf_font_resource_t *pdfont;
465
pdf_resource_t *pres = pdev->accumulating_substream_resource;
466
pdf_char_proc_t *pcp;
469
code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
472
pcp = (pdf_char_proc_t *)pres;
473
pcp->owner_fonts = NULL;
474
pcp->real_width.x = pw[font->WMode && narg > 6 ? 6 : 0];
475
pcp->real_width.y = pw[font->WMode && narg > 6 ? 7 : 1];
476
pcp->v.x = (narg > 8 ? pw[8] : 0);
477
pcp->v.y = (narg > 8 ? pw[9] : 0);
478
if (control == TEXT_SET_CHAR_WIDTH) {
479
/* PLRM 5.7.1 "BuildGlyph" reads : "Normally, it is unnecessary and
480
undesirable to initialize the current color parameter, because show
481
is defined to paint glyphs with the current color."
482
However comparefiles/Bug687044.ps doesn't follow that. */
483
pdev->skip_colors = false;
484
pprintg1(pdev->strm, "%g 0 d0\n", (float)pw[0]);
486
pdev->skip_colors = true;
487
pprintg6(pdev->strm, "%g %g %g %g %g %g d1\n",
488
(float)pw[0], (float)0.0, (float)pw[2],
489
(float)pw[3], (float)pw[4], (float)pw[5]);
490
pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
496
* Open a stream object in the temporary file.
500
pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype,
501
gs_id id, pdf_resource_t **ppres, bool reserve_object_id, int options)
504
pdf_resource_t *pres;
505
stream *s, *save_strm = pdev->strm;
506
pdf_data_writer_t writer;
507
static const pdf_filter_names_t fnames = {
511
pdev->streams.save_strm = pdev->strm;
512
code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, id),
513
pdf_resource_type_structs[rtype], &pres, reserve_object_id ? 0 : -1);
516
cos_become(pres->object, cos_type_stream);
517
s = cos_write_stream_alloc((cos_stream_t *)pres->object, pdev, "pdf_enter_substream");
519
return_error(gs_error_VMerror);
521
code = pdf_append_data_stream_filters(pdev, &writer,
522
options | DATA_STREAM_NOLENGTH, pres->object->id);
524
pdev->strm = save_strm;
527
code = pdf_put_filters((cos_dict_t *)pres->object, pdev, writer.binary.strm, &fnames);
529
pdev->strm = save_strm;
532
pdev->strm = writer.binary.strm;
538
* Close a stream object in the temporary file.
541
pdf_close_aside(gx_device_pdf *pdev)
543
/* We should call pdf_end_data here, but we don't want to put pdf_data_writer_t
544
into pdf_substream_save stack to simplify garbager descriptors.
545
Use a lower level functions instead that. */
546
stream *s = pdev->strm;
547
int status = s_close_filters(&s, cos_write_stream_from_pipeline(s));
548
cos_stream_t *pcs = cos_stream_from_pipeline(s);
552
code = gs_note_error(gs_error_ioerror);
553
pcs->is_open = false;
555
pdev->strm = pdev->streams.save_strm;
560
* Enter the substream accumulation mode.
563
pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype,
564
gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress)
566
int sbstack_ptr = pdev->sbstack_depth;
567
pdf_resource_t *pres;
568
stream *save_strm = pdev->strm;
571
if (pdev->sbstack_depth >= pdev->sbstack_size)
572
return_error(gs_error_unregistered); /* Must not happen. */
573
if (pdev->sbstack[sbstack_ptr].text_state == 0) {
574
pdev->sbstack[sbstack_ptr].text_state = pdf_text_state_alloc(pdev->pdf_memory);
575
if (pdev->sbstack[sbstack_ptr].text_state == 0)
576
return_error(gs_error_VMerror);
578
code = pdf_open_aside(pdev, rtype, id, &pres, reserve_object_id,
579
(compress ? DATA_STREAM_COMPRESS : 0));
582
code = pdf_save_viewer_state(pdev, NULL);
584
pdev->strm = save_strm;
587
pdev->sbstack[sbstack_ptr].context = pdev->context;
588
pdf_text_state_copy(pdev->sbstack[sbstack_ptr].text_state, pdev->text->text_state);
589
pdf_set_text_state_default(pdev->text->text_state);
590
pdev->sbstack[sbstack_ptr].clip_path = pdev->clip_path;
592
pdev->sbstack[sbstack_ptr].clip_path_id = pdev->clip_path_id;
593
pdev->clip_path_id = pdev->no_clip_path_id;
594
pdev->sbstack[sbstack_ptr].vgstack_bottom = pdev->vgstack_bottom;
595
pdev->vgstack_bottom = pdev->vgstack_depth;
596
pdev->sbstack[sbstack_ptr].strm = save_strm;
597
pdev->sbstack[sbstack_ptr].procsets = pdev->procsets;
598
pdev->sbstack[sbstack_ptr].substream_Resources = pdev->substream_Resources;
599
pdev->sbstack[sbstack_ptr].skip_colors = pdev->skip_colors;
600
pdev->sbstack[sbstack_ptr].font3 = pdev->font3;
601
pdev->sbstack[sbstack_ptr].accumulating_substream_resource = pdev->accumulating_substream_resource;
602
pdev->sbstack[sbstack_ptr].charproc_just_accumulated = pdev->charproc_just_accumulated;
603
pdev->sbstack[sbstack_ptr].accumulating_a_global_object = pdev->accumulating_a_global_object;
604
pdev->sbstack[sbstack_ptr].pres_soft_mask_dict = pdev->pres_soft_mask_dict;
605
pdev->sbstack[sbstack_ptr].objname = pdev->objname;
606
pdev->sbstack[sbstack_ptr].last_charpath_op = pdev->last_charpath_op;
607
pdev->skip_colors = false;
608
pdev->charproc_just_accumulated = false;
609
pdev->pres_soft_mask_dict = NULL;
610
pdev->objname.data = NULL;
611
pdev->objname.size = 0;
612
/* Do not reset pdev->accumulating_a_global_object - it inherits. */
613
pdev->sbstack_depth++;
616
pdev->context = PDF_IN_STREAM;
617
pdev->accumulating_substream_resource = pres;
618
pdev->last_charpath_op = 0;
619
/* Do not alter type3charpath, inherit the current value. We need to know if */
620
/* we are inside a charpath operation, and only reset this when the charpath */
622
pdf_reset_graphics(pdev);
628
* Exit the substream accumulation mode.
631
pdf_exit_substream(gx_device_pdf *pdev)
636
if (pdev->sbstack_depth <= 0)
637
return_error(gs_error_unregistered); /* Must not happen. */
638
code = pdf_open_contents(pdev, PDF_IN_STREAM);
639
sbstack_ptr = pdev->sbstack_depth - 1;
640
while (pdev->vgstack_depth > pdev->vgstack_bottom) {
641
code1 = pdf_restore_viewer_state(pdev, pdev->strm);
645
if (pdev->clip_path != 0)
646
gx_path_free(pdev->clip_path, "pdf_end_charproc_accum");
647
code1 = pdf_close_aside(pdev);
648
if (code1 < 0 && code >= 0)
650
pdev->context = pdev->sbstack[sbstack_ptr].context;
651
pdf_text_state_copy(pdev->text->text_state, pdev->sbstack[sbstack_ptr].text_state);
652
pdev->clip_path = pdev->sbstack[sbstack_ptr].clip_path;
653
pdev->sbstack[sbstack_ptr].clip_path = 0;
654
pdev->clip_path_id = pdev->sbstack[sbstack_ptr].clip_path_id;
655
pdev->vgstack_bottom = pdev->sbstack[sbstack_ptr].vgstack_bottom;
656
pdev->strm = pdev->sbstack[sbstack_ptr].strm;
657
pdev->sbstack[sbstack_ptr].strm = 0;
658
pdev->procsets = pdev->sbstack[sbstack_ptr].procsets;
659
pdev->substream_Resources = pdev->sbstack[sbstack_ptr].substream_Resources;
660
pdev->sbstack[sbstack_ptr].substream_Resources = 0;
661
pdev->skip_colors = pdev->sbstack[sbstack_ptr].skip_colors;
662
pdev->font3 = pdev->sbstack[sbstack_ptr].font3;
663
pdev->sbstack[sbstack_ptr].font3 = 0;
664
pdev->accumulating_substream_resource = pdev->sbstack[sbstack_ptr].accumulating_substream_resource;
665
pdev->sbstack[sbstack_ptr].accumulating_substream_resource = 0;
666
pdev->charproc_just_accumulated = pdev->sbstack[sbstack_ptr].charproc_just_accumulated;
667
pdev->accumulating_a_global_object = pdev->sbstack[sbstack_ptr].accumulating_a_global_object;
668
pdev->pres_soft_mask_dict = pdev->sbstack[sbstack_ptr].pres_soft_mask_dict;
669
pdev->objname = pdev->sbstack[sbstack_ptr].objname;
670
pdev->last_charpath_op = pdev->sbstack[sbstack_ptr].last_charpath_op;
671
pdev->sbstack_depth = sbstack_ptr;
672
code1 = pdf_restore_viewer_state(pdev, NULL);
673
if (code1 < 0 && code >= 0)
679
pdf_is_same_charproc_attrs1(gx_device_pdf *pdev, pdf_char_proc_t *pcp0, pdf_char_proc_t *pcp1)
681
if (pcp0->real_width.x != pcp1->real_width.x)
683
if (pcp0->real_width.y != pcp1->real_width.y)
685
if (pcp0->v.x != pcp1->v.x)
687
if (pcp0->v.y != pcp1->v.y)
692
typedef struct charproc_compatibility_data_s {
693
const pdf_char_glyph_pairs_t *cgp;
694
pdf_font_resource_t *pdfont;
698
} charproc_compatibility_data_t;
701
is_char_code_used(pdf_font_resource_t *pdfont, gs_char char_code)
703
pdf_char_proc_ownership_t *pcpo;
705
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
706
if (pcpo->char_code == char_code) {
714
pdf_is_charproc_compatible(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
716
charproc_compatibility_data_t *data = (charproc_compatibility_data_t *)pdev->find_resource_param;
717
pdf_char_proc_t *pcp0 = (pdf_char_proc_t *)pres0;
718
pdf_char_proc_t *pcp1 = (pdf_char_proc_t *)pres1;
719
pdf_font_resource_t *pdfont = data->pdfont;
720
pdf_char_proc_ownership_t *pcpo;
721
pdf_font_cache_elem_t **e;
722
bool can_add_to_current_font = false, computed_can_add_to_current_font = false;
724
/* Does it have same attributes ? */
725
if (!pdf_is_same_charproc_attrs1(pdev, pcp0, pcp1))
727
/* Is it from same font ? */
728
for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
729
if (pdfont == pcpo->font) {
730
/* Check for encoding conflict. */
731
if (pcpo->char_code == data->char_code && pcpo->glyph == data->glyph)
732
return 1; /* Same char code. */
733
if (!computed_can_add_to_current_font) {
734
can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
735
computed_can_add_to_current_font = true;
737
if (can_add_to_current_font)
738
return 1; /* No conflict. */
741
/* Look for another font with same encoding,
742
because we want to reduce the number of new fonts.
743
We also restrict with ones attached to same PS font,
744
otherwise it creates too mixed fonts and disturbs word breaks.
746
e = pdf_locate_font_cache_elem(pdev, data->font);
748
for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
749
if (pcpo->char_code != data->char_code || pcpo->glyph != data->glyph)
750
continue; /* Need same Encoding to generate a proper ToUnicode. */
751
if (pdfont->u.simple.s.type3.bitmap_font != pcpo->font->u.simple.s.type3.bitmap_font)
753
if (memcmp(&pdfont->u.simple.s.type3.FontMatrix, &pcpo->font->u.simple.s.type3.FontMatrix,
754
sizeof(pdfont->u.simple.s.type3.FontMatrix)))
756
if (data->cgp != NULL) {
757
if (!pdf_check_encoding_compatibility(pcpo->font, data->cgp->s, data->cgp->num_all_chars))
760
if ((*e)->pdfont != pcpo->font)
762
data->pdfont = pcpo->font; /* Switch to the other font. */
766
/* Check whether it can be added into the current font. */
767
if (!computed_can_add_to_current_font)
768
can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
769
if (!can_add_to_current_font) {
770
/* Can't substitute due to encoding conflict. */
773
/* The current font will share it with another font. */
778
pdf_find_same_charproc_aux(gx_device_pdf *pdev,
779
pdf_font_resource_t **ppdfont, pdf_char_proc_t **ppcp)
781
pdf_char_proc_ownership_t *pcpo;
784
/* fixme: this passes parameters to pdf_is_charproc_compatible
785
through special gx_device_pdf field pdev->find_resource_param
786
due to prototype limitation of pdf_find_same_resource.
787
It would be better to change the client data argument type in there to void. */
788
for (pcpo = (*ppdfont)->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
789
pdf_char_proc_t *pcp = pcpo->char_proc;
791
if (*ppcp != pcp && pdf_is_same_charproc_attrs1(pdev, *ppcp, pcp)) {
792
cos_object_t *pco0 = pcp->object;
793
cos_object_t *pco1 = (*ppcp)->object;
795
code = pco0->cos_procs->equal(pco0, pco1, pdev);
805
return pdf_find_same_resource(pdev, resourceCharProc, (pdf_resource_t **)ppcp, pdf_is_charproc_compatible);
808
pdf_find_same_charproc(gx_device_pdf *pdev,
809
pdf_font_resource_t **ppdfont, const pdf_char_glyph_pairs_t *cgp,
810
pdf_char_proc_t **ppcp, gs_glyph glyph, gs_char char_code,
813
charproc_compatibility_data_t data;
817
data.pdfont = *ppdfont;
818
data.char_code = char_code;
821
pdev->find_resource_param = &data;
822
code = pdf_find_same_charproc_aux(pdev, ppdfont, ppcp);
823
pdev->find_resource_param = NULL;
824
*ppdfont = data.pdfont;
829
pdf_is_charproc_defined(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, gs_char ch)
831
pdf_char_proc_ownership_t *pcpo;
833
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
834
if (pcpo->char_code == ch)
841
complete_adding_char(gx_device_pdf *pdev, gs_font *font,
842
gs_glyph glyph, gs_char ch, pdf_char_proc_t *pcp,
843
const gs_const_string *gnstr)
845
pdf_font_resource_t *pdfont;
848
int char_cache_size, width_cache_size;
849
pdf_encoding_element_t *pet;
852
code = pdf_attached_font_resource(pdev, font, &pdfont,
853
&glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
856
code = pdf_attach_charproc(pdev, pdfont, pcp, glyph, ch, gnstr);
859
if (ch >= char_cache_size || ch >= width_cache_size)
860
return_error(gs_error_unregistered); /* Must not happen. */
861
pet = &pdfont->u.simple.Encoding[ch];
862
pdfont->Widths[ch] = pcp->real_width.x;
863
real_widths[ch * 2 ] = pcp->real_width.x;
864
real_widths[ch * 2 + 1] = pcp->real_width.y;
865
glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
866
pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
867
if (pdfont->u.simple.v != NULL && font->WMode) {
868
pdfont->u.simple.v[ch].x = pcp->v.x;
869
pdfont->u.simple.v[ch].y = pcp->v.x;
873
pet->is_difference = true;
874
if (pdfont->u.simple.LastChar < (int)ch)
875
pdfont->u.simple.LastChar = (int)ch;
876
if (pdfont->u.simple.FirstChar > (int)ch)
877
pdfont->u.simple.FirstChar = (int)ch;
882
pdf_char_widths_from_charprocs(gx_device_pdf *pdev, gs_font *font)
884
pdf_font_resource_t *pdfont;
887
int char_cache_size, width_cache_size;
888
pdf_char_proc_ownership_t *pcpo;
891
code = pdf_attached_font_resource(pdev, font, &pdfont,
892
&glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
895
for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
896
pdf_char_proc_t *pcp = pcpo->char_proc;
897
gs_char ch = pcpo->char_code;
899
real_widths[ch * 2 ] = pcp->real_width.x;
900
real_widths[ch * 2 + 1] = pcp->real_width.y;
901
glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
908
* Complete charproc accumulation for a Type 3 font.
911
pdf_end_charproc_accum(gx_device_pdf *pdev, gs_font *font, const pdf_char_glyph_pairs_t *cgp,
912
gs_glyph glyph, gs_char output_char_code, const gs_const_string *gnstr)
915
pdf_resource_t *pres = (pdf_resource_t *)pdev->accumulating_substream_resource;
916
/* We could use pdfont->u.simple.s.type3.char_procs insted the thing above
917
unless the font is defined recursively.
918
But we don't want such assumption. */
919
pdf_char_proc_t *pcp = (pdf_char_proc_t *)pres;
920
pdf_font_resource_t *pdfont;
921
gs_char ch = output_char_code;
922
bool checking_glyph_variation = false;
924
if (ch == GS_NO_CHAR)
925
return_error(gs_error_unregistered); /* Must not happen. */
927
return_error(gs_error_unregistered); /* Must not happen. */
928
code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
931
if (pdfont != (pdf_font_resource_t *)pdev->font3)
932
return_error(gs_error_unregistered); /* Must not happen. */
933
code = pdf_exit_substream(pdev);
936
if (!(pdfont->used[ch >> 3] & (0x80 >> (ch & 7))) ||
937
!(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))) {
938
/* First appearence or not cached - check for duplicates. */
939
pdf_font_resource_t *pdfont1 = pdfont;
941
checking_glyph_variation = true;
942
/* CAUTION : a possible font change. */
943
code = pdf_find_same_charproc(pdev, &pdfont, cgp, &pcp, glyph, ch, font);
947
code = pdf_cancel_resource(pdev, pres, resourceCharProc);
950
pdf_forget_resource(pdev, pres, resourceCharProc);
951
if (pdfont1 != pdfont) {
952
code = pdf_attach_font_resource(pdev, font, pdfont);
955
code = pdf_char_widths_from_charprocs(pdev, font);
959
pdev->charproc_just_accumulated = true;
960
return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
962
if (pdf_is_charproc_defined(pdev, pdfont, ch)) {
963
/* Encoding conflict after a font change. */
964
gs_font *base_font = font, *below;
966
while ((below = base_font->base) != base_font &&
967
base_font->procs.same_font(base_font, below, FONT_SAME_OUTLINES))
969
code = pdf_make_font3_resource(pdev, base_font, &pdfont);
972
code = pdf_attach_font_resource(pdev, font, pdfont);
977
pdf_reserve_object_id(pdev, pres, 0);
978
if (checking_glyph_variation)
979
pdev->charproc_just_accumulated = true;
980
return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
983
/* Add procsets to substream Resources. */
985
pdf_add_procsets(cos_dict_t *pcd, pdf_procset_t procsets)
987
char str[5 + 7 + 7 + 7 + 5 + 2];
990
strcpy(str, "[/PDF");
991
if (procsets & ImageB)
992
strcat(str, "/ImageB");
993
if (procsets & ImageC)
994
strcat(str, "/ImageC");
995
if (procsets & ImageI)
996
strcat(str, "/ImageI");
998
strcat(str, "/Text");
1000
cos_string_value(&v, (byte *)str, strlen(str));
1001
return cos_dict_put_c_key(pcd, "/ProcSet", &v);
1004
/* Add a resource to substream Resources. */
1006
pdf_add_resource(gx_device_pdf *pdev, cos_dict_t *pcd, const char *key, pdf_resource_t *pres)
1009
const cos_value_t *v = cos_dict_find(pcd, (const byte *)key, strlen(key));
1012
char buf[10 + (sizeof(long) * 8 / 3 + 1)], buf1[sizeof(pres->rname) + 1];
1014
if (pdev->ForOPDFRead && !pres->global && pdev->accumulating_a_global_object) {
1015
pres->global = true;
1016
code = cos_dict_put_c_key_bool((cos_dict_t *)pres->object, "/.Global", true);
1020
sprintf(buf, "%ld 0 R\n", pres->object->id);
1022
if (v->value_type != COS_VALUE_OBJECT &&
1023
v->value_type != COS_VALUE_RESOURCE)
1024
return_error(gs_error_unregistered); /* Must not happen. */
1025
list = (cos_dict_t *)v->contents.object;
1026
if (list->cos_procs != &cos_dict_procs)
1027
return_error(gs_error_unregistered); /* Must not happen. */
1029
list = cos_dict_alloc(pdev, "pdf_add_resource");
1031
return_error(gs_error_VMerror);
1032
code = cos_dict_put_c_key_object((cos_dict_t *)pcd, key, (cos_object_t *)list);
1037
strcpy(buf1 + 1, pres->rname);
1038
return cos_dict_put_string(list, (const byte *)buf1, strlen(buf1),
1039
(const byte *)buf, strlen(buf));