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
/* Encoding-based (Type 1/2/42) text processing for pdfwrite. */
29
#include "gxpath.h" /* for getting current point */
30
#include "gxchar.h" /* for gx_compute_text_oversampling & gx_lookup_cached_char */
31
#include "gxfcache.h" /* for gx_lookup_fm_pair */
42
static int pdf_char_widths(gx_device_pdf *const pdev,
43
pdf_font_resource_t *pdfont, int ch,
45
pdf_glyph_widths_t *pwidths /* may be NULL */);
46
static int pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr,
47
const gs_matrix *pfmat,
48
pdf_text_process_state_t *ppts,
49
const gs_glyph *gdata);
52
* Process a string with a simple gs_font.
55
pdf_process_string_aux(pdf_text_enum_t *penum, gs_string *pstr,
56
const gs_glyph *gdata, const gs_matrix *pfmat,
57
pdf_text_process_state_t *ppts)
59
gs_font_base *font = (gs_font_base *)penum->current_font;
61
switch (font->FontType) {
66
case ft_PCL_user_defined:
67
case ft_GL2_stick_user_defined:
71
return_error(gs_error_rangecheck);
73
return pdf_process_string(penum, pstr, pfmat, ppts, gdata);
77
* Add char code pair to ToUnicode CMap,
78
* creating the CMap on neccessity.
81
pdf_add_ToUnicode(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfont,
82
gs_glyph glyph, gs_char ch, const gs_const_string *gnstr)
86
if (glyph == GS_NO_GLYPH)
88
unicode = font->procs.decode_glyph((gs_font *)font, glyph, ch);
89
if (unicode == GS_NO_CHAR && gnstr != NULL && gnstr->size == 7) {
90
if (!memcmp(gnstr->data, "uni", 3)) {
91
static const char *hexdigits = "0123456789ABCDEF";
92
char *d0 = strchr(hexdigits, gnstr->data[3]);
93
char *d1 = strchr(hexdigits, gnstr->data[4]);
94
char *d2 = strchr(hexdigits, gnstr->data[5]);
95
char *d3 = strchr(hexdigits, gnstr->data[6]);
97
if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL)
98
unicode = ((d0 - hexdigits) << 12) + ((d1 - hexdigits) << 8) +
99
((d2 - hexdigits) << 4 ) + (d3 - hexdigits);
102
if (unicode != GS_NO_CHAR) {
103
if (pdfont->cmap_ToUnicode == NULL) {
104
/* ToUnicode CMaps are always encoded with two byte keys. See
105
* Technical Note 5411, 'ToUnicode Mapping File Tutorial'
108
/* Unfortunately, the above is not true. See the PDF Reference (version 1.7
109
* p 472 'ToUnicode CMaps'. Even that documentation is incorrect as it
110
* describes codespaceranges, in fact for Acrobat this is irrelevant,
111
* but the bfranges must be one byte for simple fonts. By altering the
112
* key size for CID fonts we can write both consistently correct.
114
uint num_codes = 256, key_size = 1;
116
if (font->FontType == ft_CID_encrypted) {
117
gs_font_cid0 *pfcid = (gs_font_cid0 *)font;
119
num_codes = pfcid->cidata.common.CIDCount;
121
} else if (font->FontType == ft_CID_TrueType || font->FontType == ft_composite) {
123
#ifdef DEPRECATED_906
124
gs_font_cid2 *pfcid = (gs_font_cid2 *)font;
126
num_codes = pfcid->cidata.common.CIDCount;
128
/* Since PScript5.dll creates GlyphNames2Unicode with character codes
129
instead CIDs, and with the WinCharSetFFFF-H2 CMap
130
character codes appears from the range 0-0xFFFF (Bug 687954),
131
we must use the maximal character code value for the ToUnicode
136
code = gs_cmap_ToUnicode_alloc(pdev->pdf_memory, pdfont->rid, num_codes, key_size,
137
&pdfont->cmap_ToUnicode);
141
if (pdfont->cmap_ToUnicode != NULL)
142
gs_cmap_ToUnicode_add_pair(pdfont->cmap_ToUnicode, ch, unicode);
149
pdf_resource_type_t rtype;
150
} pdf_resource_enum_data_t;
153
process_resources2(void *client_data, const byte *key_data, uint key_size, const cos_value_t *v)
155
pdf_resource_enum_data_t *data = (pdf_resource_enum_data_t *)client_data;
156
pdf_resource_t *pres = pdf_find_resource_by_resource_id(data->pdev, data->rtype, v->contents.object->id);
159
return_error(gs_error_unregistered); /* Must not happen. */
160
pres->where_used |= data->pdev->used_mask;
165
process_resources1(void *client_data, const byte *key_data, uint key_size, const cos_value_t *v)
167
pdf_resource_enum_data_t *data = (pdf_resource_enum_data_t *)client_data;
168
static const char *rn[] = {PDF_RESOURCE_TYPE_NAMES};
171
for (i = 0; i < count_of(rn); i++) {
172
if (rn[i] != NULL && !bytes_compare((const byte *)rn[i], strlen(rn[i]), key_data, key_size))
175
if (i >= count_of(rn))
178
return cos_dict_forall((cos_dict_t *)v->contents.object, data, process_resources2);
182
* Register charproc fonts with the page or substream.
185
pdf_used_charproc_resources(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
187
if (pdfont->where_used & pdev->used_mask)
189
pdfont->where_used |= pdev->used_mask;
190
if (pdev->CompatibilityLevel >= 1.2)
192
if (pdfont->FontType == ft_user_defined ||
193
pdfont->FontType == ft_PCL_user_defined ||
194
pdfont->FontType == ft_GL2_stick_user_defined ||
195
pdfont->FontType == ft_GL2_531) {
196
pdf_resource_enum_data_t data;
199
return cos_dict_forall(pdfont->u.simple.s.type3.Resources, &data, process_resources1);
205
* Given a text string and a simple gs_font, return a font resource suitable
206
* for the text string, possibly re-encoding the string. This
207
* may involve creating a font resource and/or adding glyphs and/or Encoding
213
pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfont,
214
gs_char ch, const gs_glyph *gdata)
216
gs_font_base *cfont, *ccfont;
218
gs_glyph copied_glyph;
219
gs_const_string gnstr;
220
pdf_encoding_element_t *pet;
224
* In contradiction with pre-7.20 versions of pdfwrite,
225
* we never re-encode texts due to possible encoding conflict while font merging.
227
cfont = pdf_font_resource_font(pdfont, false);
228
ccfont = pdf_font_resource_font(pdfont, true);
229
pet = &pdfont->u.simple.Encoding[ch];
230
glyph = (gdata == NULL ? font->procs.encode_char(font, ch, GLYPH_SPACE_NAME)
232
if (glyph == GS_NO_GLYPH || glyph == pet->glyph)
234
if (pet->glyph != GS_NO_GLYPH) { /* encoding conflict */
235
return_error(gs_error_rangecheck);
236
/* Must not happen because pdf_obtain_font_resource
237
* checks for encoding compatibility.
240
code = font->procs.glyph_name(font, glyph, &gnstr);
242
return code; /* can't get name of glyph */
243
if (font->FontType != ft_user_defined &&
244
font->FontType != ft_PCL_user_defined &&
245
font->FontType != ft_GL2_stick_user_defined &&
246
font->FontType != ft_GL2_531) {
247
/* The standard 14 fonts don't have a FontDescriptor. */
248
code = (pdfont->base_font != 0 ?
249
pdf_base_font_copy_glyph(pdfont->base_font, glyph, (gs_font_base *)font) :
250
pdf_font_used_glyph(pdfont->FontDescriptor, glyph, (gs_font_base *)font));
251
if (code < 0 && code != gs_error_undefined)
253
if (code == gs_error_undefined) {
254
if (pdev->PDFA != 0 || pdev->PDFX) {
255
switch (pdev->PDFACompatibilityPolicy) {
257
emprintf(pdev->memory,
258
"Requested glyph not present in source font,\n not permitted in PDF/A, reverting to normal PDF output\n");
259
pdev->AbortPDFAX = true;
263
emprintf(pdev->memory,
264
"Requested glyph not present in source font,\n not permitted in PDF/A, glyph will not be present in output file\n\n");
265
/* Returning an error causees text processing to try and
266
* handle the glyph by rendering to a bitmap instead of
267
* as a glyph in a font. This will eliminate the problem
268
* and the fiel should appear the same as the original.
270
return gs_error_unknownerror;
273
emprintf(pdev->memory,
274
"Requested glyph not present in source font,\n not permitted in PDF/A, aborting conversion\n");
275
/* Careful here, only certain errors will bubble up
276
* through the text processing.
278
return gs_error_invalidfont;
281
emprintf(pdev->memory,
282
"Requested glyph not present in source font,\n not permitted in PDF/A, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n");
283
pdev->AbortPDFAX = true;
288
/* PS font has no such glyph. */
289
if (bytes_compare(gnstr.data, gnstr.size, (const byte *)".notdef", 7)) {
292
pet->is_difference = true;
294
} else if (pdfont->base_font == NULL && ccfont != NULL &&
295
(gs_copy_glyph_options(font, glyph, (gs_font *)ccfont, COPY_GLYPH_NO_NEW) != 1 ||
296
gs_copied_font_add_encoding((gs_font *)ccfont, ch, glyph) < 0)) {
298
* The "complete" copy of the font appears incomplete
299
* due to incrementally added glyphs. Drop the "complete"
300
* copy now and continue with subset font only.
302
* Note that we need to add the glyph to the encoding of the
303
* "complete" font, because "PPI-ProPag 2.6.1.4 (archivePg)"
304
* creates multiple font copies with reduced encodings
305
* (we believe it is poorly designed),
306
* and we can merge the copies back to a single font (see Bug 686875).
307
* We also check whether the encoding is compatible.
308
* It must be compatible here due to the pdf_obtain_font_resource
309
* and ccfont logics, but we want to ensure for safety reason.
312
pdf_font_descriptor_drop_complete_font(pdfont->FontDescriptor);
315
* We arbitrarily allow the first encoded character in a given
316
* position to determine the encoding associated with the copied
319
copied_glyph = cfont->procs.encode_char((gs_font *)cfont, ch,
321
if (glyph != copied_glyph &&
322
gs_copied_font_add_encoding((gs_font *)cfont, ch, glyph) < 0
324
pet->is_difference = true;
325
pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
328
* We always generate ToUnicode for simple fonts, because
329
* we can't detemine in advance, which glyphs the font actually uses.
330
* The decision about writing it out is deferred until pdf_write_font_resource.
332
code = pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, &gnstr);
341
* Estimate text bbox.
344
process_text_estimate_bbox(pdf_text_enum_t *pte, gs_font_base *font,
345
const gs_const_string *pstr,
346
const gs_matrix *pfmat,
347
gs_rect *text_bbox, gs_point *pdpt)
351
(pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
352
pte->text.space.s_char : -1);
353
int WMode = font->WMode;
355
gs_point total = {0, 0};
356
gs_fixed_point origin;
358
int xy_index = pte->xy_index;
360
if (font->FontBBox.p.x == font->FontBBox.q.x ||
361
font->FontBBox.p.y == font->FontBBox.q.y)
362
return_error(gs_error_undefined);
363
code = gx_path_current_point(pte->path, &origin);
366
m = ctm_only(pte->pis);
367
m.tx = fixed2float(origin.x);
368
m.ty = fixed2float(origin.y);
369
gs_matrix_multiply(pfmat, &m, &m);
370
for (i = 0; i < pstr->size; ++i) {
371
byte c = pstr->data[i];
373
gs_point wanted, tpt, p0, p1, p2, p3;
374
gs_glyph glyph = font->procs.encode_char((gs_font *)font, c,
376
gs_glyph_info_t info;
379
if (glyph == gs_no_glyph)
380
return_error (gs_error_invalidfont);
382
code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
383
GLYPH_INFO_WIDTH0 << WMode,
386
/* If we got an undefined error, and its a type 1/CFF font, try to
387
* find the /.notdef glyph and use its width instead (as this is the
388
* glyph which will be rendered). We don't do this for other font types
389
* as it seems Acrobat/Distiller may not do so either.
391
/* The GL/2 stick font does not supply the enumerate_glyphs method,
392
* *and* leaves it uninitialised. But it should not be possible to
393
* get an undefiend error with this font anyway.
396
if ((font->FontType == ft_encrypted ||
397
font->FontType == ft_encrypted2)) {
401
(font->procs.enumerate_glyph((gs_font *)font, &index,
402
(GLYPH_SPACE_NAME), &glyph)) >= 0 &&
405
if (gs_font_glyph_is_notdef(font, glyph)) {
406
code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
407
GLYPH_INFO_WIDTH0 << WMode,
419
gs_point_transform(font->FontBBox.p.x, font->FontBBox.p.y, &m, &p0);
420
gs_point_transform(font->FontBBox.p.x, font->FontBBox.q.y, &m, &p1);
421
gs_point_transform(font->FontBBox.q.x, font->FontBBox.p.y, &m, &p2);
422
gs_point_transform(font->FontBBox.q.x, font->FontBBox.q.y, &m, &p3);
423
bbox.p.x = min(min(p0.x, p1.x), min(p1.x, p2.x)) + total.x;
424
bbox.p.y = min(min(p0.y, p1.y), min(p1.y, p2.y)) + total.y;
425
bbox.q.x = max(max(p0.x, p1.x), max(p1.x, p2.x)) + total.x;
426
bbox.q.y = max(max(p0.y, p1.y), max(p1.y, p2.y)) + total.y;
430
rect_merge(*text_bbox, bbox);
431
if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
432
gs_text_replaced_width(&pte->text, xy_index++, &tpt);
433
gs_distance_transform(tpt.x, tpt.y, &ctm_only(pte->pis), &wanted);
435
gs_distance_transform(info.width[WMode].x,
438
if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
439
gs_distance_transform(pte->text.delta_all.x,
440
pte->text.delta_all.y,
441
&ctm_only(pte->pis), &tpt);
445
if (pstr->data[i] == space_char && pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
446
gs_distance_transform(pte->text.delta_space.x,
447
pte->text.delta_space.y,
448
&ctm_only(pte->pis), &tpt);
461
adjust_first_last_char(pdf_font_resource_t *pdfont, byte *str, int size)
465
for (i = 0; i < size; ++i) {
468
if (chr < pdfont->u.simple.FirstChar)
469
pdfont->u.simple.FirstChar = chr;
470
if (chr > pdfont->u.simple.LastChar)
471
pdfont->u.simple.LastChar = chr;
476
pdf_shift_text_currentpoint(pdf_text_enum_t *penum, gs_point *wpt)
479
extern_st(st_gs_state);
481
if (gs_object_type(penum->dev->memory, penum->pis) != &st_gs_state) {
482
/* Probably never happens. Not sure though. */
483
return_error(gs_error_unregistered);
485
pgs = (gs_state *)penum->pis;
486
return gs_moveto_aux(penum->pis, gx_current_path(pgs),
487
fixed2float(penum->origin.x) + wpt->x,
488
fixed2float(penum->origin.y) + wpt->y);
492
* Internal procedure to process a string in a non-composite font.
493
* Doesn't use or set pte->{data,size,index}; may use/set pte->xy_index;
494
* may set penum->returned.total_width. Sets ppts->values.
496
* Note that the caller is responsible for re-encoding the string, if
497
* necessary; for adding Encoding entries in pdfont; and for copying any
498
* necessary glyphs. penum->current_font provides the gs_font for getting
499
* glyph metrics, but this font's Encoding is not used.
501
static int process_text_return_width(const pdf_text_enum_t *pte,
503
pdf_text_process_state_t *ppts,
504
const gs_const_string *pstr, const gs_glyph *gdata,
505
gs_point *pdpt, int *accepted);
507
pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr,
508
const gs_matrix *pfmat,
509
pdf_text_process_state_t *ppts, const gs_glyph *gdata)
511
gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
512
gs_font_base *font = (gs_font_base *)penum->current_font;
513
pdf_font_resource_t *pdfont;
514
const gs_text_params_t *text = &penum->text;
519
code = pdf_obtain_font_resource(penum, pstr, &pdfont);
523
pfmat = &font->FontMatrix;
524
if (text->operation & TEXT_RETURN_WIDTH) {
525
code = gx_path_current_point(penum->path, &penum->origin);
531
if (penum->pis->text_rendering_mode != 3 && !(text->operation & TEXT_DO_NONE)) {
533
* Acrobat Reader can't handle text with huge coordinates,
534
* so skip the text if it is outside the clip bbox
535
* (Note : it ever fails with type 3 fonts).
537
gs_rect text_bbox = {{0, 0}, {0, 0}};
539
code = process_text_estimate_bbox(penum, font, (gs_const_string *)pstr, pfmat,
540
&text_bbox, &width_pt);
542
gs_fixed_rect clip_bbox;
545
gx_cpath_outer_box(penum->pcpath, &clip_bbox);
546
rect.p.x = fixed2float(clip_bbox.p.x);
547
rect.p.y = fixed2float(clip_bbox.p.y);
548
rect.q.x = fixed2float(clip_bbox.q.x);
549
rect.q.y = fixed2float(clip_bbox.q.y);
550
rect_intersect(rect, text_bbox);
551
if (rect.p.x > rect.q.x || rect.p.y > rect.q.y) {
552
penum->index += pstr->size;
557
/* We have no penum->pcpath. */
561
* Note that pdf_update_text_state sets all the members of ppts->values
562
* to their current values.
564
code = pdf_update_text_state(ppts, penum, pdfont, pfmat);
566
/* Try not to emulate ADD_TO_WIDTH if we don't have to. */
567
if (code & TEXT_ADD_TO_SPACE_WIDTH) {
568
if (!memchr(pstr->data, penum->text.space.s_char, pstr->size))
569
code &= ~TEXT_ADD_TO_SPACE_WIDTH;
576
if (text->operation & TEXT_REPLACE_WIDTHS)
577
mask |= TEXT_REPLACE_WIDTHS;
580
* The only operations left to handle are TEXT_DO_DRAW and
585
* If any character has real_width != Width, we have to process
586
* the string character-by-character. process_text_return_width
587
* will tell us what we need to know.
589
if (!(text->operation & (TEXT_DO_DRAW | TEXT_RETURN_WIDTH)))
591
code = process_text_return_width(penum, font, ppts,
592
(gs_const_string *)pstr, gdata,
593
&width_pt, &accepted);
597
/* No characters with redefined widths -- the fast case. */
598
if (text->operation & TEXT_DO_DRAW || penum->pis->text_rendering_mode == 3) {
599
code = pdf_append_chars(pdev, pstr->data, accepted,
600
width_pt.x, width_pt.y, false);
603
adjust_first_last_char(pdfont, pstr->data, accepted);
604
penum->index += accepted;
605
} else if (text->operation & TEXT_DO_NONE)
606
penum->index += accepted;
608
/* Use the slow case. Set mask to any non-zero value. */
609
mask = TEXT_RETURN_WIDTH;
613
/* process_text_modify_width destroys text parameters, save them now. */
614
int index0 = penum->index, xy_index = penum->xy_index;
615
gs_text_params_t text = penum->text;
616
int xy_index_step = (!(penum->text.operation & TEXT_REPLACE_WIDTHS) ? 0 :
617
penum->text.x_widths == penum->text.y_widths ? 2 : 1);
618
/* A glyphshow takes a shortcut by storing the single glyph directly into
619
* penum->text.data.d_glyph. However, process_text_modify_width
620
* replaces pte->text.data.bytes (these two are part of a union) with
621
* pstr->data, which is not valid for a glyphshow because it alters
622
* the glyph value store there. If we make a copy of the single glyph,
623
* it all works correctly.then
625
gs_glyph gdata_i, *gdata_p = (gs_glyph *)gdata;
626
if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
631
if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
632
if (penum->text.x_widths != NULL)
633
penum->text.x_widths += xy_index * xy_index_step;
634
if (penum->text.y_widths != NULL)
635
penum->text.y_widths += xy_index * xy_index_step;
638
code = process_text_modify_width(penum, (gs_font *)font, ppts,
639
(gs_const_string *)pstr,
640
&width_pt, (const gs_glyph *)gdata_p, false);
641
if (penum->text.operation & TEXT_REPLACE_WIDTHS) {
642
if (penum->text.x_widths != NULL)
643
penum->text.x_widths -= xy_index * xy_index_step;
644
if (penum->text.y_widths != NULL)
645
penum->text.y_widths -= xy_index * xy_index_step;
647
penum->xy_index += xy_index;
648
adjust_first_last_char(pdfont, pstr->data, penum->index);
650
penum->index += index0;
656
/* Finally, return the total width if requested. */
657
if (!(text->operation & TEXT_RETURN_WIDTH))
659
if (text->operation & TEXT_DO_NONE) {
660
/* stringwidth needs to transform to user space. */
663
gs_distance_transform_inverse(width_pt.x, width_pt.y, &ctm_only(penum->pis), &p);
664
penum->returned.total_width.x += p.x;
665
penum->returned.total_width.y += p.y;
667
penum->returned.total_width = width_pt;
668
return pdf_shift_text_currentpoint(penum, &width_pt);
672
* Get the widths (unmodified and possibly modified) of a given character
673
* in a simple font. May add the widths to the widths cache (pdfont->Widths
674
* and pdf_font_cache_elem::real_widths). Return 1 if the widths were not cached.
677
pdf_char_widths(gx_device_pdf *const pdev,
678
pdf_font_resource_t *pdfont, int ch, gs_font_base *font,
679
pdf_glyph_widths_t *pwidths /* may be NULL */)
681
pdf_glyph_widths_t widths;
685
int char_cache_size, width_cache_size;
686
pdf_font_resource_t *pdfont1;
688
code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont1,
689
&glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
692
if (pdfont1 != pdfont)
693
return_error(gs_error_unregistered); /* Must not happen. */
694
if (ch < 0 || ch > 255)
695
return_error(gs_error_rangecheck);
696
if (ch >= width_cache_size)
697
return_error(gs_error_unregistered); /* Must not happen. */
700
if ((font->FontType != ft_user_defined &&
701
font->FontType != ft_PCL_user_defined &&
702
font->FontType != ft_GL2_stick_user_defined &&
703
font->FontType != ft_GL2_531) && real_widths[ch] == 0) {
704
/* Might be an unused char, or just not cached. */
705
gs_glyph glyph = pdfont->u.simple.Encoding[ch].glyph;
707
code = pdf_glyph_widths(pdfont, font->WMode, glyph, (gs_font *)font, pwidths, NULL);
710
if (font->WMode != 0 && code > 0 && !pwidths->replaced_v) {
712
* The font has no Metrics2, so it must write
713
* horizontally due to PS spec.
714
* Therefore we need to fill the Widths array,
715
* which is required by PDF spec.
716
* Take it from WMode==0.
718
code = pdf_glyph_widths(pdfont, 0, glyph, (gs_font *)font, pwidths, NULL);
720
if (pwidths->replaced_v) {
721
pdfont->u.simple.v[ch].x = pwidths->real_width.v.x - pwidths->Width.v.x;
722
pdfont->u.simple.v[ch].y = pwidths->real_width.v.y - pwidths->Width.v.y;
724
pdfont->u.simple.v[ch].x = pdfont->u.simple.v[ch].y = 0;
726
pdfont->Widths[ch] = pwidths->Width.w;
727
real_widths[ch] = pwidths->real_width.w;
729
if (font->WMode == 0 && !pwidths->replaced_v)
730
pdfont->Widths[ch] = pwidths->real_width.w;
733
if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
734
font->FontType == ft_GL2_stick_user_defined || font->FontType == ft_GL2_531) {
735
if (!(pdfont->used[ch >> 3] & 0x80 >> (ch & 7)))
736
return gs_error_undefined; /* The charproc was not accumulated. */
737
if (!pdev->charproc_just_accumulated &&
738
!(pdfont->u.simple.s.type3.cached[ch >> 3] & 0x80 >> (ch & 7))) {
739
/* The charproc uses setcharwidth.
740
Need to accumulate again to check for a glyph variation. */
741
return gs_error_undefined;
744
pwidths->Width.w = pdfont->Widths[ch];
745
pwidths->Width.v = pdfont->u.simple.v[ch];
746
if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
747
font->FontType == ft_GL2_stick_user_defined || font->FontType == ft_GL2_531) {
748
pwidths->real_width.w = real_widths[ch * 2];
749
pwidths->Width.xy.x = pwidths->Width.w;
750
pwidths->Width.xy.y = 0;
751
pwidths->real_width.xy.x = real_widths[ch * 2 + 0];
752
pwidths->real_width.xy.y = real_widths[ch * 2 + 1];
753
pwidths->replaced_v = 0;
754
} else if (font->WMode) {
755
pwidths->real_width.w = real_widths[ch];
756
pwidths->Width.xy.x = 0;
757
pwidths->Width.xy.y = pwidths->Width.w;
758
pwidths->real_width.xy.x = 0;
759
pwidths->real_width.xy.y = pwidths->real_width.w;
761
pwidths->real_width.w = real_widths[ch];
762
pwidths->Width.xy.x = pwidths->Width.w;
763
pwidths->Width.xy.y = 0;
764
pwidths->real_width.xy.x = pwidths->real_width.w;
765
pwidths->real_width.xy.y = 0;
773
* Convert glyph widths (.Width.xy and .real_widths.xy) from design to PDF text space
774
* Zero-out one of Width.xy.x/y per PDF Ref 5.3.3 "Text Space Details"
777
pdf_char_widths_to_uts(pdf_font_resource_t *pdfont /* may be NULL for non-Type3 */,
778
pdf_glyph_widths_t *pwidths)
780
if (pdfont && (pdfont->FontType == ft_user_defined ||
781
pdfont->FontType == ft_PCL_user_defined ||
782
pdfont->FontType == ft_GL2_stick_user_defined ||
783
pdfont->FontType == ft_GL2_531)) {
784
gs_matrix *pmat = &pdfont->u.simple.s.type3.FontMatrix;
786
pwidths->Width.xy.x *= pmat->xx; /* formula simplified based on wy in glyph space == 0 */
787
pwidths->Width.xy.y = 0.0; /* WMode == 0 for PDF Type 3 fonts */
788
gs_distance_transform(pwidths->real_width.xy.x, pwidths->real_width.xy.y, pmat, &pwidths->real_width.xy);
791
* For other font types:
792
* - PDF design->text space is a simple scaling by 0.001.
793
* - The Width.xy.x/y that should be zeroed-out per 5.3.3 "Text Space Details" is already 0.
795
pwidths->Width.xy.x /= 1000.0;
796
pwidths->Width.xy.y /= 1000.0;
797
pwidths->real_width.xy.x /= 1000.0;
798
pwidths->real_width.xy.y /= 1000.0;
803
* Compute the total text width (in user space). Return 1 if any
804
* character had real_width != Width, otherwise 0.
807
process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font,
808
pdf_text_process_state_t *ppts,
809
const gs_const_string *pstr, const gs_glyph *gdata,
810
gs_point *pdpt, int *accepted)
817
(pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
818
pte->text.space.s_char : -1);
819
int widths_differ = 0, code;
820
gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
821
pdf_font_resource_t *pdfont;
823
code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont, NULL, NULL, NULL, NULL);
826
for (i = 0, w.x = w.y = 0; i < pstr->size; ++i) {
827
pdf_glyph_widths_t cw; /* in PDF text space */
828
gs_char ch = pstr->data[i];
830
{ const gs_glyph *gdata_i = (gdata != NULL ? gdata + i : 0);
832
code = pdf_encode_string_element(pdev, (gs_font *)font, pdfont, ch, gdata_i);
836
if ((font->FontType == ft_user_defined ||
837
font->FontType == ft_PCL_user_defined ||
838
font->FontType == ft_GL2_stick_user_defined ||
839
font->FontType == ft_GL2_531) &&
840
(i > 0 || !pdev->charproc_just_accumulated) &&
841
!(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))){
842
code = gs_error_undefined;
845
if (font->FontType == ft_PCL_user_defined) {
846
/* Check the cache, if the glyph has been flushed, assume that
847
* it has been redefined, and do not use the current glyph.
848
* Additional code in pdf_text_process will also spot this
849
* condition and will not capture the glyph in this font.
851
/* Cache checking code copied from gxchar.c, show_proceed,
852
* case 0, 'plain char'.
854
gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
855
gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
856
pte->fstack.items[pte->fstack.depth].font);
857
int wmode = rfont->WMode;
858
gs_log2_scale_point log2_scale = {0,0};
859
gs_fixed_point subpix_origin = {0,0};
860
cached_fm_pair *pair;
862
code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pis), &log2_scale,
866
if (gx_lookup_cached_char(pfont, pair, ch, wmode,
867
1, &subpix_origin) == 0) {
868
/* Character is not in cache, must have been redefined. */
869
code = gs_error_undefined;
872
/* Character is in cache, go ahead and use it */
873
code = pdf_char_widths((gx_device_pdf *)pte->dev,
874
ppts->values.pdfont, ch, font, &cw);
877
/* Not a PCL bitmap font, we don't need to worry about redefined glyphs */
878
code = pdf_char_widths((gx_device_pdf *)pte->dev,
879
ppts->values.pdfont, ch, font, &cw);
887
pdf_char_widths_to_uts(pdfont, &cw);
888
w.x += cw.real_width.xy.x;
889
w.y += cw.real_width.xy.y;
890
if (cw.real_width.xy.x != cw.Width.xy.x ||
891
cw.real_width.xy.y != cw.Width.xy.y
894
if (pstr->data[i] == space_char)
898
gs_distance_transform(w.x * ppts->values.size, w.y * ppts->values.size,
899
&ppts->values.matrix, &dpt);
900
if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
901
int num_chars = *accepted;
904
gs_distance_transform(pte->text.delta_all.x, pte->text.delta_all.y,
905
&ctm_only(pte->pis), &tpt);
906
dpt.x += tpt.x * num_chars;
907
dpt.y += tpt.y * num_chars;
909
if (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
912
gs_distance_transform(pte->text.delta_space.x, pte->text.delta_space.y,
913
&ctm_only(pte->pis), &tpt);
914
dpt.x += tpt.x * num_spaces;
915
dpt.y += tpt.y * num_spaces;
919
return widths_differ;
922
#ifdef DEPRECATED_906
924
* Retrieve glyph origing shift for WMode = 1 in design units.
927
pdf_glyph_origin(pdf_font_resource_t *pdfont, int ch, int WMode, gs_point *p)
929
/* For CID fonts PDF viewers provide glyph origin shift automatically.
930
* Therefore we only need to do for non-CID fonts.
932
switch (pdfont->FontType) {
936
case ft_user_defined:
937
*p = pdfont->u.simple.v[ch];
947
* Emulate TEXT_ADD_TO_ALL_WIDTHS and/or TEXT_ADD_TO_SPACE_WIDTH,
948
* and implement TEXT_REPLACE_WIDTHS if requested.
949
* Uses and updates ppts->values.matrix; uses ppts->values.pdfont.
951
* Destroys the text parameters in *pte.
952
* The caller must restore them.
955
process_text_modify_width(pdf_text_enum_t *pte, gs_font *font,
956
pdf_text_process_state_t *ppts,
957
const gs_const_string *pstr,
958
gs_point *pdpt, const gs_glyph *gdata, bool composite)
960
gx_device_pdf *const pdev = (gx_device_pdf *)pte->dev;
962
(pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
963
pte->text.space.s_char : -1);
964
gs_point start, total;
965
pdf_font_resource_t *pdfont3 = NULL;
968
if (font->FontType == ft_user_defined ||
969
font->FontType == ft_PCL_user_defined ||
970
font->FontType == ft_GL2_stick_user_defined ||
971
font->FontType == ft_GL2_531) {
972
code = pdf_attached_font_resource(pdev, font, &pdfont3, NULL, NULL, NULL, NULL);
977
pte->text.data.bytes = pstr->data;
978
pte->text.size = pstr->size;
980
pte->text.operation &= ~TEXT_FROM_ANY;
981
pte->text.operation |= TEXT_FROM_STRING;
982
start.x = ppts->values.matrix.tx;
983
start.y = ppts->values.matrix.ty;
984
total.x = total.y = 0; /* user space */
986
* Note that character widths are in design space, but text.delta_*
987
* values and the width value returned in *pdpt are in user space,
988
* and the width values for pdf_append_chars are in device space.
991
pdf_glyph_widths_t cw; /* design space, then converted to PDF text space */
992
gs_point did, wanted, tpt; /* user space */
993
gs_point v = {0, 0}; /* design space */
996
int index = pte->index;
997
gs_text_enum_t pte1 = *(gs_text_enum_t *)pte;
999
bool use_cached_v = true;
1000
byte composite_type3_text[1];
1002
code = pte1.orig_font->procs.next_char_glyph(&pte1, &chr, &glyph);
1003
if (code == 2) { /* end of string */
1004
gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true);
1009
if (composite) { /* from process_cmap_text */
1010
gs_font *subfont = pte1.fstack.items[pte1.fstack.depth].font;
1012
if (subfont->FontType == ft_user_defined) {
1013
pdf_font_resource_t *pdfont;
1015
FontType = subfont->FontType;
1016
code = pdf_attached_font_resource(pdev, subfont,
1017
&pdfont, NULL, NULL, NULL, NULL);
1020
chr = pdf_find_glyph(pdfont, glyph);
1021
composite_type3_text[0] = (byte)chr;
1022
code = pdf_char_widths((gx_device_pdf *)pte->dev,
1023
ppts->values.pdfont, chr, (gs_font_base *)subfont,
1026
pdf_font_resource_t *pdsubf = ppts->values.pdfont->u.type0.DescendantFont;
1028
FontType = pdsubf->FontType;
1029
code = pdf_glyph_widths(pdsubf, font->WMode, glyph, subfont, &cw,
1030
pte->cdevproc_callout ? pte->cdevproc_result : NULL);
1032
} else {/* must be a base font */
1033
const gs_glyph *gdata_i = (gdata != NULL ? gdata + pte->index : 0);
1035
/* gdata is NULL when composite == true, or the text isn't a single byte. */
1036
code = pdf_encode_string_element(pdev, font, ppts->values.pdfont, chr, gdata_i);
1037
FontType = font->FontType;
1039
if (chr == GS_NO_CHAR && glyph != GS_NO_GLYPH) {
1040
/* glyphshow, we have no char code. Bug 686988.*/
1041
code = pdf_glyph_widths(ppts->values.pdfont, font->WMode, glyph, font, &cw, NULL);
1042
use_cached_v = false; /* Since we have no chr and don't call pdf_char_widths. */
1044
code = pdf_char_widths((gx_device_pdf *)pte->dev,
1045
ppts->values.pdfont, chr, (gs_font_base *)font,
1047
if (code == 0 && font->FontType == ft_PCL_user_defined) {
1048
/* Check the cache, if the glyph has been flushed, assume that
1049
* it has been redefined, and do not use the current glyph.
1050
* Additional code in pdf_text_process will also spot this
1051
* condition and will not capture the glyph in this font.
1053
/* Cache checking code copied from gxchar.c, show_proceed,
1054
* case 0, 'plain char'.
1056
gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
1057
gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
1058
pte->fstack.items[pte->fstack.depth].font);
1059
int wmode = rfont->WMode;
1060
gs_log2_scale_point log2_scale = {0,0};
1061
gs_fixed_point subpix_origin = {0,0};
1062
cached_fm_pair *pair;
1064
code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pis), &log2_scale,
1068
if (gx_lookup_cached_char(pfont, pair, chr, wmode,
1069
1, &subpix_origin) == 0) {
1070
/* Character is not in cache, must have been redefined. */
1071
code = gs_error_undefined;
1082
gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true);
1083
if (composite || !use_cached_v) {
1084
if (cw.replaced_v) {
1085
v.x = cw.real_width.v.x - cw.Width.v.x;
1086
v.y = cw.real_width.v.y - cw.Width.v.y;
1089
v = ppts->values.pdfont->u.simple.v[chr];
1091
/* With WMode 1 v-vector is (WMode 1 origin) - (WMode 0 origin).
1092
The glyph shifts in the opposite direction. */
1096
/* With WMode 0 v-vector is (Metrics sb) - (native sb).
1097
The glyph shifts in same direction. */
1099
/* pdf_glyph_origin is not longer used. */
1100
if (v.x != 0 || v.y != 0) {
1101
gs_point glyph_origin_shift;
1104
if (FontType == ft_TrueType || FontType == ft_CID_TrueType)
1105
scale0 = (float)0.001;
1108
glyph_origin_shift.x = v.x * scale0;
1109
glyph_origin_shift.y = v.y * scale0;
1111
gs_font *subfont = pte->fstack.items[pte->fstack.depth].font;
1113
gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1114
&subfont->FontMatrix, &glyph_origin_shift);
1116
gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1117
&font->FontMatrix, &glyph_origin_shift);
1118
gs_distance_transform(glyph_origin_shift.x, glyph_origin_shift.y,
1119
&ctm_only(pte->pis), &glyph_origin_shift);
1120
if (glyph_origin_shift.x != 0 || glyph_origin_shift.y != 0) {
1121
ppts->values.matrix.tx = start.x + total.x + glyph_origin_shift.x;
1122
ppts->values.matrix.ty = start.y + total.y + glyph_origin_shift.y;
1123
code = pdf_set_text_state_values(pdev, &ppts->values);
1128
pdf_char_widths_to_uts(pdfont3, &cw); /* convert design->text space */
1129
if (pte->text.operation & (TEXT_DO_DRAW | TEXT_RENDER_MODE_3)) {
1130
gs_distance_transform(cw.Width.xy.x * ppts->values.size,
1131
cw.Width.xy.y * ppts->values.size,
1132
&ppts->values.matrix, &did);
1133
gs_distance_transform((font->WMode ? 0 : ppts->values.character_spacing),
1134
(font->WMode ? ppts->values.character_spacing : 0),
1135
&ppts->values.matrix, &tpt);
1138
if (chr == space_char) {
1139
gs_distance_transform((font->WMode ? 0 : ppts->values.word_spacing),
1140
(font->WMode ? ppts->values.word_spacing : 0),
1141
&ppts->values.matrix, &tpt);
1145
if (composite && FontType == ft_user_defined)
1146
code = pdf_append_chars(pdev, composite_type3_text, 1, did.x, did.y, composite);
1148
code = pdf_append_chars(pdev, pstr->data + index, pte->index - index, did.x, did.y, composite);
1153
if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
1156
code = gs_text_replaced_width(&pte->text, pte->xy_index++, &dpt);
1158
return_error(gs_error_unregistered);
1159
gs_distance_transform(dpt.x, dpt.y, &ctm_only(pte->pis), &wanted);
1161
gs_distance_transform(cw.real_width.xy.x * ppts->values.size,
1162
cw.real_width.xy.y * ppts->values.size,
1163
&ppts->values.matrix, &wanted);
1164
if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
1165
gs_distance_transform(pte->text.delta_all.x,
1166
pte->text.delta_all.y,
1167
&ctm_only(pte->pis), &tpt);
1171
if (chr == space_char && pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
1172
gs_distance_transform(pte->text.delta_space.x,
1173
pte->text.delta_space.y,
1174
&ctm_only(pte->pis), &tpt);
1179
total.x += wanted.x;
1180
total.y += wanted.y;
1181
if (wanted.x != did.x || wanted.y != did.y) {
1182
ppts->values.matrix.tx = start.x + total.x;
1183
ppts->values.matrix.ty = start.y + total.y;
1184
code = pdf_set_text_state_values(pdev, &ppts->values);
1188
pdev->charproc_just_accumulated = false;
1195
* Get character code from a glyph code.
1196
* An usage of this function is very undesirable,
1197
* because a glyph may be unlisted in Encoding.
1200
pdf_encode_glyph(gs_font_base *bfont, gs_glyph glyph0,
1201
byte *buf, int buf_size, int *char_code_length)
1205
*char_code_length = 1;
1206
if (*char_code_length > buf_size)
1207
return_error(gs_error_rangecheck); /* Must not happen. */
1208
for (c = 0; c < 255; c++) {
1209
gs_glyph glyph1 = bfont->procs.encode_char((gs_font *)bfont, c,
1211
if (glyph1 == glyph0) {
1216
return_error(gs_error_rangecheck); /* Can't encode. */
1219
/* ---------------- Type 1 or TrueType font ---------------- */
1222
* Process a text string in a simple font.
1225
process_plain_text(gs_text_enum_t *pte, void *vbuf, uint bsize)
1227
byte *const buf = vbuf;
1229
uint operation = pte->text.operation;
1230
pdf_text_enum_t *penum = (pdf_text_enum_t *)pte;
1233
pdf_text_process_state_t text_state;
1234
const gs_glyph *gdata = NULL;
1236
if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) {
1237
count = pte->text.size - pte->index;
1239
return_error(gs_error_unregistered); /* Must not happen. */
1240
memcpy(buf, (const byte *)pte->text.data.bytes + pte->index, count);
1241
} else if (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR)) {
1242
/* Check that all chars fit in a single byte. */
1243
const gs_char *cdata;
1246
if (operation & TEXT_FROM_CHARS) {
1247
cdata = pte->text.data.chars;
1248
count = (pte->text.size - pte->index);
1250
cdata = &pte->text.data.d_char;
1253
if (bsize < count * sizeof(gs_char))
1254
return_error(gs_error_unregistered); /* Must not happen. */
1255
for (i = 0; i < count; ++i) {
1256
gs_char chr = cdata[pte->index + i];
1259
return_error(gs_error_rangecheck);
1262
} else if (operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH)) {
1264
* Since PDF has no analogue of 'glyphshow',
1265
* we try to encode glyphs with the current
1266
* font's encoding. If the current font has no encoding,
1267
* or the encoding doesn't contain necessary glyphs,
1268
* the text will be represented with a Type 3 font with
1269
* bitmaps or outlines.
1271
* When we fail with encoding (136-01.ps is an example),
1272
* we could locate a PDF font resource or create a new one
1273
* with same outlines and an appropriate encoding.
1274
* Also we could change .notdef entries in the
1275
* copied font (assuming that document designer didn't use
1276
* .notdef for a meanful printing).
1277
* fixme: Not implemented yet.
1279
gs_font *font = pte->current_font;
1283
if (operation & TEXT_FROM_GLYPHS) {
1284
gdata = pte->text.data.glyphs;
1285
size = pte->text.size - pte->index;
1287
gdata = &pte->text.data.d_glyph;
1290
if (!pdf_is_simple_font(font))
1291
return_error(gs_error_unregistered); /* Must not happen. */
1293
for (i = 0; i < size; ++i) {
1294
gs_glyph glyph = gdata[pte->index + i];
1295
int char_code_length;
1297
code = pdf_encode_glyph((gs_font_base *)font, glyph,
1298
buf + count, size - count, &char_code_length);
1301
count += char_code_length;
1302
if (operation & TEXT_INTERVENE)
1303
break; /* Just do one character. */
1306
pdf_font_resource_t *pdfont;
1310
code = pdf_obtain_font_resource_unencoded(penum, &str, &pdfont, gdata);
1313
* pdf_text_process will fall back
1314
* to default implementation.
1320
/* So far we will use TEXT_FROM_STRING instead
1321
TEXT_FROM_*_GLYPH*. Since we used a single
1322
byte encoding, the character index appears invariant
1323
during this substitution.
1326
return_error(gs_error_rangecheck);
1328
if (count > 1 && (operation & TEXT_INTERVENE)) {
1329
/* Just do one character. */
1331
code = pdf_process_string_aux(penum, &str, gdata, NULL, &text_state);
1333
pte->returned.current_char = buf[0];
1334
code = TEXT_PROCESS_INTERVENE;
1338
code = pdf_process_string_aux(penum, &str, gdata, NULL, &text_state);