xref: /plan9-contrib/sys/src/cmd/gs/src/gdevpdft.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 /* Copyright (C) 1996, 2000 Aladdin Enterprises.  All rights reserved.
2 
3    This file is part of Aladdin Ghostscript.
4 
5    Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
6    or distributor accepts any responsibility for the consequences of using it,
7    or for whether it serves any particular purpose or works at all, unless he
8    or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
9    License (the "License") for full details.
10 
11    Every copy of Aladdin Ghostscript must include a copy of the License,
12    normally in a plain ASCII text file named PUBLIC.  The License grants you
13    the right to copy, modify and redistribute Aladdin Ghostscript, but only
14    under certain conditions described in the License.  Among other things, the
15    License requires that the copyright notice and this notice be preserved on
16    all copies.
17  */
18 
19 /*$Id: gdevpdft.c,v 1.3 2000/03/16 01:21:24 lpd Exp $ */
20 /* Text handling for PDF-writing driver. */
21 #include "math_.h"
22 #include "memory_.h"
23 #include "string_.h"
24 #include "gx.h"
25 #include "gserrors.h"
26 #include "gsmatrix.h"
27 #include "gsutil.h"		/* for bytes_compare */
28 #include "gxfixed.h"		/* for gxfcache.h */
29 #include "gxfont.h"
30 #include "gxfont0.h"
31 #include "gxfont1.h"
32 #include "gxfont42.h"
33 #include "gxfcache.h"		/* for orig_fonts list */
34 #include "gxpath.h"		/* for getting current point */
35 #include "gdevpdfx.h"
36 #include "gdevpdff.h"
37 #include "scommon.h"
38 
39 /*
40  * The PDF documentation does a pretty shoddy job of specifying use of fonts
41  * beyond the base 14, and on top of that, Acrobat Reader has some serious
42  * bugs.  Specifically, Acrobat Reader 3's Print function has a bug that
43  * make re-encoded characters print as blank if the font is substituted (not
44  * embedded or one of the base 14).
45  *
46  * We do have to handle re-encoded Type 1 fonts, because TeX output makes
47  * constant use of them.  We have several alternatives for how to handle
48  * characters whose encoding doesn't match their encoding in the base font's
49  * built-in encoding.  If a character's glyph doesn't match the character's
50  * glyph in the encoding built up so far, we check if the font has that
51  * glyph at all; if not, we fall back to a bitmap.  Otherwise, we use one or
52  * both of the following algorithms:
53  *
54  *      1. If this is the first time a character at this position has been
55  *      seen, assign its glyph to that position in the encoding.
56  *      We do this step if the device parameter ReAssignCharacters is true.
57  *      (This is the default.)
58  *
59  *      2. If the glyph is present in the encoding at some other position,
60  *      substitute that position for the character; otherwise, assign the
61  *      glyph to an unoccupied (.notdef) position.
62  *      We do this step if the device parameter ReEncodeCharacters is true.
63  *      (This is the default.)
64  *
65  *      3. Finally, fall back to using a bitmap.
66  *
67  * If it is essential that all strings in the output contain exactly the
68  * same character codes as the input, set ReEncodeCharacters to false.  If
69  * it is important that strings be searchable, but some non-searchable
70  * strings can be tolerated, the defaults are appropriate.  If searchability
71  * is not important, set ReAssignCharacters to false.
72  *
73  * Since the chars_used bit vector keeps track of characters by their
74  * position in the Encoding, not by their glyph identifier, it can't record
75  * use of unencoded characters.  Therefore, if we ever use an unencoded
76  * character in an embedded font, we force writing the entire font rather
77  * than a subset.  This is inelegant but (for the moment) too awkward to
78  * fix.
79  *
80  * Because of the AR3 printing bug, if CompatibilityLevel <= 1.2, for
81  * non-embedded non-base fonts, no substitutions or re-encodings are allowed.
82  */
83 
84 /* Forward references */
85 private int pdf_set_font_and_size(P3(gx_device_pdf * pdev, pdf_font_t * font,
86 				     floatp size));
87 private int pdf_set_text_matrix(P2(gx_device_pdf * pdev,
88 				   const gs_matrix * pmat));
89 private int pdf_append_chars(P3(gx_device_pdf * pdev, const byte * str,
90 				uint size));
91 
92 /* Define the text enumerator. */
93 typedef struct pdf_text_enum_s {
94     gs_text_enum_common;
95     gs_text_enum_t *pte_default;
96     gs_fixed_point origin;
97 } pdf_text_enum_t;
98 extern_st(st_gs_text_enum);
99 gs_private_st_suffix_add1(st_pdf_text_enum, pdf_text_enum_t, "pdf_text_enum_t",
100   pdf_text_enum_enum_ptrs, pdf_text_enum_reloc_ptrs, st_gs_text_enum,
101   pte_default);
102 
103 /*
104  * Define quantities derived from the current font and CTM, used within
105  * the text processing loop.
106  */
107 typedef struct pdf_text_process_state_s {
108     float chars;		/* scaled character spacing (Tc) */
109     float words;		/* scaled word spacing (Tw) */
110     float size;			/* font size for Tf */
111     gs_matrix text_matrix;	/* normalized FontMatrix * CTM for Tm */
112     pdf_font_t *pdfont;
113 } pdf_text_process_state_t;
114 
115 /* Define the auxiliary procedures for text processing. */
116 private int
117 pdf_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
118 {
119     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
120 
121     if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY)
122 	return_error(gs_error_rangecheck);
123     if (penum->pte_default) {
124 	int code = gs_text_resync(penum->pte_default, pfrom);
125 
126 	if (code < 0)
127 	    return code;
128     }
129     pte->text = pfrom->text;
130     gs_text_enum_copy_dynamic(pte, pfrom, false);
131     return 0;
132 }
133 private bool
134 pdf_text_is_width_only(const gs_text_enum_t *pte)
135 {
136     const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
137 
138     if (penum->pte_default)
139 	return gs_text_is_width_only(penum->pte_default);
140     return false;
141 }
142 private int
143 pdf_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth)
144 {
145     const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
146 
147     if (penum->pte_default)
148 	return gs_text_current_width(penum->pte_default, pwidth);
149     return_error(gs_error_rangecheck); /* can't happen */
150 }
151 private int
152 pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
153 		   gs_text_cache_control_t control)
154 {
155     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
156 
157     if (penum->pte_default)
158 	return gs_text_set_cache(penum->pte_default, pw, control);
159     return_error(gs_error_rangecheck); /* can't happen */
160 }
161 private int
162 pdf_text_retry(gs_text_enum_t *pte)
163 {
164     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
165 
166     if (penum->pte_default)
167 	return gs_text_retry(penum->pte_default);
168     return_error(gs_error_rangecheck); /* can't happen */
169 }
170 private void
171 pdf_text_release(gs_text_enum_t *pte, client_name_t cname)
172 {
173     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
174 
175     if (penum->pte_default) {
176 	gs_text_release(penum->pte_default, cname);
177 	penum->pte_default = 0;
178     }
179     gx_default_text_release(pte, cname);
180 }
181 
182 /* Begin processing text. */
183 private text_enum_proc_process(pdf_text_process);
184 private const gs_text_enum_procs_t pdf_text_procs = {
185     pdf_text_resync, pdf_text_process,
186     pdf_text_is_width_only, pdf_text_current_width,
187     pdf_text_set_cache, pdf_text_retry,
188     pdf_text_release
189 };
190 int
191 gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis,
192 		    const gs_text_params_t *text, gs_font * font,
193 		    gx_path * path, const gx_device_color * pdcolor,
194 		    const gx_clip_path * pcpath,
195 		    gs_memory_t * mem, gs_text_enum_t ** ppte)
196 {
197     gx_device_pdf *const pdev = (gx_device_pdf *)dev;
198     pdf_text_enum_t *penum;
199     gs_fixed_point cpt;
200     int code;
201 
202     if ((text->operation &
203 	 ~(TEXT_FROM_STRING | TEXT_FROM_BYTES |
204 	   TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH |
205 	   TEXT_REPLACE_WIDTHS |
206 	   TEXT_DO_DRAW | TEXT_RETURN_WIDTH)) != 0 ||
207 	!gx_dc_is_pure(pdcolor) ||
208 	gx_path_current_point(path, &cpt) < 0
209 	)
210 	return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
211 				     pcpath, mem, ppte);
212 
213     /* Set the clipping path and color. */
214 
215     if (pdf_must_put_clip_path(pdev, pcpath)) {
216 	int code = pdf_open_page(pdev, PDF_IN_STREAM);
217 
218 	if (code < 0)
219 	    return code;
220 	pdf_put_clip_path(pdev, pcpath);
221     }
222     pdf_set_color(pdev, gx_dc_pure_color(pdcolor), &pdev->fill_color,
223 		  &psdf_set_fill_color_commands);
224 
225     /* Allocate and initialize the enumerator. */
226 
227     rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem,
228 		      return_error(gs_error_VMerror), "gdev_pdf_text_begin");
229     penum->rc.free = rc_free_text_enum;
230     penum->pte_default = 0;
231     code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs,
232 			     dev, pis, text, font, path, pdcolor, pcpath, mem);
233     if (code < 0) {
234 	gs_free_object(mem, penum, "gdev_pdf_text_begin");
235 	return code;
236     }
237 
238     if (text->operation & TEXT_RETURN_WIDTH)
239 	gx_path_current_point(path, &penum->origin);
240     *ppte = (gs_text_enum_t *)penum;
241 
242     return 0;
243 }
244 
245 /*
246  * Create a new pdf_font for a gs_font.  This is a separate procedure only
247  * for readability: it is only called from one place in
248  * pdf_update_text_state.
249  */
250 private int
251 create_pdf_font(gx_device_pdf *pdev, gs_font *font, const gs_matrix *pomat,
252 		pdf_font_t **pppf)
253 {
254     int index = -1;
255     pdf_font_t ftemp;
256     int BaseEncoding = ENCODING_INDEX_UNKNOWN;
257     int same = 0, base_same = 0;
258     pdf_font_embed_t embed =
259 	pdf_font_embed_status(pdev, font, &index, &same);
260     bool have_widths = false;
261     bool is_standard = false;
262     long ffid = 0;
263     pdf_font_descriptor_t *pfd;
264     gs_font *base_font = font;
265     gs_font *below;
266     pdf_font_descriptor_t fdesc;
267     pdf_font_t *ppf;
268     int code;
269 #define BASE_UID(fnt) (&((const gs_font_base *)(fnt))->UID)
270 
271     /* Find the "lowest" base font that has the same outlines. */
272     while ((below = base_font->base) != base_font &&
273 	   base_font->procs.same_font(base_font, below,
274 				      FONT_SAME_OUTLINES))
275 	base_font = below;
276  set_base:
277     if (base_font == font)
278 	base_same = same;
279     else
280 	embed = pdf_font_embed_status(pdev, base_font, &index, &base_same);
281     if (embed == FONT_EMBED_STANDARD && pdev->std_fonts[index].font != 0) {
282 	/* Use the standard font as the base font. */
283 	base_font = pdev->std_fonts[index].font;
284 	is_standard = true;
285     } else if (embed == FONT_EMBED_YES &&
286 	       base_font->FontType != ft_composite &&
287 	       uid_is_valid(BASE_UID(base_font)) &&
288 	       !base_font->is_resource
289 	       ) {
290 	/*
291 	 * The base font has a UID, but it isn't a resource.  Look for a
292 	 * resource with the same UID, in the hope that that will be
293 	 * longer-lived.
294 	 */
295 	gs_font *orig = base_font->dir->orig_fonts;
296 
297 	for (; orig; orig = orig->next)
298 	    if (orig != base_font && orig->FontType == base_font->FontType &&
299 		orig->is_resource &&
300 		uid_equal(BASE_UID(base_font), BASE_UID(orig))
301 		) {
302 		/* Use this as the base font instead. */
303 		base_font = orig;
304 		/*
305 		 * Recompute the embedding status of the base font.  This
306 		 * can't lead to a loop, because base_font->is_resource is
307 		 * now known to be true.
308 		 */
309 		goto set_base;
310 	    }
311     }
312 
313     /* See if we already have a descriptor for this base font. */
314     pfd = (pdf_font_descriptor_t *)
315 	pdf_find_resource_by_gs_id(pdev, resourceFontDescriptor,
316 				   base_font->id);
317     if (pfd != 0 && pfd->base_font != base_font)
318 	pfd = 0;
319 
320     /* Create an appropriate font and descriptor. */
321 
322     switch (embed) {
323     case FONT_EMBED_YES:
324 	/*
325 	 * HACK: Acrobat Reader 3 has a bug that makes cmap formats 4
326 	 * and 6 not work in embedded TrueType fonts.  Consequently, it
327 	 * can only handle embedded TrueType fonts if all the glyphs
328 	 * referenced by the Encoding have numbers 0-255.  Check for
329 	 * this now.
330 	 */
331 	if (font->FontType == ft_TrueType &&
332 	    pdev->CompatibilityLevel <= 1.2
333 	    ) {
334 	    int i;
335 
336 	    for (i = 0; i <= 0xff; ++i) {
337 		gs_glyph glyph =
338 		    font->procs.encode_char(font, (gs_char)i,
339 					    GLYPH_SPACE_INDEX);
340 
341 		if (glyph == gs_no_glyph ||
342 		    (glyph >= gs_min_cid_glyph &&
343 		     glyph <= gs_min_cid_glyph + 0xff)
344 		    )
345 		    continue;
346 		/* Can't embed, punt. */
347 		return_error(gs_error_rangecheck);
348 	    }
349 	}
350 	/*
351 	 * Acrobat Reader doesn't accept embedded Multiple Master
352 	 * instances, and we haven't been able to figure out why.
353 	 */
354 	if (font->FontType == ft_encrypted &&
355 	    ((const gs_font_type1 *)font)->data.WeightVector.count > 0)
356 	    return_error(gs_error_rangecheck);
357 	code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
358 	if (code < 0)
359 	    return code;
360 	ffid = pdf_obj_ref(pdev);
361 	goto wf;
362     case FONT_EMBED_NO:
363 	/*
364 	 * Per the PDF 1.3 documentation, there are only 3 BaseEncoding
365 	 * values allowed for non-embedded fonts.  Pick one here.
366 	 */
367 	BaseEncoding =
368 	    ((const gs_font_base *)base_font)->nearest_encoding_index;
369 	switch (BaseEncoding) {
370 	default:
371 	    BaseEncoding = ENCODING_INDEX_WINANSI;
372 	case ENCODING_INDEX_WINANSI:
373 	case ENCODING_INDEX_MACROMAN:
374 	case ENCODING_INDEX_MACEXPERT:
375 	    break;
376 	}
377 	code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
378 	if (code < 0)
379 	    return code;
380     wf:
381 	/* The font isn't standard: make sure we write the Widths. */
382 	same &= ~FONT_SAME_METRICS;
383 	/* falls through */
384     case FONT_EMBED_STANDARD:
385 	if (~same & (FONT_SAME_METRICS | FONT_SAME_ENCODING)) {
386 	    /*
387 	     * Before allocating the font resource, check that we can
388 	     * get all the widths.
389 	     */
390 	    int i;
391 
392 	    memset(&ftemp, 0, sizeof(ftemp));
393 	    for (i = 0; i <= 255; ++i) {
394 		code = pdf_char_width(&ftemp, i, font, NULL);
395 		if (code < 0 && code != gs_error_undefined)
396 		    return code;
397 	    }
398 	    have_widths = true;
399 	}
400 	if (pfd) {
401 	    code = pdf_alloc_font(pdev, font->id, &ppf, gs_no_id);
402 	    if (code < 0)
403 		return code;
404 	    if_debug4('_',
405 		      "[_]created pdf_font_t 0x%lx, id %ld, FontDescriptor 0x%lx, id %ld (old)\n",
406 		      (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf),
407 		      (ulong)pfd, pdf_resource_id((pdf_resource_t *)pfd));
408 	    ppf->FontDescriptor = pfd;
409 	} else {
410 	    int name_index = index;
411 
412 	    code = pdf_alloc_font(pdev, font->id, &ppf, base_font->id);
413 	    if (code < 0)
414 		return code;
415 	    pfd = ppf->FontDescriptor;
416 	    if_debug4('_',
417 		      "[_]created pdf_font_t 0x%lx, id %ld, FontDescriptor 0x%lx, id %ld (new)\n",
418 		      (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf),
419 		      (ulong)pfd, pdf_resource_id((pdf_resource_t *)pfd));
420 	    if (index < 0) {
421 		int ignore_same;
422 
423 		memcpy(pfd->FontName.chars, base_font->font_name.chars,
424 		       base_font->font_name.size);
425 		pfd->FontName.size = base_font->font_name.size;
426 		pfd->values = fdesc.values;
427 		pfd->FontFile_id = ffid;
428 		pfd->base_font = base_font;
429 		pfd->orig_matrix = *pomat;
430 		/* Don't allow non-standard fonts with standard names. */
431 		pdf_font_embed_status(pdev, base_font, &name_index,
432 				      &ignore_same);
433 	    } else {
434 		/* Use the standard name. */
435 		const pdf_standard_font_t *ppsf = &pdf_standard_fonts[index];
436 		const char *fnchars = ppsf->fname;
437 		uint fnsize = strlen(fnchars);
438 
439 		memcpy(pfd->FontName.chars, fnchars, fnsize);
440 		pfd->FontName.size = fnsize;
441 	    }
442 	    if (!is_standard) {
443 		code = pdf_adjust_font_name(pdev, pfd, name_index >= 0);
444 		if (code < 0)
445 		    return code;
446 	    }
447 	}
448 	ppf->FontType = font->FontType;
449 	ppf->index = index;
450 	switch (font->FontType) {
451 	case ft_encrypted:
452 	case ft_encrypted2:
453 	    ppf->is_MM_instance =
454 		((const gs_font_type1 *)font)->data.WeightVector.count > 0;
455 	default:
456 	    DO_NOTHING;
457 	}
458 	ppf->BaseEncoding = BaseEncoding;
459 	ppf->fname = pfd->FontName;
460 	ppf->font = font;
461 	if (~same & FONT_SAME_METRICS) {
462 	    /*
463 	     * Contrary to the PDF 1.3 documentation, FirstChar and
464 	     * LastChar are *not* simply a way to strip off initial and
465 	     * final entries in the Widths array that are equal to
466 	     * MissingWidth.  Acrobat Reader assumes that characters
467 	     * with codes less than FirstChar or greater than LastChar
468 	     * are undefined, without bothering to consult the Encoding.
469 	     * Therefore, the implicit value of MissingWidth is pretty
470 	     * useless, because there must be explicit Width entries for
471 	     * every character in the font that is ever used.
472 	     * Furthermore, if there are several subsets of the same
473 	     * font in a document, it appears to be random as to which
474 	     * one Acrobat Reader uses to decide what the FirstChar and
475 	     * LastChar values are.  Therefore, we must write the Widths
476 	     * array for the entire font even for subsets.
477 	     */
478 	    ppf->write_Widths = true;
479 	    pdf_find_char_range(font, &ppf->FirstChar, &ppf->LastChar);
480 	}
481 	if (have_widths) {
482 	    /*
483 	     * C's bizarre coercion rules make us use memcpy here
484 	     * rather than direct assignments, even though sizeof()
485 	     * gives the correct value....
486 	     */
487 	    memcpy(ppf->Widths, ftemp.Widths, sizeof(ppf->Widths));
488 	    memcpy(ppf->widths_known, ftemp.widths_known,
489 		   sizeof(ppf->widths_known));
490 	}
491 	code = pdf_register_font(pdev, font, ppf);
492     }
493 
494     *pppf = ppf;
495     return code;
496 }
497 
498 /*
499  * Compute the cached values in the text state from the text parameters,
500  * current_font, and pis->ctm.
501  */
502 private int
503 pdf_update_text_state(pdf_text_process_state_t *ppts,
504 		      const pdf_text_enum_t *penum, const gs_matrix *pfmat)
505 {
506     gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
507     gs_font *font = penum->current_font;
508     pdf_font_t *ppf;
509     gs_fixed_point cpt;
510     gs_matrix orig_matrix, smat, tmat;
511     double
512 	sx = pdev->HWResolution[0] / 72.0,
513 	sy = pdev->HWResolution[1] / 72.0;
514     float chars, words, size;
515     int code = gx_path_current_point(penum->path, &cpt);
516 
517     if (code < 0)
518 	return code;
519 
520     /* PDF always uses 1000 units per em for font metrics. */
521     switch (font->FontType) {
522     case ft_TrueType:
523 	/*
524 	 * ****** HACK ALERT ******
525 	 *
526 	 * The code above that calls pdf_find_char_range does so the first
527 	 * time the font is used.  This causes an incorrect (too small)
528 	 * Widths array to be written if the font is downloaded
529 	 * incrementally.  In practice, this appears only to be a problem
530 	 * for TrueType fonts written by certain Windows drivers
531 	 * (including AdobePS5 for Windows NT).  Fortunately, it is easy
532 	 * to determine whether the font is an incremental one: this is
533 	 * the case iff the font doesn't have glyf and loca entries.
534 	 * In this case, we punt and treat the font as bitmaps.
535 	 */
536 	if (((const gs_font_type42 *)font)->data.glyf == 0)
537 	    return_error(gs_error_rangecheck); /* incremental */
538 	/* The TrueType FontMatrix is 1 unit per em, which is what we want. */
539 	gs_make_identity(&orig_matrix);
540 	break;
541     case ft_encrypted:
542     case ft_encrypted2:
543 	gs_make_scaling(0.001, 0.001, &orig_matrix);
544 	break;
545     default:
546 	return_error(gs_error_rangecheck);
547     }
548     DISCARD(pdf_find_orig_font(pdev, font, &orig_matrix));
549 
550     /* Compute the scaling matrix and combined matrix. */
551 
552     gs_matrix_invert(&orig_matrix, &smat);
553     gs_matrix_multiply(&smat, pfmat, &smat);
554     tmat = ctm_only(penum->pis);
555     tmat.tx = tmat.ty = 0;
556     gs_matrix_multiply(&smat, &tmat, &tmat);
557 
558     /* Try to find a reasonable size value.  This isn't necessary, */
559     /* but it's worth a little effort. */
560 
561     size = fabs(tmat.yy) / sy;
562     if (size < 0.01)
563 	size = fabs(tmat.xx) / sx;
564     if (size < 0.01)
565 	size = 1;
566 
567     /* Check for spacing parameters we can handle, and transform them. */
568 
569     if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
570 	gs_point pt;
571 
572 	gs_distance_transform_inverse(penum->text.delta_all.x,
573 				      penum->text.delta_all.y,
574 				      &smat, &pt);
575 	if (pt.y != 0)
576 	    return_error(gs_error_rangecheck);
577 	chars = pt.x * size;
578     } else
579 	chars = 0.0;
580 
581     if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
582 	gs_point pt;
583 
584 	gs_distance_transform_inverse(penum->text.delta_space.x,
585 				      penum->text.delta_space.y,
586 				      &smat, &pt);
587 	if (pt.y != 0 || penum->text.space.s_char != 32)
588 	    return_error(gs_error_rangecheck);
589 	words = pt.x * size;
590     } else
591 	words = 0.0;
592 
593     /* Find or create the font resource. */
594 
595     ppf = (pdf_font_t *)
596 	pdf_find_resource_by_gs_id(pdev, resourceFont, font->id);
597     /* Check for the possibility that the base font has been freed. */
598     if (ppf && ppf->FontDescriptor->written)
599 	ppf = 0;
600     if (ppf == 0 || ppf->font == 0) {
601 	code = create_pdf_font(pdev, font, &orig_matrix, &ppf);
602 	if (code < 0)
603 	    return code;
604     }
605 
606     /* Store the updated values. */
607 
608     tmat.xx /= size;
609     tmat.xy /= size;
610     tmat.yx /= size;
611     tmat.yy /= size;
612     tmat.tx += fixed2float(cpt.x);
613     tmat.ty += fixed2float(cpt.y);
614 
615     ppts->chars = chars;
616     ppts->words = words;
617     ppts->size = size;
618     ppts->text_matrix = tmat;
619     ppts->pdfont = ppf;
620 
621     return 0;
622 }
623 
624 /* Check whether a glyph exists in a (pseudo-)encoding. */
625 private bool
626 encoding_has_glyph(gs_font_base *bfont, gs_glyph font_glyph,
627 		   gs_encoding_index_t index)
628 {
629     int ch;
630     gs_glyph glyph;
631 
632     for (ch = 0;
633 	 (glyph = bfont->procs.callbacks.known_encode((gs_char)ch, index)) !=
634 	     gs_no_glyph;
635 	 ++ch)
636 	if (glyph == font_glyph)
637 	    return true;
638     return false;
639 }
640 
641 /*
642  * For a given character, check whether the encoding of bfont (the current
643  * font) is compatible with that of the underlying unscaled, possibly
644  * standard, base font, and if not, whether we can re-encode the character
645  * using the base font's encoding.  Return the (possibly re-encoded)
646  * character if successful.
647  */
648 inline private void
649 record_used(pdf_font_descriptor_t *pfd, int c)
650 {
651     pfd->chars_used[c >> 3] |= 1 << (c & 7);
652 }
653 private int
654 pdf_encode_char(gx_device_pdf *pdev, int chr, gs_font_base *bfont,
655 		pdf_font_t *ppf)
656 {
657     pdf_font_descriptor_t *const pfd = ppf->FontDescriptor;
658     /*
659      * bfont is the current font in which the text is being shown.
660      * ei is its encoding_index.
661      */
662     gs_encoding_index_t ei = bfont->encoding_index;
663     /*
664      * base_font is the font that underlies this PDF font (i.e., this PDF
665      * font is base_font plus some possible Encoding and Widths differences,
666      * and possibly a different FontMatrix).  base_font is 0 iff this PDF
667      * font is one of the standard 14 (i.e., ppf->index !=
668      * ENCODING_INDEX_UNKNOWN).  bei is the index of the BaseEncoding
669      * (explicit or, for the standard fonts, implicit) that will be written
670      * in the PDF file: it is not necessarily the same as
671      * base_font->encoding_index, or even base_font->nearest_encoding_index.
672      */
673     gs_font *base_font = pfd->base_font;
674     bool have_font = base_font != 0 && base_font->FontType != ft_composite;
675     bool is_standard = ppf->index != ENCODING_INDEX_UNKNOWN;
676     gs_encoding_index_t bei =
677 	(ppf->BaseEncoding != ENCODING_INDEX_UNKNOWN ? ppf->BaseEncoding :
678 	 is_standard ? pdf_standard_fonts[ppf->index].base_encoding :
679 	 ENCODING_INDEX_UNKNOWN);
680     pdf_encoding_element_t *pdiff = ppf->Differences;
681     /*
682      * If set, font_glyph is the glyph currently associated with chr in
683      * base_font + bei + diffs; glyph is the glyph corresponding to chr in
684      * bfont.
685      */
686     gs_glyph font_glyph, glyph;
687 #define IS_USED(c)\
688   (((pfd)->chars_used[(c) >> 3] & (1 << ((c) & 7))) != 0)
689 
690     if (ei == bei && ei != ENCODING_INDEX_UNKNOWN && pdiff == 0) {
691 	/*
692 	 * Just note that the character has been used with its original
693 	 * encoding.
694 	 */
695 	record_used(pfd, chr);
696 	return chr;
697     }
698     if (!is_standard && !have_font)
699 	return_error(gs_error_undefined); /* can't encode */
700 
701 #define ENCODE_NO_DIFF(ch)\
702    (bei != ENCODING_INDEX_UNKNOWN ?\
703     bfont->procs.callbacks.known_encode((gs_char)(ch), bei) :\
704     /* have_font */ bfont->procs.encode_char(base_font, chr, GLYPH_SPACE_NAME))
705 #define HAS_DIFF(ch) (pdiff != 0 && pdiff[ch].str.data != 0)
706 #define ENCODE_DIFF(ch) (pdiff[ch].glyph)
707 #define ENCODE(ch)\
708   (HAS_DIFF(ch) ? ENCODE_DIFF(ch) : ENCODE_NO_DIFF(ch))
709 
710     font_glyph = ENCODE(chr);
711     glyph =
712 	(ei == ENCODING_INDEX_UNKNOWN ?
713 	 bfont->procs.encode_char((gs_font *)bfont, chr, GLYPH_SPACE_NAME) :
714 	 bfont->procs.callbacks.known_encode(chr, ei));
715     if (glyph == font_glyph) {
716 	record_used(pfd, chr);
717 	return chr;
718     }
719 
720     if (ppf->index == ENCODING_INDEX_UNKNOWN && pfd->FontFile_id == 0 &&
721 	pdev->CompatibilityLevel <= 1.2
722 	) {
723 	/*
724 	 * Work around the bug in Acrobat Reader 3's Print function
725 	 * that makes re-encoded characters in substituted fonts
726 	 * print as blank.
727 	 */
728 	return_error(gs_error_undefined);
729     }
730 
731     /*
732      * TrueType fonts don't allow Differences in the encoding, but we might
733      * be able to re-encode the character if it appears elsewhere in the
734      * encoding.
735      */
736     if (bfont->FontType == ft_TrueType) {
737 	if (pdev->ReEncodeCharacters) {
738 	    int c;
739 
740 	    for (c = 0; c < 256; ++c)
741 		if (ENCODE_NO_DIFF(c) == glyph) {
742 		    record_used(pfd, c);
743 		    return c;
744 		}
745 	}
746 	return_error(gs_error_undefined);
747     }
748 
749     /*
750      * If the font isn't going to be embedded, check whether this glyph is
751      * available in the base font's glyph set at all.
752      */
753     if (pfd->FontFile_id == 0) {
754 	switch (bei) {
755 	case ENCODING_INDEX_STANDARD:
756 	case ENCODING_INDEX_ISOLATIN1:
757 	case ENCODING_INDEX_WINANSI:
758 	case ENCODING_INDEX_MACROMAN:
759 	    /* Check the full Adobe glyph set(s). */
760 	    if (!encoding_has_glyph(bfont, glyph, ENCODING_INDEX_ALOGLYPH) &&
761 		(pdev->CompatibilityLevel < 1.3 ||
762 		 !encoding_has_glyph(bfont, glyph, ENCODING_INDEX_ALXGLYPH))
763 		)
764 		return_error(gs_error_undefined);
765 	default:
766 	    break;
767 	}
768     }
769 
770     if (pdev->ReAssignCharacters) {
771 	/*
772 	 * If this is the first time we've seen this character,
773 	 * assign the glyph to its position in the encoding.
774 	 */
775 	if (!HAS_DIFF(chr) && !IS_USED(chr)) {
776 	    int code =
777 		pdf_add_encoding_difference(pdev, ppf, chr, bfont, glyph);
778 
779 	    if (code >= 0) {
780 		/*
781 		 * As noted in the comments at the beginning of this file,
782 		 * we don't have any way to record, for the purpose of
783 		 * subsetting, the fact that a particular unencoded glyph
784 		 * was used.  If this glyph doesn't appear anywhere else in
785 		 * the base encoding, fall back to writing the entire font.
786 		 */
787 		int c;
788 
789 		for (c = 0; c < 256; ++c)
790 		    if (ENCODE_NO_DIFF(c) == glyph)
791 			break;
792 		if (c < 256)	/* found */
793 		    record_used(pfd, c);
794 		else		/* not found */
795 		    pfd->subset_ok = false;
796 		return chr;
797 	    }
798 	}
799     }
800 
801     if (pdev->ReEncodeCharacters) {
802 	/*
803 	 * Look for the character at some other position in the
804 	 * encoding.
805 	 */
806 	int c, code;
807 
808 	for (c = 0; c < 256; ++c) {
809 	    if (HAS_DIFF(c)) {
810 		if (ENCODE_DIFF(c) == glyph)
811 		    return c;
812 	    } else if (ENCODE_NO_DIFF(c) == glyph) {
813 		record_used(pfd, c);
814 		return c;
815 	    }
816 	}
817 	/*
818 	 * The character isn't encoded anywhere.  Look for a
819 	 * never-referenced .notdef position where we can put it.
820 	 */
821 	for (c = 0; c < 256; ++c) {
822 	    gs_const_string gnstr;
823 
824 	    if (HAS_DIFF(c) || IS_USED(c))
825 		continue; /* slot already referenced */
826 	    font_glyph = ENCODE_NO_DIFF(c);
827 	    if (font_glyph == gs_no_glyph)
828 		break;
829 	    gnstr.data = (const byte *)
830 		bfont->procs.callbacks.glyph_name(font_glyph,
831 						  &gnstr.size);
832 	    if (gnstr.size == 7 &&
833 		!memcmp(gnstr.data, ".notdef", 7)
834 		)
835 		break;
836 	}
837 	if (c == 256)	/* no .notdef positions left */
838 	    return_error(gs_error_undefined);
839 	code = pdf_add_encoding_difference(pdev, ppf, c, bfont, glyph);
840 	if (code < 0)
841 	    return code;
842 	/* See under ReAssignCharacters above regarding the following: */
843 	pfd->subset_ok = false;
844 	return c;
845     }
846 
847     return_error(gs_error_undefined);
848 
849 #undef IS_USED
850 #undef ENCODE_NO_DIFF
851 #undef HAS_DIFF
852 #undef ENCODE_DIFF
853 #undef ENCODE
854 }
855 
856 /*
857  * Write out commands to make the output state match the processing state.
858  */
859 private int
860 pdf_write_text_process_state(gx_device_pdf *pdev,
861 			     const pdf_text_process_state_t *ppts,
862 			     const gs_const_string *pstr)
863 {
864     int code;
865     stream *s;
866 
867     pdf_set_font_and_size(pdev, ppts->pdfont, ppts->size);
868     code = pdf_set_text_matrix(pdev, &ppts->text_matrix);
869     if (code < 0)
870 	return code;
871 
872     if (pdev->text.character_spacing != ppts->chars &&
873 	pstr->size + pdev->text.buffer_count > 1
874 	) {
875 	code = pdf_open_page(pdev, PDF_IN_TEXT);
876 	if (code < 0)
877 	    return code;
878 	s = pdev->strm;
879 	pprintg1(s, "%g Tc\n", ppts->chars);
880 	pdev->text.character_spacing = ppts->chars;
881     }
882 
883     if (pdev->text.word_spacing != ppts->words &&
884 	(memchr(pstr->data, 32, pstr->size) ||
885 	 memchr(pdev->text.buffer, 32, pdev->text.buffer_count))
886 	) {
887 	code = pdf_open_page(pdev, PDF_IN_TEXT);
888 	if (code < 0)
889 	    return code;
890 	s = pdev->strm;
891 	pprintg1(s, "%g Tw\n", ppts->words);
892 	pdev->text.word_spacing = ppts->words;
893     }
894 
895     return 0;
896 }
897 
898 /*
899  * Continue processing text.  Per the check in pdf_text_begin, we know the
900  * operation is TEXT_FROM_STRING/BYTES, TEXT_DO_DRAW, and possibly
901  * TEXT_ADD_TO_ALL_WIDTHS, TEXT_ADD_TO_SPACE_WIDTH, TEXT_REPLACE_WIDTHS,
902  * and/or TEXT_RETURN_WIDTH.
903  */
904 private int
905 pdf_text_process(gs_text_enum_t *pte)
906 {
907     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
908     gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
909     gs_text_enum_t *pte_default = penum->pte_default;
910     gs_font *font;
911     gs_matrix fmat;
912     const gs_text_params_t *text = &pte->text;
913     gs_text_params_t alt_text;
914     pdf_text_process_state_t text_state;
915     gs_const_string str;
916     int i;
917     byte strbuf[200];		/* arbitrary */
918     int code;
919 
920  top:
921     if (pte_default) {
922 	/* Continue processing using the default algorithms. */
923 	code = gs_text_process(pte_default);
924 	gs_text_enum_copy_dynamic(pte, pte_default, true);
925 	if (code)
926 	    return code;
927 	gs_text_release(pte_default, "pdf_text_process");
928 	penum->pte_default = pte_default = 0;
929 	/****** FOR NOW ******/
930 	return 0;
931     }
932     str.data = text->data.bytes;
933     str.size = text->size;
934     font = penum->current_font;
935     fmat = font->FontMatrix;
936  fnt:
937     switch (font->FontType) {
938     case ft_TrueType:
939     case ft_encrypted:
940     case ft_encrypted2:
941 	break;
942     case ft_composite: {
943 	gs_font_type0 *const font0 = (gs_font_type0 *)font;
944 	/*
945 	 * Support just one special format, which is used by some versions
946 	 * of the Adobe PS4 driver even for single-byte text.
947 	 */
948 	switch (font0->data.FMapType) {
949 	case fmap_8_8:
950 	    if (str.size > sizeof(strbuf) * 2)
951 		goto dflt;
952 	    for (i = 0; i < str.size; i += 2) {
953 		if (str.data[i] != 0)
954 		    goto dflt;
955 		strbuf[i >> 1] = str.data[i + 1];
956 	    }
957 	    str.data = strbuf;
958 	    str.size >>= 1;
959 	    font = penum->current_font = font0->data.FDepVector[0];
960 	    /*
961 	     * The FontMatrix of descendant base fonts is not scaled by
962 	     * scalefont/makefont.
963 	     */
964 	    if (font->FontType != ft_composite)
965 		gs_matrix_multiply(&fmat, &font->FontMatrix, &fmat);
966 	    goto fnt;
967 	default:
968 	    goto dflt;
969 	}
970 	break;
971     }
972     default:
973 	goto dflt;
974     }
975 
976     code = pdf_update_text_state(&text_state, penum, &fmat);
977     if (code < 0)
978 	goto dflt;
979 
980     /* Check that all characters can be encoded. */
981 
982     for (i = 0; i < str.size; ++i) {
983 	int chr = str.data[i];
984 	int code = pdf_encode_char(pdev, chr, (gs_font_base *)font,
985 				   text_state.pdfont);
986 
987 	if (code < 0)
988 	    goto dflt;
989 	if (code != chr) {
990 	    /*
991 	     * It really simplifies things if we can buffer
992 	     * the entire string locally in one piece....
993 	     */
994 	    if (str.data != strbuf) {
995 		if (str.size > sizeof(strbuf))
996 		    goto dflt;
997 		memcpy(strbuf, str.data, str.size);
998 		str.data = strbuf;
999 	    }
1000 	    strbuf[i] = (byte)code;
1001 	}
1002     }
1003 
1004     /* Bring the text-related parameters in the output up to date. */
1005 
1006     code = pdf_write_text_process_state(pdev, &text_state, &str);
1007     if (code < 0)
1008 	goto dflt;
1009 
1010     if (text->operation & TEXT_REPLACE_WIDTHS) {
1011 	gs_point w;
1012 	gs_matrix tmat;
1013 
1014 	w.x = w.y = 0;
1015 	tmat = text_state.text_matrix;
1016 	for (; pte->index < str.size; pte->index++, pte->xy_index++) {
1017 	    gs_point d, dpt;
1018 
1019 	    code = pdf_append_chars(pdev, str.data + pte->index, 1);
1020 	    if (code < 0)
1021 		return code;
1022 	    gs_text_replaced_width(&pte->text, pte->xy_index, &d);
1023 	    w.x += d.x, w.y += d.y;
1024 	    gs_distance_transform(d.x, d.y, &ctm_only(pte->pis), &dpt);
1025 	    tmat.tx += dpt.x;
1026 	    tmat.ty += dpt.y;
1027 	    if (pte->index + 1 < str.size) {
1028 		code = pdf_set_text_matrix(pdev, &tmat);
1029 		if (code < 0)
1030 		    return code;
1031 	    }
1032 	}
1033 	pte->returned.total_width = w;
1034 	return
1035 	    (text->operation & TEXT_RETURN_WIDTH ?
1036 	     gx_path_add_point(pte->path, float2fixed(tmat.tx),
1037 			       float2fixed(tmat.ty)) :
1038 	     0);
1039     }
1040     code = pdf_append_chars(pdev, str.data + pte->index,
1041 			    str.size - pte->index);
1042     pte->index = 0;
1043     if (code < 0)
1044 	goto dflt;
1045     /*
1046      * If we don't need the widths, return now.  If the widths are
1047      * available directly from the font, compute and return the total
1048      * width now.  Otherwise, call the default implementation.
1049      */
1050     if (!(text->operation & TEXT_RETURN_WIDTH))
1051 	return 0;
1052     {
1053 	int i, w;
1054 	double scale = (font->FontType == ft_TrueType ? 0.001 : 1.0);
1055 	gs_point dpt;
1056 	int num_spaces = 0;
1057 
1058 	for (i = pte->index, w = 0; i < str.size; ++i) {
1059 	    int cw;
1060 	    int code =
1061 		pdf_char_width(text_state.pdfont, str.data[i], font, &cw);
1062 
1063 	    if (code < 0)
1064 		goto dflt_w;
1065 	    w += cw;
1066 	    if (str.data[i] == ' ')
1067 		++num_spaces;
1068 	}
1069 	gs_distance_transform(w * scale, 0.0, &font->FontMatrix, &dpt);
1070 	if (text->operation & TEXT_ADD_TO_ALL_WIDTHS) {
1071 	    int num_chars = str.size - pte->index;
1072 
1073 	    dpt.x += penum->text.delta_all.x * num_chars;
1074 	    dpt.y += penum->text.delta_all.y * num_chars;
1075 	}
1076 	if (text->operation & TEXT_ADD_TO_SPACE_WIDTH) {
1077 	    dpt.x += penum->text.delta_space.x * num_spaces;
1078 	    dpt.y += penum->text.delta_space.y * num_spaces;
1079 	}
1080 	pte->returned.total_width = dpt;
1081 	gs_distance_transform(dpt.x, dpt.y, &ctm_only(pte->pis), &dpt);
1082 	return gx_path_add_point(pte->path,
1083 				 penum->origin.x + float2fixed(dpt.x),
1084 				 penum->origin.y + float2fixed(dpt.y));
1085     }
1086  dflt_w:
1087     alt_text = *text;
1088     alt_text.operation ^= TEXT_DO_DRAW | TEXT_DO_CHARWIDTH;
1089     text = &alt_text;
1090  dflt:
1091     code = gx_default_text_begin(pte->dev, pte->pis, text, pte->current_font,
1092 				 pte->path, pte->pdcolor, pte->pcpath,
1093 				 pte->memory, &penum->pte_default);
1094     if (code < 0)
1095 	return code;
1096     pte_default = penum->pte_default;
1097     gs_text_enum_copy_dynamic(pte_default, pte, false);
1098     goto top;
1099 }
1100 
1101 /* ---------------- Text and font utilities ---------------- */
1102 
1103 /* Forward declarations */
1104 private int assign_char_code(P1(gx_device_pdf * pdev));
1105 
1106 /*
1107  * Set the current font and size, writing a Tf command if needed.
1108  */
1109 private int
1110 pdf_set_font_and_size(gx_device_pdf * pdev, pdf_font_t * font, floatp size)
1111 {
1112     if (font != pdev->text.font || size != pdev->text.size) {
1113 	int code = pdf_open_page(pdev, PDF_IN_TEXT);
1114 	stream *s = pdev->strm;
1115 
1116 	if (code < 0)
1117 	    return code;
1118 	pprints1(s, "/%s ", font->frname);
1119 	pprintg1(s, "%g Tf\n", size);
1120 	pdev->text.font = font;
1121 	pdev->text.size = size;
1122     }
1123     font->used_on_page = true;
1124     return 0;
1125 }
1126 
1127 /*
1128  * Set the text matrix for writing text.
1129  * The translation component of the matrix is the text origin.
1130  * If the non-translation components of the matrix differ from the
1131  * current ones, write a Tm command; otherwise, write either a Td command
1132  * or a Tj command using space pseudo-characters.
1133  */
1134 private int
1135 set_text_distance(gs_point *pdist, const gs_point *ppt, const gs_matrix *pmat)
1136 {
1137     double rounded;
1138 
1139     gs_distance_transform_inverse(pmat->tx - ppt->x, pmat->ty - ppt->y,
1140 				  pmat, pdist);
1141     /* If the distance is very close to integers, round it. */
1142     if (fabs(pdist->x - (rounded = floor(pdist->x + 0.5))) < 0.0005)
1143 	pdist->x = rounded;
1144     if (fabs(pdist->y - (rounded = floor(pdist->y + 0.5))) < 0.0005)
1145 	pdist->y = rounded;
1146     return 0;
1147 }
1148 private int
1149 pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
1150 {
1151     stream *s = pdev->strm;
1152     double sx = 72.0 / pdev->HWResolution[0],
1153 	sy = 72.0 / pdev->HWResolution[1];
1154     int code;
1155 
1156     if (pmat->xx == pdev->text.matrix.xx &&
1157 	pmat->xy == pdev->text.matrix.xy &&
1158 	pmat->yx == pdev->text.matrix.yx &&
1159 	pmat->yy == pdev->text.matrix.yy &&
1160     /*
1161      * If we aren't already in text context, BT will reset
1162      * the text matrix.
1163      */
1164 	(pdev->context == PDF_IN_TEXT || pdev->context == PDF_IN_STRING)
1165 	) {
1166 	/* Use Td or a pseudo-character. */
1167 	gs_point dist;
1168 
1169 	set_text_distance(&dist, &pdev->text.current, pmat);
1170 	if (dist.y == 0 && dist.x >= X_SPACE_MIN &&
1171 	    dist.x <= X_SPACE_MAX &&
1172 	    pdev->text.font != 0 &&
1173 	    PDF_FONT_IS_SYNTHESIZED(pdev->text.font)
1174 	    ) {			/* Use a pseudo-character. */
1175 	    int dx = (int)dist.x;
1176 	    int dx_i = dx - X_SPACE_MIN;
1177 	    byte space_char = pdev->text.font->spaces[dx_i];
1178 
1179 	    if (space_char == 0) {
1180 		if (pdev->text.font != pdev->open_font)
1181 		    goto td;
1182 		code = assign_char_code(pdev);
1183 		if (code <= 0)
1184 		    goto td;
1185 		space_char =
1186 		    pdev->open_font->spaces[dx_i] =
1187 		    (byte) code;
1188 		if (pdev->space_char_ids[dx_i] == 0) {
1189 		    /* Create the space char_proc now. */
1190 		    char spstr[3 + 14 + 1];
1191 		    stream *s;
1192 
1193 		    sprintf(spstr, "%d 0 0 0 0 0 d1\n", dx);
1194 		    pdev->space_char_ids[dx_i] = pdf_begin_separate(pdev);
1195 		    s = pdev->strm;
1196 		    pprintd1(s, "<</Length %d>>\nstream\n", strlen(spstr));
1197 		    pprints1(s, "%sendstream\n", spstr);
1198 		    pdf_end_separate(pdev);
1199 		}
1200 	    }
1201 	    pdf_append_chars(pdev, &space_char, 1);
1202 	    pdev->text.current.x += dist.x * pmat->xx;
1203 	    return 0;
1204 	}
1205       td:			/* Use Td. */
1206 	code = pdf_open_page(pdev, PDF_IN_TEXT);
1207 	if (code < 0)
1208 	    return code;
1209 	set_text_distance(&dist, &pdev->text.line_start, pmat);
1210 	pprintg2(s, "%g %g Td\n", dist.x, dist.y);
1211     } else {			/* Use Tm. */
1212 	code = pdf_open_page(pdev, PDF_IN_TEXT);
1213 	if (code < 0)
1214 	    return code;
1215 	/*
1216 	 * See stream_to_text in gdevpdf.c for why we need the following
1217 	 * matrix adjustments.
1218 	 */
1219 	pprintg6(pdev->strm, "%g %g %g %g %g %g Tm\n",
1220 		 pmat->xx * sx, pmat->xy * sy,
1221 		 pmat->yx * sx, pmat->yy * sy,
1222 		 pmat->tx * sx, pmat->ty * sy);
1223 	pdev->text.matrix = *pmat;
1224     }
1225     pdev->text.line_start.x = pmat->tx;
1226     pdev->text.line_start.y = pmat->ty;
1227     pdev->text.current.x = pmat->tx;
1228     pdev->text.current.y = pmat->ty;
1229     return 0;
1230 }
1231 
1232 /* Append characters to a string being accumulated. */
1233 private int
1234 pdf_append_chars(gx_device_pdf * pdev, const byte * str, uint size)
1235 {
1236     const byte *p = str;
1237     uint left = size;
1238 
1239     while (left)
1240 	if (pdev->text.buffer_count == max_text_buffer) {
1241 	    int code = pdf_open_page(pdev, PDF_IN_TEXT);
1242 
1243 	    if (code < 0)
1244 		return code;
1245 	} else {
1246 	    int code = pdf_open_page(pdev, PDF_IN_STRING);
1247 	    uint copy;
1248 
1249 	    if (code < 0)
1250 		return code;
1251 	    copy = min(max_text_buffer - pdev->text.buffer_count, left);
1252 	    memcpy(pdev->text.buffer + pdev->text.buffer_count, p, copy);
1253 	    pdev->text.buffer_count += copy;
1254 	    p += copy;
1255 	    left -= copy;
1256 	}
1257     return 0;
1258 }
1259 
1260 /* ---------------- Synthesized fonts ---------------- */
1261 
1262 /* Assign a code for a char_proc. */
1263 private int
1264 assign_char_code(gx_device_pdf * pdev)
1265 {
1266     pdf_font_t *font = pdev->open_font;
1267 
1268     if (pdev->embedded_encoding_id == 0) {
1269 	long id = pdf_begin_separate(pdev);
1270 	stream *s = pdev->strm;
1271 	int i;
1272 
1273 	/*
1274 	 * Even though the PDF reference documentation says that a
1275 	 * BaseEncoding key is required unless the encoding is
1276 	 * "based on the base font's encoding" (and there is no base
1277 	 * font in this case), Acrobat 2.1 gives an error if the
1278 	 * BaseEncoding key is present.
1279 	 */
1280 	pputs(s, "<</Type/Encoding/Differences[0");
1281 	for (i = 0; i < 256; ++i) {
1282 	    if (!(i & 15))
1283 		pputs(s, "\n");
1284 	    pprintd1(s, "/a%d", i);
1285 	}
1286 	pputs(s, "\n] >>\n");
1287 	pdf_end_separate(pdev);
1288 	pdev->embedded_encoding_id = id;
1289     }
1290     if (font == 0 || font->num_chars == 256) {
1291 	/* Start a new synthesized font. */
1292 	int code = pdf_alloc_font(pdev, gs_no_id, &font, gs_no_id);
1293 	char *pc;
1294 
1295 	if (code < 0)
1296 	    return code;
1297 	strcpy(font->frname, pdev->open_font_name);
1298 	for (pc = font->frname; *pc == 'Z'; ++pc)
1299 	    *pc = '@';
1300 	if ((*pc)++ == 0)
1301 	    *pc = 'A', pc[1] = 0;
1302 	pdev->open_font = font;
1303 	strcpy(pdev->open_font_name, font->frname);
1304     }
1305     return font->num_chars++;
1306 }
1307 
1308 /* Begin a CharProc for a synthesized (bitmap) font. */
1309 int
1310 pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
1311   int y_offset, gs_id id, pdf_char_proc_t ** ppcp, pdf_stream_position_t * ppos)
1312 {
1313     pdf_resource_t *pres;
1314     pdf_char_proc_t *pcp;
1315     int char_code = assign_char_code(pdev);
1316     pdf_font_t *font = pdev->open_font;
1317     int code;
1318 
1319     if (char_code < 0)
1320 	return char_code;
1321     code = pdf_begin_resource(pdev, resourceCharProc, id, &pres);
1322     if (code < 0)
1323 	return code;
1324     pcp = (pdf_char_proc_t *) pres;
1325     pcp->font = font;
1326     pcp->char_next = font->char_procs;
1327     font->char_procs = pcp;
1328     pcp->char_code = char_code;
1329     pcp->width = w;
1330     pcp->height = h;
1331     pcp->x_width = x_width;
1332     pcp->y_offset = y_offset;
1333     font->max_y_offset = max(font->max_y_offset, h + (h >> 2));
1334     *ppcp = pcp;
1335     {
1336 	stream *s = pdev->strm;
1337 
1338 	/*
1339 	 * The resource file is positionable, so rather than use an
1340 	 * object reference for the length, we'll go back and fill it in
1341 	 * at the end of the definition.  Take 10K as the longest
1342 	 * definition we can handle.
1343 	 */
1344 	pputs(s, "<</Length     >>\nstream\n");
1345 	ppos->start_pos = stell(s);
1346     }
1347     return 0;
1348 }
1349 
1350 /* End a CharProc. */
1351 int
1352 pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos)
1353 {
1354     stream *s = pdev->strm;
1355     long start_pos = ppos->start_pos;
1356     long end_pos = stell(s);
1357     long length = end_pos - start_pos;
1358 
1359     if (length > 9999)
1360 	return_error(gs_error_limitcheck);
1361     sseek(s, start_pos - 14);
1362     pprintd1(s, "%d", length);
1363     sseek(s, end_pos);
1364     pputs(s, "endstream\n");
1365     pdf_end_separate(pdev);
1366     return 0;
1367 }
1368 
1369 /* Put out a reference to an image as a character in a synthesized font. */
1370 int
1371 pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
1372 		  const gs_matrix * pimat)
1373 {
1374     pdf_set_font_and_size(pdev, pcp->font, 1.0);
1375     {
1376 	gs_matrix tmat;
1377 
1378 	tmat = *pimat;
1379 	tmat.ty -= pcp->y_offset;
1380 	pdf_set_text_matrix(pdev, &tmat);
1381     }
1382     pdf_append_chars(pdev, &pcp->char_code, 1);
1383     pdev->text.current.x += pcp->x_width * pdev->text.matrix.xx;
1384     return 0;
1385 }
1386