xref: /plan9/sys/src/cmd/gs/src/gdevpdtt.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 2002 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gdevpdtt.c,v 1.104 2005/10/12 08:16:50 leonardo Exp $ */
18 /* Text processing for pdfwrite. */
19 #include "math_.h"
20 #include "string_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gscencs.h"
24 #include "gscedata.h"
25 #include "gsmatrix.h"
26 #include "gzstate.h"
27 #include "gxfcache.h"		/* for orig_fonts list */
28 #include "gxfont.h"
29 #include "gxfont0.h"
30 #include "gxfcid.h"
31 #include "gxfcopy.h"
32 #include "gxfcmap.h"
33 #include "gxpath.h"		/* for getting current point */
34 #include "gxchar.h"
35 #include "gxstate.h"
36 #include "gdevpdfx.h"
37 #include "gdevpdfg.h"
38 #include "gdevpdtx.h"
39 #include "gdevpdtd.h"
40 #include "gdevpdtf.h"
41 #include "gdevpdts.h"
42 #include "gdevpdtt.h"
43 #include "gdevpdti.h"
44 #include "gxhldevc.h"
45 
46 /* ================ Text enumerator ================ */
47 
48 /* GC descriptor */
49 private_st_pdf_text_enum();
50 
51 /* Define the auxiliary procedures for text processing. */
52 private int
pdf_text_resync(gs_text_enum_t * pte,const gs_text_enum_t * pfrom)53 pdf_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
54 {
55     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
56 
57     if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY)
58 	return_error(gs_error_rangecheck);
59     if (penum->pte_default) {
60 	int code = gs_text_resync(penum->pte_default, pfrom);
61 
62 	if (code < 0)
63 	    return code;
64     }
65     pte->text = pfrom->text;
66     gs_text_enum_copy_dynamic(pte, pfrom, false);
67     return 0;
68 }
69 private bool
pdf_text_is_width_only(const gs_text_enum_t * pte)70 pdf_text_is_width_only(const gs_text_enum_t *pte)
71 {
72     const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
73 
74     if (penum->pte_default)
75 	return gs_text_is_width_only(penum->pte_default);
76     return false;
77 }
78 private int
pdf_text_current_width(const gs_text_enum_t * pte,gs_point * pwidth)79 pdf_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth)
80 {
81     const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
82 
83     if (penum->pte_default)
84 	return gs_text_current_width(penum->pte_default, pwidth);
85     return_error(gs_error_rangecheck); /* can't happen */
86 }
87 private int
pdf_text_set_cache(gs_text_enum_t * pte,const double * pw,gs_text_cache_control_t control)88 pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
89 		   gs_text_cache_control_t control)
90 {
91     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
92     gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
93 
94     switch (control) {
95     case TEXT_SET_CHAR_WIDTH:
96     case TEXT_SET_CACHE_DEVICE:
97 	gs_distance_transform(pw[0], pw[1], &ctm_only(pte->pis), &pdev->char_width);
98 	break;
99     case TEXT_SET_CACHE_DEVICE2:
100 	/*
101 	 * pdev->char_width is used with synthesized Type 3 fonts only.
102 	 * Since they are simple fonts, we only need the horisontal
103 	 * width for Widths array. Therefore we don't check
104 	 * gs_rootfont(pgs)->WMode and don't use pw[6:7].
105 	 */
106 	gs_distance_transform(pw[0], pw[1], &ctm_only(pte->pis), &pdev->char_width);
107 	if (penum->cdevproc_callout) {
108 	    memcpy(penum->cdevproc_result, pw, sizeof(penum->cdevproc_result));
109 	    return 0;
110 	}
111 	break;
112     default:
113 	return_error(gs_error_rangecheck);
114     }
115     if (penum->current_font->FontType == ft_user_defined &&
116 	    penum->orig_font->FontType != ft_composite &&
117 	    penum->outer_CID == GS_NO_GLYPH &&
118 	    !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
119 	int code;
120 	gs_font *font = penum->orig_font;
121 	gs_char ch;
122 	gs_glyph glyph;
123 	gs_const_string gnstr;
124 
125 	if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
126 	    byte buf[1];
127 	    int char_code_length;
128 
129 	    glyph = pte->text.data.d_glyph;
130 	    code = pdf_encode_glyph((gs_font_base *)font, glyph,
131 			buf, sizeof(buf), &char_code_length);
132 	    if (code < 0) {
133 		/* Must not happen, becuse pdf_encode_glyph was passed in process_plain_text.*/
134 		ch = GS_NO_CHAR;
135 	    } else if (char_code_length != 1) {
136 		/* Must not happen with type 3 fonts.*/
137 		ch = GS_NO_CHAR;
138 	    } else
139 		ch = buf[0];
140 	} else {
141 	    ch = penum->text.data.bytes[penum->index];
142 	    glyph = font->procs.encode_char(font, ch, GLYPH_SPACE_NAME);
143 	    /*
144 	     * If glyph == GS_NO_GLYPH, we should replace it with
145 	     * a notdef glyph, but we don't know how to do with Type 3 fonts.
146 	     */
147 	}
148 	if (glyph != GS_NO_GLYPH && ch != GS_NO_CHAR) {
149 	    gs_show_enum *penum_s;
150 	    extern_st(st_gs_show_enum);
151 	    gs_fixed_rect clip_box;
152 	    double pw1[10];
153 	    int narg = (control == TEXT_SET_CHAR_WIDTH ? 2 :
154 			control == TEXT_SET_CACHE_DEVICE ? 6 : 10), i;
155 
156 	    if (penum->pte_default == NULL)
157 		return_error(gs_error_unregistered); /* Must not happen. */
158 	    /* Check to verify the structure type is really gs_show_enum */
159 	    if (gs_object_type(penum->pte_default->memory, penum->pte_default) != &st_gs_show_enum) {
160 		/* Must not happen with PS interpreter.
161 		   Other clients should conform. */
162 		return_error(gs_error_unregistered);
163 	    }
164 	    penum_s = (gs_show_enum *)penum->pte_default;
165 	    code = font->procs.glyph_name(font, glyph, &gnstr);
166 	    if (code < 0)
167 		return_error(gs_error_unregistered); /* Must not happen. */
168 	    /* BuildChar could change the scale before calling setcachedevice (Bug 687290).
169 	       We must scale the setcachedevice arguments because we assumed
170 	       identity scale before entering the charproc.
171 	       For now we only handle scaling matrices.
172 	    */
173 	    for (i = 0; i < narg; i += 2) {
174 		gs_point p;
175 
176 		gs_point_transform(pw[i], pw[i + 1], &ctm_only(penum_s->pgs), &p);
177 		pw1[i] = p.x;
178 		pw1[i + 1] = p.y;
179 	    }
180 	    if (control != TEXT_SET_CHAR_WIDTH) {
181 		clip_box.p.x = float2fixed(pw1[2]);
182 		clip_box.p.y = float2fixed(pw1[3]);
183 		clip_box.q.x = float2fixed(pw1[4]);
184 		clip_box.q.y = float2fixed(pw1[5]);
185 	    } else {
186 		/*
187 		 * We have no character bbox, but we need one to install the clipping
188 		 * to the graphic state of the PS interpreter. Since some fonts don't
189 		 * provide a proper FontBBox (Bug 687239 supplies a zero one),
190 		 * we set an "infinite" clipping here.
191 		 * We also detected that min_int, max_int don't work here with
192 		 * comparefiles/Bug687044.ps, therefore we divide them by 2.
193 		 */
194 		clip_box.p.x = clip_box.p.y = min_int / 2;
195 		clip_box.q.x = clip_box.q.y = max_int / 2;
196 	    }
197 	    code = gx_clip_to_rectangle(penum_s->pgs, &clip_box);
198 	    if (code < 0)
199 		return code;
200 	    code = pdf_set_charproc_attrs(pdev, pte->current_font,
201 			pw1, narg, control, ch, &gnstr);
202 	    if (code < 0)
203 		return code;
204 	    /* Prevent writing the clipping path to charproc.
205 	       See the comment above and bugs 687678, 688327.
206 	       Note that the clipping in the graphic state will be used while
207 	       fallbacks to default implementations of graphic objects.
208 	       Hopely such fallbacks are rare. */
209 	    pdev->clip_path_id = gx_get_clip_path_id(penum_s->pgs);
210 	    penum->charproc_accum = true;
211 	    return code;
212 	} else {
213 	    gs_matrix m;
214 	    pdf_resource_t *pres = pdev->accumulating_substream_resource;
215 
216 	    /* pdf_text_process started a charproc stream accumulation,
217 	       but now we re-decided to go with the default implementation.
218 	       Cancel the stream now.
219 	     */
220 	    code = pdf_exit_substream(pdev);
221 	    if (code < 0)
222 		return code;
223 	    code = pdf_cancel_resource(pdev, pres, resourceCharProc);
224 	    if (code < 0)
225 		return code;
226 	    pdf_forget_resource(pdev, pres, resourceCharProc);
227 	    /* pdf_text_process had set an identity CTM for the
228 	       charproc stream accumulation, but now we re-decided
229 	       to go with the default implementation.
230 	       Need to restore the correct CTM and add
231 	       changes, which the charproc possibly did. */
232 	    gs_matrix_multiply((gs_matrix *)&pdev->charproc_ctm, (gs_matrix *)&penum->pis->ctm, &m);
233 	    gs_matrix_fixed_from_matrix(&penum->pis->ctm, &m);
234 	}
235     }
236     if (penum->pte_default) {
237 	if (penum->pte_default->text.operation & TEXT_DO_CHARWIDTH /* See process_cmap_text.*/)
238 	    return gs_text_set_cache(penum->pte_default, pw, TEXT_SET_CHAR_WIDTH);
239 	else
240 	    return gs_text_set_cache(penum->pte_default, pw, control);
241     }
242     return_error(gs_error_unregistered); /* can't happen */
243 }
244 private int
pdf_text_retry(gs_text_enum_t * pte)245 pdf_text_retry(gs_text_enum_t *pte)
246 {
247     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
248 
249     if (penum->pte_default)
250 	return gs_text_retry(penum->pte_default);
251     return_error(gs_error_rangecheck); /* can't happen */
252 }
253 private void
pdf_text_release(gs_text_enum_t * pte,client_name_t cname)254 pdf_text_release(gs_text_enum_t *pte, client_name_t cname)
255 {
256     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
257 
258     if (penum->pte_default) {
259 	gs_text_release(penum->pte_default, cname);
260 	penum->pte_default = 0;
261     }
262     pdf_text_release_cgp(penum);
263     gx_default_text_release(pte, cname);
264 }
265 void
pdf_text_release_cgp(pdf_text_enum_t * penum)266 pdf_text_release_cgp(pdf_text_enum_t *penum)
267 {
268     if (penum->cgp) {
269 	gs_free_object(penum->memory, penum->cgp, "pdf_text_release");
270 	penum->cgp = 0;
271     }
272 }
273 
274 /* Begin processing text. */
275 private text_enum_proc_process(pdf_text_process);
276 private const gs_text_enum_procs_t pdf_text_procs = {
277     pdf_text_resync, pdf_text_process,
278     pdf_text_is_width_only, pdf_text_current_width,
279     pdf_text_set_cache, pdf_text_retry,
280     pdf_text_release
281 };
282 
283 private int
pdf_prepare_text_drawing(gx_device_pdf * const pdev,gs_text_enum_t * pte)284 pdf_prepare_text_drawing(gx_device_pdf *const pdev, gs_text_enum_t *pte)
285 {
286     gs_imager_state * pis = pte->pis;
287     const gx_device_color * pdcolor = pte->pdcolor;
288     const gx_clip_path * pcpath = pte->pcpath;
289     const gs_text_params_t *text = &pte->text;
290     bool new_clip = false; /* Quiet compiler. */
291     int code;
292 
293     if (!(text->operation & TEXT_DO_NONE) || pis->text_rendering_mode == 3) {
294 	new_clip = pdf_must_put_clip_path(pdev, pcpath);
295 	if (new_clip)
296 	    code = pdf_unclip(pdev);
297 	else if (pdev->context == PDF_IN_NONE)
298 	    code = pdf_open_page(pdev, PDF_IN_STREAM);
299 	else
300 	    code = 0;
301 	if (code < 0)
302 	    return code;
303 	code = pdf_prepare_fill(pdev, pis);
304 	if (code < 0)
305 	    return code;
306     }
307     if (text->operation & TEXT_DO_DRAW) {
308 	/*
309 	 * Set the clipping path and drawing color.  We set both the fill
310 	 * and stroke color, because we don't know whether the fonts will be
311 	 * filled or stroked, and we can't set a color while we are in text
312 	 * mode.  (This is a consequence of the implementation, not a
313 	 * limitation of PDF.)
314 	 */
315 
316 	if (new_clip) {
317 	    code = pdf_put_clip_path(pdev, pcpath);
318 	    if (code < 0)
319 		return code;
320 	}
321 
322 	if ((code =
323 	     pdf_set_drawing_color(pdev, pis, pdcolor, &pdev->saved_stroke_color,
324 				   &pdev->stroke_used_process_color,
325 				   &psdf_set_stroke_color_commands)) < 0 ||
326 	    (code =
327 	     pdf_set_drawing_color(pdev, pis, pdcolor, &pdev->saved_fill_color,
328 				   &pdev->fill_used_process_color,
329 				   &psdf_set_fill_color_commands)) < 0
330 	    )
331 	    return code;
332     }
333     return 0;
334 }
335 
336 int
gdev_pdf_text_begin(gx_device * dev,gs_imager_state * pis,const gs_text_params_t * text,gs_font * font,gx_path * path0,const gx_device_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gs_text_enum_t ** ppte)337 gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis,
338 		    const gs_text_params_t *text, gs_font * font,
339 		    gx_path * path0, const gx_device_color * pdcolor,
340 		    const gx_clip_path * pcpath,
341 		    gs_memory_t * mem, gs_text_enum_t ** ppte)
342 {
343     gx_device_pdf *const pdev = (gx_device_pdf *)dev;
344     gx_path *path = path0;
345     pdf_text_enum_t *penum;
346     gs_fixed_point cpt;
347     int code;
348 
349     /* Track the dominant text rotation. */
350     {
351 	gs_matrix tmat;
352 	int i;
353 
354 	gs_matrix_multiply(&font->FontMatrix, &ctm_only(pis), &tmat);
355 	if (is_xxyy(&tmat))
356 	    i = (tmat.xx >= 0 ? 0 : 2);
357 	else if (is_xyyx(&tmat))
358 	    i = (tmat.xy >= 0 ? 1 : 3);
359 	else
360 	    i = 4;
361 	pdf_current_page(pdev)->text_rotation.counts[i] += text->size;
362     }
363 
364     if (font->FontType == ft_user_defined &&
365 	(text->operation & TEXT_DO_NONE) && (text->operation & TEXT_RETURN_WIDTH)) {
366 	/* This is stringwidth, see gx_default_text_begin.
367 	 * We need to prevent writing characters to PS cache,
368 	 * otherwise the font converts to bitmaps.
369 	 * So pass through even with stringwidth.
370 	 */
371 	code = gx_hld_stringwidth_begin(pis, &path);
372 	if (code < 0)
373 	    return code;
374     } else if ((!(text->operation & TEXT_DO_DRAW) && pis->text_rendering_mode != 3)
375 		|| path == 0 || gx_path_current_point(path, &cpt) < 0
376 	    )
377 	return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
378 					 pcpath, mem, ppte);
379 
380     /* Allocate and initialize the enumerator. */
381 
382     rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem,
383 		      return_error(gs_error_VMerror), "gdev_pdf_text_begin");
384     penum->rc.free = rc_free_text_enum;
385     penum->pte_default = 0;
386     penum->charproc_accum = false;
387     penum->cdevproc_callout = false;
388     penum->returned.total_width.x = penum->returned.total_width.y = 0;
389     penum->cgp = NULL;
390     code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs,
391 			     dev, pis, text, font, path, pdcolor, pcpath, mem);
392     if (code < 0) {
393 	gs_free_object(mem, penum, "gdev_pdf_text_begin");
394 	return code;
395     }
396     if (pdev->font3 != 0) {
397 	/* A text operation happens while accumulating a charproc.
398 	   This is a case when source document uses a Type 3 font,
399 	   which's charproc uses another font.
400 	   Since the text operation is handled by the device,
401 	   the font isn't converting to a raster (i.e. to a bitmap font).
402 	   Disable the grid fitting for the convertion to get a proper outlines,
403 	   because the viewer resolution is not known during the accumulation.
404 	   Note we set identity CTM in pdf_text_set_cache for the accumilation,
405 	   and therefore the font may look too small while the source charproc
406 	   interpretation. The document tpc2.ps of the bug 687087 is an example.
407 	*/
408 	penum->device_disabled_grid_fitting = true;
409     }
410 
411     *ppte = (gs_text_enum_t *)penum;
412 
413     return 0;
414 }
415 
416 /* ================ Font cache element ================ */
417 
418 /* GC descriptor */
419 private_st_pdf_font_cache_elem();
420 
421 /*
422  * Compute id for a font cache element.
423  */
424 private ulong
pdf_font_cache_elem_id(gs_font * font)425 pdf_font_cache_elem_id(gs_font *font)
426 {
427 #if 0
428     /*
429      *	For compatibility with Ghostscript rasterizer's
430      *	cache logic we use UniqueID to identify fonts.
431      *  Note that with buggy documents, which don't
432      *	undefine UniqueID redefining a font,
433      *	Ghostscript PS interpreter can occasionaly
434      *	replace cache elements on insufficient cache size,
435      *	taking glyphs from random fonts with random metrics,
436      *	therefore the compatibility isn't complete.
437      */
438     /*
439      *	This branch is incompatible with pdf_notify_remove_font.
440      */
441     if (font->FontType == ft_composite || font->PaintType != 0 ||
442 	!uid_is_valid(&(((gs_font_base *)font)->UID)))
443 	return font->id;
444     else
445 	return ((gs_font_base *)font)->UID.id;
446 #else
447     return font->id;
448 #endif
449 }
450 
451 private pdf_font_cache_elem_t **
pdf_locate_font_cache_elem(gx_device_pdf * pdev,gs_font * font)452 pdf_locate_font_cache_elem(gx_device_pdf *pdev, gs_font *font)
453 {
454     pdf_font_cache_elem_t **e = &pdev->font_cache;
455     long id = pdf_font_cache_elem_id(font);
456 
457     for (; *e != 0; e = &(*e)->next)
458 	if ((*e)->font_id == id) {
459 	    return e;
460 	}
461     return 0;
462 }
463 
464 private void
pdf_remove_font_cache_elem(pdf_font_cache_elem_t * e0)465 pdf_remove_font_cache_elem(pdf_font_cache_elem_t *e0)
466 {
467     gx_device_pdf *pdev = e0->pdev;
468     pdf_font_cache_elem_t **e = &pdev->font_cache;
469 
470     for (; *e != 0; e = &(*e)->next)
471 	if (*e == e0) {
472 	    *e = e0->next;
473 	    gs_free_object(pdev->pdf_memory, e0->glyph_usage,
474 				"pdf_remove_font_cache_elem");
475 	    gs_free_object(pdev->pdf_memory, e0->real_widths,
476 				"pdf_remove_font_cache_elem");
477 	    e0->glyph_usage = 0;
478 	    e0->real_widths = 0;
479 	    gs_free_object(pdev->pdf_memory, e0,
480 				"pdf_remove_font_cache_elem");
481 	    return;
482 	}
483 }
484 
485 private void
font_cache_elem_array_sizes(gx_device_pdf * pdev,gs_font * font,int * num_widths,int * num_chars)486 font_cache_elem_array_sizes(gx_device_pdf *pdev, gs_font *font,
487 			    int *num_widths, int *num_chars)
488 {
489     switch (font->FontType) {
490     case ft_composite:
491 	*num_widths = 0; /* Unused for Type 0 */
492 	*num_chars = 65536; /* No chance to determine, use max. */
493 	break;
494     case ft_encrypted:
495     case ft_encrypted2:
496     case ft_user_defined:
497     case ft_disk_based:
498     case ft_Chameleon:
499     case ft_TrueType:
500 	*num_widths = *num_chars = 256; /* Assuming access to glyph_usage by character codes */
501 	break;
502     case ft_CID_encrypted:
503 	*num_widths = *num_chars = ((gs_font_cid0 *)font)->cidata.common.CIDCount;
504 	break;
505     case ft_CID_TrueType:
506 	*num_widths = *num_chars = ((gs_font_cid2 *)font)->cidata.common.CIDCount;
507 	break;
508     default:
509 	*num_widths = *num_chars = 65536; /* No chance to determine, use max. */
510     }
511 }
512 
513 private int
alloc_font_cache_elem_arrays(gx_device_pdf * pdev,pdf_font_cache_elem_t * e,gs_font * font)514 alloc_font_cache_elem_arrays(gx_device_pdf *pdev, pdf_font_cache_elem_t *e,
515 			     gs_font *font)
516 {
517     int num_widths, num_chars, len;
518 
519     font_cache_elem_array_sizes(pdev, font, &num_widths, &num_chars);
520     len = (num_chars + 7) / 8;
521     e->glyph_usage = gs_alloc_bytes(pdev->pdf_memory,
522 			len, "alloc_font_cache_elem_arrays");
523 
524     e->real_widths = (num_widths > 0 ? (double *)gs_alloc_bytes(pdev->pdf_memory,
525 			num_widths * sizeof(*e->real_widths) *
526 			    (font->FontType == ft_user_defined ? 2 : 1),
527 			"alloc_font_cache_elem_arrays") : NULL);
528     if (e->glyph_usage == NULL || (num_widths !=0 && e->real_widths == NULL)) {
529 	gs_free_object(pdev->pdf_memory, e->glyph_usage,
530 			    "pdf_attach_font_resource");
531 	gs_free_object(pdev->pdf_memory, e->real_widths,
532 			    "alloc_font_cache_elem_arrays");
533 	return_error(gs_error_VMerror);
534     }
535     e->num_chars = num_chars;
536     e->num_widths = num_widths;
537     memset(e->glyph_usage, 0, len);
538     memset(e->real_widths, 0, num_widths * sizeof(*e->real_widths));
539     return 0;
540 }
541 
542 int
pdf_free_font_cache(gx_device_pdf * pdev)543 pdf_free_font_cache(gx_device_pdf *pdev)
544 {
545     /* fixme : release elements. */
546     pdev->font_cache = NULL;
547     return 0;
548 }
549 
550 
551 /*
552  * Retrive font resource attached to a font,
553  * allocating glyph_usage and real_widths on request.
554  */
555 int
pdf_attached_font_resource(gx_device_pdf * pdev,gs_font * font,pdf_font_resource_t ** pdfont,byte ** glyph_usage,double ** real_widths,int * num_chars,int * num_widths)556 pdf_attached_font_resource(gx_device_pdf *pdev, gs_font *font,
557 			    pdf_font_resource_t **pdfont, byte **glyph_usage,
558 			    double **real_widths, int *num_chars, int *num_widths)
559 {
560     pdf_font_cache_elem_t **e = pdf_locate_font_cache_elem(pdev, font);
561 
562     if (e != NULL && (((*e)->glyph_usage == NULL && glyph_usage !=NULL) ||
563 		      ((*e)->real_widths == NULL && real_widths !=NULL))) {
564 	int code = alloc_font_cache_elem_arrays(pdev, *e, font);
565 
566 	if (code < 0)
567 	    return code;
568     }
569     *pdfont = (e == NULL ? NULL : (*e)->pdfont);
570     if (glyph_usage != NULL)
571 	*glyph_usage = (e == NULL ? NULL : (*e)->glyph_usage);
572     if (real_widths != NULL)
573 	*real_widths = (e == NULL ? NULL : (*e)->real_widths);
574     if (num_chars != NULL)
575 	*num_chars = (e == NULL ? 0 : (*e)->num_chars);
576     if (num_widths != NULL)
577 	*num_widths = (e == NULL ? 0 : (*e)->num_widths);
578     return 0;
579 }
580 
581 private int
pdf_notify_remove_font(void * proc_data,void * event_data)582 pdf_notify_remove_font(void *proc_data, void *event_data)
583 {   /* gs_font_finalize passes event_data == NULL, so check it here. */
584     if (event_data == NULL)
585 	pdf_remove_font_cache_elem((pdf_font_cache_elem_t *)proc_data);
586     return 0;
587 }
588 
589 /*
590  * Attach font resource to a font.
591  */
592 int
pdf_attach_font_resource(gx_device_pdf * pdev,gs_font * font,pdf_font_resource_t * pdfont)593 pdf_attach_font_resource(gx_device_pdf *pdev, gs_font *font,
594 			 pdf_font_resource_t *pdfont)
595 {
596     int num_chars, num_widths, len;
597     pdf_font_cache_elem_t *e, **pe = pdf_locate_font_cache_elem(pdev, font);
598 
599     if (pdfont->FontType != font->FontType)
600 	return_error(gs_error_unregistered); /* Must not happen. */
601     font_cache_elem_array_sizes(pdev, font, &num_widths, &num_chars);
602     len = (num_chars + 7) / 8;
603     if (pe != NULL) {
604 	e = *pe;
605 	if (e->pdfont == pdfont)
606 	    return 0;
607 	e->pdfont = pdfont;
608 	/* Reset glyph cache because e->pdfont had changed. */
609 	memset(e->glyph_usage, 0, len);
610 	memset(e->real_widths, 0, num_widths * sizeof(*e->real_widths));
611     } else {
612 	int code;
613 	e = (pdf_font_cache_elem_t *)gs_alloc_struct(pdev->pdf_memory,
614 		pdf_font_cache_elem_t, &st_pdf_font_cache_elem,
615 			    "pdf_attach_font_resource");
616 	if (e == NULL)
617 	    return_error(gs_error_VMerror);
618 	e->pdfont = pdfont;
619 	e->font_id = pdf_font_cache_elem_id(font);
620 	e->num_chars = 0;
621 	e->glyph_usage = NULL;
622 	e->real_widths = NULL;
623 	e->pdev = pdev;
624 	e->next = pdev->font_cache;
625 	pdev->font_cache = e;
626 	code = gs_notify_register(&font->notify_list, pdf_notify_remove_font, e);
627 	if (code < 0)
628 	    return code;
629     }
630     return 0;
631 }
632 
633 /* ================ Process text ================ */
634 
635 /* ---------------- Internal utilities ---------------- */
636 
637 /*
638  * Compute and return the orig_matrix of a font.
639  */
640 int
pdf_font_orig_matrix(const gs_font * font,gs_matrix * pmat)641 pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat)
642 {
643     switch (font->FontType) {
644     case ft_composite:		/* subfonts have their own FontMatrix */
645     case ft_TrueType:
646     case ft_CID_TrueType:
647 	/* The TrueType FontMatrix is 1 unit per em, which is what we want. */
648 	gs_make_identity(pmat);
649 	return 0;
650     case ft_encrypted:
651     case ft_encrypted2:
652     case ft_CID_encrypted:
653     case ft_user_defined:
654 	/*
655          * Type 1 fonts are supposed to use a standard FontMatrix of
656          * [0.001 0 0 0.001 0 0], with a 1000-unit cell.  However,
657          * Windows NT 4.0 creates Type 1 fonts, apparently derived from
658          * TrueType fonts, that use a 2048-unit cell and corresponding
659          * FontMatrix.  Also, some PS programs perform font scaling by
660          * replacing FontMatrix like this :
661          *
662          *   /f12 /Times-Roman findfont
663          *   copyfont	  % (remove FID)
664          *   dup /FontMatrix [0.012 0 0 0.012 0 0] put
665          *   definefont
666          *   /f12 1 selectfont
667          *
668          * Such fonts are their own "base font", but the orig_matrix
669          * must still be set to 0.001, not 0.012 .
670          *
671          * The old code used a heuristic to detect and correct for this here.
672 	 * Unfortunately it doesn't work properly when it meets a font
673 	 * with FontMatrix like this :
674 	 *
675 	 *   /FontMatrix [1 2288 div 0 0 1 2288 div 0 0 ] def
676 	 *
677 	 * (the bug 686970). Also comparefiles\455690.pdf appears to
678 	 * have similar problem. Therefore we added a support to lib/gs_fonts.ps,
679 	 * src/zbfont.c, src/gsfont.c that provides an acces to the original
680 	 * font via a special key .OrigFont added to the font dictionary while definefont.
681 	 * Now we work through this access with PS interpreter,
682 	 * but keep the old heuristic for other clients.
683 	 */
684 	{
685 	    const gs_font *base_font = font;
686 
687 	    while (base_font->base != base_font)
688 		base_font = base_font->base;
689 	    if (font->FontType == ft_user_defined)
690 		*pmat = base_font->FontMatrix;
691 	    else if (base_font->orig_FontMatrix.xx != 0 || base_font->orig_FontMatrix.xy != 0 ||
692 	        base_font->orig_FontMatrix.yx != 0 || base_font->orig_FontMatrix.yy != 0)
693 		*pmat = base_font->orig_FontMatrix;
694 	    else {
695 		/*  Must not happen with PS interpreter.
696 		    Provide a hewuristic for other clients.
697 		*/
698 		if (base_font->FontMatrix.xx == 1.0/2048 &&
699 		    base_font->FontMatrix.xy == 0 &&
700 		    base_font->FontMatrix.yx == 0 &&
701 		    any_abs(base_font->FontMatrix.yy) == 1.0/2048
702 		    )
703 		    *pmat = base_font->FontMatrix;
704 		else
705 		    gs_make_scaling(0.001, 0.001, pmat);
706 	    }
707 	}
708 	return 0;
709     default:
710 	return_error(gs_error_rangecheck);
711     }
712 }
713 
714 int
font_orig_scale(const gs_font * font,double * sx)715 font_orig_scale(const gs_font *font, double *sx)
716 {
717     gs_matrix mat;
718     int code = pdf_font_orig_matrix(font, &mat);
719 
720     if (code < 0)
721 	return code;
722     *sx = mat.xx;
723     return 0;
724 }
725 
726 /*
727  * Check the Encoding compatibility
728  */
729 bool
pdf_check_encoding_compatibility(const pdf_font_resource_t * pdfont,const pdf_char_glyph_pair_t * pairs,int num_chars)730 pdf_check_encoding_compatibility(const pdf_font_resource_t *pdfont,
731 	    const pdf_char_glyph_pair_t *pairs, int num_chars)
732 {
733     int i;
734 
735     for (i = 0; i < num_chars; ++i) {
736 	gs_char ch = pairs[i].chr;
737 	pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
738 
739 	if (pairs[i].glyph == pet->glyph)
740 	    continue;
741 	if (pet->glyph != GS_NO_GLYPH) /* encoding conflict */
742 	    return false;
743     }
744     return true;
745 }
746 
747 /*
748  * Check font resource for encoding compatibility.
749  */
750 private bool
pdf_is_compatible_encoding(gx_device_pdf * pdev,pdf_font_resource_t * pdfont,gs_font * font,const pdf_char_glyph_pair_t * pairs,int num_chars)751 pdf_is_compatible_encoding(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
752 			   gs_font *font, const pdf_char_glyph_pair_t *pairs, int num_chars)
753 {
754     /*
755      * This crude version of the code ignores
756      * the possibility of re-encoding characters.
757      */
758     switch (pdfont->FontType) {
759     case ft_composite:
760 	{   /*
761 	     * We assume that source document don't redefine CMap
762 	     * resources and that incremental CMaps do not exist.
763 	     * Therefore we don't maintain stable CMap copies,
764 	     * but just compare CMap names for equality.
765 	     * A better implementation should compare the chars->glyphs
766 	     * translation against the stable copy of CMap,
767 	     * which to be handled with PDF CMap resource.
768 	     */
769 	    gs_font_type0 *pfont = (gs_font_type0 *)font;
770 
771 	    if (pfont->data.FMapType == fmap_CMap) {
772 		const gs_cmap_t *pcmap = pfont->data.CMap;
773 		const gs_const_string *s0 = &pdfont->u.type0.CMapName;
774 		const gs_const_string *s1 = &pcmap->CMapName;
775 
776 		return (s0->size == s1->size &&
777 			!memcmp(s0->data, s1->data, s0->size));
778 	    }
779 	}
780 	return false;
781     case ft_user_defined:
782 	if (pdfont->u.simple.Encoding == NULL)
783 	    return false; /* Not sure. Happens with 020-01.ps . */
784 	/* fall through */
785     case ft_encrypted:
786     case ft_encrypted2:
787     case ft_TrueType:
788 	return pdf_check_encoding_compatibility(pdfont, pairs, num_chars);
789     case ft_CID_encrypted:
790     case ft_CID_TrueType:
791 	{
792 	    gs_font *font1 = (gs_font *)pdf_font_resource_font(pdfont, false);
793 
794 	    return gs_is_CIDSystemInfo_compatible(
795 				gs_font_cid_system_info(font),
796 				gs_font_cid_system_info(font1));
797 	}
798     default:
799 	return false;
800     }
801 }
802 
803 /*
804  * Find a font resource compatible with a given font.
805  */
806 private int
pdf_find_font_resource(gx_device_pdf * pdev,gs_font * font,pdf_resource_type_t type,pdf_font_resource_t ** ppdfont,pdf_char_glyph_pairs_t * cgp)807 pdf_find_font_resource(gx_device_pdf *pdev, gs_font *font,
808 		       pdf_resource_type_t type,
809 		       pdf_font_resource_t **ppdfont,
810 		       pdf_char_glyph_pairs_t *cgp)
811 {
812     pdf_resource_t **pchain = pdev->resources[type].chains;
813     pdf_resource_t *pres;
814     int i;
815 
816     for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
817 	for (pres = pchain[i]; pres != 0; pres = pres->next) {
818 	    pdf_font_resource_t *pdfont = (pdf_font_resource_t *)pres;
819 	    const gs_font_base *cfont;
820 	    gs_font *ofont = font;
821 	    int code;
822 
823 	    if (font->FontType != pdfont->FontType)
824 		continue;
825 	    if (pdfont->FontType == ft_composite) {
826 		gs_font_type0 *font0 = (gs_font_type0 *)font;
827 
828 		ofont = font0->data.FDepVector[0]; /* See pdf_make_font_resource. */
829 		cfont = pdf_font_resource_font(pdfont->u.type0.DescendantFont, false);
830 		if (font0->data.CMap->WMode != pdfont->u.type0.WMode)
831 		    continue;
832 	    } else
833 		cfont = pdf_font_resource_font(pdfont, false);
834 	    if (!pdf_is_CID_font(ofont) &&
835 		!pdf_is_compatible_encoding(pdev, pdfont, font, cgp->s, cgp->num_all_chars))
836 		continue;
837 	    if (cfont == 0)
838 		continue;
839 	    code = gs_copied_can_copy_glyphs((const gs_font *)cfont, ofont,
840 			    &cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars,
841 			    sizeof(pdf_char_glyph_pair_t), true);
842 	    if (code == gs_error_unregistered) /* Debug purpose only. */
843 		return code;
844 	    if(code > 0) {
845 		*ppdfont = pdfont;
846 		return 1;
847 	    }
848 	}
849     }
850     return 0;
851 }
852 
853 /*
854  * Find a type0 font resource for a gived descendent name and CMap name.
855  */
856 private int
pdf_find_type0_font_resource(gx_device_pdf * pdev,const pdf_font_resource_t * pdsubf,const gs_const_string * CMapName,pdf_font_resource_t ** ppdfont)857 pdf_find_type0_font_resource(gx_device_pdf *pdev, const pdf_font_resource_t *pdsubf,
858 	    const gs_const_string *CMapName, pdf_font_resource_t **ppdfont)
859 {
860     pdf_resource_t **pchain = pdev->resources[resourceFont].chains;
861     pdf_resource_t *pres;
862     int i;
863 
864     for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
865 	for (pres = pchain[i]; pres != 0; pres = pres->next) {
866 	    pdf_font_resource_t *pdfont = (pdf_font_resource_t *)pres;
867 
868 	    if (pdfont->FontType != ft_composite)
869 		continue;
870 	    if (pdfont->u.type0.DescendantFont != pdsubf)
871 		continue;
872 	    if (pdfont->BaseFont.size != pdsubf->BaseFont.size + CMapName->size + 1)
873 		continue;
874 	    if (memcmp(pdfont->BaseFont.data + pdsubf->BaseFont.size + 1,
875 			CMapName->data, CMapName->size))
876 		continue;
877 	    *ppdfont = pdfont;
878 	    return 1;
879 	}
880     }
881     return 0;
882 }
883 
884 
885 private int pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font,
886 		       pdf_font_resource_t **ppdfont,
887 		       pdf_char_glyph_pairs_t *cgp);
888 
889 /*
890  * Create or find a CID font resource object for a glyph set.
891  */
892 int
pdf_obtain_cidfont_resource(gx_device_pdf * pdev,gs_font * subfont,pdf_font_resource_t ** ppdsubf,pdf_char_glyph_pairs_t * cgp)893 pdf_obtain_cidfont_resource(gx_device_pdf *pdev, gs_font *subfont,
894 			    pdf_font_resource_t **ppdsubf,
895 			    pdf_char_glyph_pairs_t *cgp)
896 {
897     int code = 0;
898 
899     pdf_attached_font_resource(pdev, subfont, ppdsubf, NULL, NULL, NULL, NULL);
900     if (*ppdsubf != NULL) {
901 	const gs_font_base *cfont = pdf_font_resource_font(*ppdsubf, false);
902 
903 	code = gs_copied_can_copy_glyphs((const gs_font *)cfont, subfont,
904 			&cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars,
905 			sizeof(pdf_char_glyph_pair_t), true);
906 	if (code > 0)
907 	    return 0;
908 	if (code < 0)
909 	    return code;
910 	*ppdsubf = NULL;
911     }
912     code = pdf_find_font_resource(pdev, subfont,
913 				  resourceCIDFont, ppdsubf, cgp);
914     if (code < 0)
915 	return code;
916     if (*ppdsubf == NULL) {
917 	code = pdf_make_font_resource(pdev, subfont, ppdsubf, cgp);
918 	if (code < 0)
919 	    return code;
920     }
921     return pdf_attach_font_resource(pdev, subfont, *ppdsubf);
922 }
923 
924 /*
925  * Refine index of BaseEncoding.
926  */
927 private int
pdf_refine_encoding_index(const gx_device_pdf * pdev,int index,bool is_standard)928 pdf_refine_encoding_index(const gx_device_pdf *pdev, int index, bool is_standard)
929 {
930     if (pdev->ForOPDFRead) {
931 	/*
932 	* Allow Postscript encodings only.
933 	*/
934 	switch (index) {
935 
936 	    case ENCODING_INDEX_STANDARD: return index;
937 	    case ENCODING_INDEX_ISOLATIN1: return index;
938 	    default:
939 		return ENCODING_INDEX_STANDARD;
940 	}
941     }
942     /*
943      * Per the PDF 1.3 documentation, there are only 3 BaseEncoding
944      * values allowed for non-embedded fonts.  Pick one here.
945      */
946     switch (index) {
947     case ENCODING_INDEX_WINANSI:
948     case ENCODING_INDEX_MACROMAN:
949     case ENCODING_INDEX_MACEXPERT:
950 	return index;
951     case ENCODING_INDEX_STANDARD:
952 	if (is_standard)
953 	    return index;
954 	/* Falls through. */
955     default:
956 	return ENCODING_INDEX_WINANSI;
957     }
958 }
959 
960 /*
961  * Create a font resource object for a gs_font of Type 3.
962  */
963 int
pdf_make_font3_resource(gx_device_pdf * pdev,gs_font * font,pdf_font_resource_t ** ppdfont)964 pdf_make_font3_resource(gx_device_pdf *pdev, gs_font *font,
965 		       pdf_font_resource_t **ppdfont)
966 {
967     const gs_font_base *bfont = (const gs_font_base *)font;
968     pdf_font_resource_t *pdfont;
969     byte *cached;
970     int code;
971 
972     cached = gs_alloc_bytes(pdev->pdf_memory, 256/8, "pdf_make_font3_resource");
973     if (cached == NULL)
974 	return_error(gs_error_VMerror);
975     code = font_resource_encoded_alloc(pdev, &pdfont, bfont->id,
976 		    ft_user_defined, pdf_write_contents_bitmap);
977     if (code < 0) {
978 	gs_free_object(pdev->pdf_memory, cached, "pdf_make_font3_resource");
979 	return code;
980     }
981     memset(cached, 0, 256 / 8);
982     pdfont->u.simple.s.type3.bitmap_font = false;
983     pdfont->u.simple.BaseEncoding = pdf_refine_encoding_index(pdev,
984 			bfont->nearest_encoding_index, true);
985     pdfont->u.simple.s.type3.char_procs = NULL;
986     pdfont->u.simple.s.type3.cached = cached;
987     pdfont->u.simple.s.type3.FontBBox.p.x = (int)floor(bfont->FontBBox.p.x);
988     pdfont->u.simple.s.type3.FontBBox.p.y = (int)floor(bfont->FontBBox.p.y);
989     pdfont->u.simple.s.type3.FontBBox.q.x = (int)ceil(bfont->FontBBox.q.x);
990     pdfont->u.simple.s.type3.FontBBox.q.y = (int)ceil(bfont->FontBBox.q.y);
991     pdfont->u.simple.s.type3.FontMatrix = bfont->FontMatrix;
992     /* Adobe viewers have a precision problem with small font matrices : */
993     while (any_abs(pdfont->u.simple.s.type3.FontMatrix.xx) < 0.001 &&
994 	   any_abs(pdfont->u.simple.s.type3.FontMatrix.xy) < 0.001 &&
995 	   any_abs(pdfont->u.simple.s.type3.FontMatrix.yx) < 0.001 &&
996 	   any_abs(pdfont->u.simple.s.type3.FontMatrix.yy) < 0.001) {
997 	pdfont->u.simple.s.type3.FontMatrix.xx *= 10;
998 	pdfont->u.simple.s.type3.FontMatrix.xy *= 10;
999 	pdfont->u.simple.s.type3.FontMatrix.yx *= 10;
1000 	pdfont->u.simple.s.type3.FontMatrix.yy *= 10;
1001     }
1002     *ppdfont = pdfont;
1003     return 0;
1004 }
1005 
1006 /*
1007  * Create a font resource object for a gs_font.  Return 1 iff the
1008  * font was newly created (it's a roudiment, keeping reverse compatibility).
1009  * This procedure is only intended to be called
1010  * from a few places in the text code.
1011  */
1012 private int
pdf_make_font_resource(gx_device_pdf * pdev,gs_font * font,pdf_font_resource_t ** ppdfont,pdf_char_glyph_pairs_t * cgp)1013 pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font,
1014 		       pdf_font_resource_t **ppdfont,
1015 		       pdf_char_glyph_pairs_t *cgp)
1016 {
1017     int index = -1;
1018     int BaseEncoding = ENCODING_INDEX_UNKNOWN;
1019     pdf_font_embed_t embed;
1020     pdf_font_descriptor_t *pfd = 0;
1021     int (*font_alloc)(gx_device_pdf *, pdf_font_resource_t **,
1022 		      gs_id, pdf_font_descriptor_t *);
1023     gs_font *base_font = font; /* A roudiment from old code. Keep it for a while. */
1024     pdf_font_resource_t *pdfont;
1025     pdf_standard_font_t *const psfa =
1026 	pdev->text->outline_fonts->standard_fonts;
1027     int code = 0;
1028 
1029     if (pdev->version < psdf_version_level2_with_TT) {
1030 	switch(font->FontType) {
1031 	    case ft_TrueType:
1032 	    case ft_CID_TrueType:
1033 		return_error(gs_error_undefined);
1034 	    default:
1035 		break;
1036 	}
1037     }
1038     if (pdev->ForOPDFRead && !pdev->HaveCIDSystem) {
1039 	switch(font->FontType) {
1040 	    case ft_CID_encrypted:
1041 	    case ft_CID_TrueType:
1042 		return_error(gs_error_undefined);
1043 	    default:
1044 		break;
1045 	}
1046     }
1047     if (!pdev->HaveCFF) {
1048 	if (font->FontType == ft_encrypted2)
1049 	    return_error(gs_error_undefined);
1050     }
1051     embed = pdf_font_embed_status(pdev, base_font, &index, cgp->s, cgp->num_all_chars);
1052     if (embed == FONT_EMBED_STANDARD) {
1053 	pdf_standard_font_t *psf = &psfa[index];
1054 
1055 	if (psf->pdfont == NULL ||
1056 		!pdf_is_compatible_encoding(pdev, psf->pdfont, font,
1057 			cgp->s, cgp->num_all_chars)) {
1058 	    code = pdf_font_std_alloc(pdev, ppdfont, (psf->pdfont == NULL), base_font->id,
1059 				      (gs_font_base *)base_font, index);
1060 	    if (code < 0)
1061 		return code;
1062 	    if (psf->pdfont == NULL)
1063 		psf->pdfont = *ppdfont;
1064 	    (*ppdfont)->u.simple.BaseEncoding = pdf_refine_encoding_index(pdev,
1065 		((const gs_font_base *)base_font)->nearest_encoding_index, true);
1066 	    code = 1;
1067 	} else
1068 	    *ppdfont = psf->pdfont;
1069 	return code;
1070     }
1071 
1072     switch (font->FontType) {
1073     case ft_CID_encrypted:
1074     case ft_CID_TrueType:
1075 	font_alloc = pdf_font_cidfont_alloc;
1076 	break;
1077     case ft_encrypted:
1078     case ft_encrypted2:
1079     case ft_TrueType:
1080 	font_alloc = pdf_font_simple_alloc;
1081 	break;
1082     case ft_user_defined:
1083 	code = pdf_make_font3_resource(pdev, font, ppdfont);
1084 	if (code < 0)
1085 	    return code;
1086 	return 1;
1087     default:
1088 	return_error(gs_error_invalidfont);
1089     }
1090 
1091     /* Create an appropriate font resource and descriptor. */
1092     if (embed == FONT_EMBED_YES) {
1093 	/*
1094 	 * HACK: Acrobat Reader 3 has a bug that makes cmap formats 4
1095 	 * and 6 not work in embedded TrueType fonts.  Consequently, it
1096 	 * can only handle embedded TrueType fonts if all the glyphs
1097 	 * referenced by the Encoding have numbers 0-255.  Check for
1098 	 * this now.
1099 	 */
1100 	if (font->FontType == ft_TrueType &&
1101 	    pdev->CompatibilityLevel <= 1.2
1102 	    ) {
1103 	    int i;
1104 
1105 	    for (i = 0; i <= 0xff; ++i) {
1106 		gs_glyph glyph =
1107 		    font->procs.encode_char(font, (gs_char)i,
1108 					    GLYPH_SPACE_INDEX);
1109 
1110 		if (glyph == GS_NO_GLYPH ||
1111 		    (glyph >= GS_MIN_GLYPH_INDEX &&
1112 		     glyph <= GS_MIN_GLYPH_INDEX + 0xff)
1113 		    )
1114 		    continue;
1115 		/* Can't embed, punt. */
1116 		return_error(gs_error_rangecheck);
1117 	    }
1118 	}
1119     }
1120     if (font->FontType == ft_encrypted || font->FontType == ft_encrypted2 ||
1121 	font->FontType == ft_TrueType) {
1122         /*
1123 	 * We write True Types with Symbolic flag set.
1124 	 * PDF spec says that "symbolic font should not specify Encoding entry"
1125 	 * (see section 5.5, the article "Encodings for True Type fonts", paragraph 3).
1126 	 * However Acrobat Reader 4,5,6 fail when TT font with no Encoding
1127 	 * appears in a document together with a CID font with a non-standard CMap
1128 	 * (AR 4 and 5 claim "The encoding (CMap) specified by a font is corrupted."
1129 	 * (we read it as "The encoding or CMap specified by a font is corrupted.",
1130 	 * and apply the 1st alternative)). We believe that AR is buggy,
1131 	 * and therefore we write an Encoding with non-CID True Type fonts.
1132 	 * Hopely other viewers can ignore Encoding in such case. Actually in this case
1133 	 * an Encoding doesn't add an useful information.
1134 	 */
1135 	BaseEncoding = pdf_refine_encoding_index(pdev,
1136 	    ((const gs_font_base *)base_font)->nearest_encoding_index, false);
1137     }
1138     if ((code = pdf_font_descriptor_alloc(pdev, &pfd,
1139 					  (gs_font_base *)base_font,
1140 					  embed == FONT_EMBED_YES)) < 0 ||
1141 	(code = font_alloc(pdev, &pdfont, base_font->id, pfd)) < 0
1142 	)
1143 	return code;
1144     code = 1;
1145 
1146     if (!pdf_is_CID_font(font))
1147 	pdfont->u.simple.BaseEncoding = BaseEncoding;
1148 
1149     *ppdfont = pdfont;
1150     return 1;
1151 }
1152 
1153 /* Get a synthesized Type 3 font scale. */
1154 void
pdf_font3_scale(gx_device_pdf * pdev,gs_font * font,double * scale)1155 pdf_font3_scale(gx_device_pdf *pdev, gs_font *font, double *scale)
1156 {
1157     pdf_font_resource_t *pdfont;
1158 
1159     pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
1160     *scale = pdfont->u.simple.s.type3.FontMatrix.xx;
1161 }
1162 
1163 /*
1164  * Check for simple font.
1165  */
1166 bool
pdf_is_simple_font(gs_font * font)1167 pdf_is_simple_font(gs_font *font)
1168 {
1169     return (font->FontType == ft_encrypted ||
1170 	    font->FontType == ft_encrypted2 ||
1171 	    font->FontType == ft_TrueType ||
1172 	    font->FontType == ft_user_defined);
1173 }
1174 
1175 /*
1176  * Check for CID font.
1177  */
1178 bool
pdf_is_CID_font(gs_font * font)1179 pdf_is_CID_font(gs_font *font)
1180 {
1181     return (font->FontType == ft_CID_encrypted ||
1182 	    font->FontType == ft_CID_TrueType);
1183 }
1184 
1185 /*
1186  * Enumerate glyphs for a text.
1187  */
1188 private int
pdf_next_char_glyph(gs_text_enum_t * penum,const gs_string * pstr,gs_font * font,bool font_is_simple,gs_char * char_code,gs_char * cid,gs_glyph * glyph)1189 pdf_next_char_glyph(gs_text_enum_t *penum, const gs_string *pstr,
1190 	       /* const */ gs_font *font, bool font_is_simple,
1191 	       gs_char *char_code, gs_char *cid, gs_glyph *glyph)
1192 {
1193     int code = font->procs.next_char_glyph(penum, char_code, glyph);
1194 
1195     if (code == 2)		/* end of string */
1196 	return code;
1197     if (code < 0)
1198 	return code;
1199     if (font_is_simple) {
1200 	*cid = *char_code;
1201 	*glyph = font->procs.encode_char(font, *char_code, GLYPH_SPACE_NAME);
1202 	if (*glyph == GS_NO_GLYPH)
1203 	    return 3;
1204     } else {
1205 	if (*glyph < GS_MIN_CID_GLYPH)
1206 	    return 3; /* Not sure why, copied from scan_cmap_text. */
1207 	*cid = *glyph - GS_MIN_CID_GLYPH; /* CID */
1208     }
1209     return 0;
1210 }
1211 
1212 private void
store_glyphs(pdf_char_glyph_pairs_t * cgp,byte * glyph_usage,int char_cache_size,gs_char char_code,gs_char cid,gs_glyph glyph)1213 store_glyphs(pdf_char_glyph_pairs_t *cgp,
1214 	     byte *glyph_usage, int char_cache_size,
1215 	     gs_char char_code, gs_char cid, gs_glyph glyph)
1216 {
1217     int j;
1218 
1219     for (j = 0; j < cgp->num_all_chars; j++)
1220 	if (cgp->s[j].chr == cid)
1221 	    break;
1222     if (j < cgp->num_all_chars)
1223 	return;
1224     cgp->s[cgp->num_all_chars].glyph = glyph;
1225     cgp->s[cgp->num_all_chars].chr = char_code;
1226     cgp->num_all_chars++;
1227     if (glyph_usage == 0 || !(glyph_usage[cid / 8] & (0x80 >> (cid & 7)))) {
1228 	cgp->s[cgp->unused_offset + cgp->num_unused_chars].glyph = glyph;
1229     	cgp->s[cgp->unused_offset + cgp->num_unused_chars].chr = char_code;
1230 	cgp->num_unused_chars++;
1231     }
1232     /* We are disliked that gs_copied_can_copy_glyphs can get redundant
1233      * glyphs, if Encoding specifies several codes for same glyph.
1234      * But we need the positional correspondence
1235      * of glyphs to codes for pdf_is_compatible_encoding.
1236      * Redundant glyphs isn't a big payment for it
1237      * because they happen seldom.
1238      */
1239 }
1240 
1241 /* Allocate storage for the glyph set of the text. */
1242 private int
pdf_alloc_text_glyphs_table(gx_device_pdf * pdev,pdf_text_enum_t * penum,const gs_string * pstr)1243 pdf_alloc_text_glyphs_table(gx_device_pdf *pdev, pdf_text_enum_t *penum, const gs_string *pstr)
1244 {
1245     const int go = (pstr != NULL ? pstr->size : penum->text.size);
1246     const int struct_size = sizeof(pdf_char_glyph_pairs_t) +
1247 			    sizeof(pdf_char_glyph_pair_t) * (2 * go - 1);
1248     pdf_char_glyph_pairs_t *cgp = (pdf_char_glyph_pairs_t *)gs_alloc_bytes(penum->memory,
1249 		struct_size, "pdf_alloc_text_glyphs_table");
1250     if (cgp == NULL)
1251 	return_error(gs_error_VMerror);
1252     penum->cgp = cgp;
1253     cgp->unused_offset = go;
1254     cgp->num_all_chars = 0;
1255     cgp->num_unused_chars = 0;
1256     return 0;
1257 }
1258 
1259 /* Build the glyph set of the text. */
1260 private int
pdf_make_text_glyphs_table(pdf_text_enum_t * penum,const gs_string * pstr,byte * glyph_usage,int char_cache_size)1261 pdf_make_text_glyphs_table(pdf_text_enum_t *penum, const gs_string *pstr,
1262 		byte *glyph_usage, int char_cache_size)
1263 {
1264     gs_text_enum_t scan = *(gs_text_enum_t *)penum;
1265     gs_font *font = (gs_font *)penum->current_font;
1266     bool font_is_simple = pdf_is_simple_font(font);
1267     pdf_char_glyph_pairs_t *cgp = penum->cgp;
1268     gs_char char_code, cid;
1269     gs_glyph glyph;
1270     int code;
1271 
1272     cgp->num_unused_chars = 0;
1273     cgp->num_all_chars = 0;
1274     if (pstr != NULL) {
1275 	scan.text.data.bytes = pstr->data;
1276 	scan.text.size = pstr->size;
1277 	scan.index = 0;
1278         /* if TEXT_FROM_CHARS the data was converted to bytes earlier */
1279         if ( scan.text.operation & TEXT_FROM_CHARS )
1280             scan.text.operation = ((scan.text.operation & ~TEXT_FROM_CHARS) | TEXT_FROM_STRING);
1281     }
1282     for (;;) {
1283 	code = pdf_next_char_glyph(&scan, pstr, font, font_is_simple,
1284 				   &char_code, &cid, &glyph);
1285 	if (code == 2)		/* end of string */
1286 	    break;
1287 	if (code == 3)		/* no glyph */
1288 	    continue;
1289 	if (code < 0)
1290 	    return code;
1291 	if (cgp->num_all_chars > cgp->unused_offset)
1292 	    return_error(gs_error_unregistered); /* Must not happen. */
1293 	if (glyph_usage != 0 && cid > char_cache_size)
1294 	    continue;
1295 	store_glyphs(cgp, glyph_usage, char_cache_size,
1296 		     char_code, cid, glyph);
1297     }
1298     return 0;
1299 }
1300 
1301 /* Build the glyph set of the glyphshow text, and re_encode the text. */
1302 private int
pdf_make_text_glyphs_table_unencoded(pdf_char_glyph_pairs_t * cgp,gs_font * font,const gs_string * pstr,const gs_glyph * gdata,int * ps_encoding_index)1303 pdf_make_text_glyphs_table_unencoded(pdf_char_glyph_pairs_t *cgp,
1304 		gs_font *font, const gs_string *pstr, const gs_glyph *gdata,
1305 		int *ps_encoding_index)
1306 {
1307     int i, ei;
1308     gs_char ch;
1309     gs_const_string gname;
1310     gs_glyph *gid = (gs_glyph *)pstr->data; /* pdf_text_process allocs enough space. */
1311 
1312     /* Translate glyph name indices into gscencs.c indices. */
1313     for (i = 0; i < pstr->size; i++) {
1314 	int code = font->procs.glyph_name(font, gdata[i], &gname);
1315 
1316 	if (code < 0)
1317 	    return code;
1318 	gid[i] = gs_c_name_glyph(gname.data, gname.size);
1319 	if (gid[i] == GS_NO_GLYPH)
1320 	    return_error(gs_error_rangecheck);
1321     }
1322 
1323     /* Find an acceptable encodng. */
1324     for (ei = 0; gs_c_known_encodings[ei]; ei++) {
1325 	cgp->num_unused_chars = 0;
1326 	cgp->num_all_chars = 0;
1327 	for (i = 0; i < pstr->size; i++) {
1328 	    ch = gs_c_decode(gid[i], ei);
1329 	    if (ch == GS_NO_CHAR)
1330 		break;
1331 	    /* pstr->data[i] = (byte)ch; Can't do because pstr->data and gid
1332 	       are same pointer. Will do in a separate pass below. */
1333 	    store_glyphs(cgp, NULL, 0,
1334 			 ch, ch, gdata[i]);
1335 	}
1336 	*ps_encoding_index = ei;
1337 	if (i == pstr->size) {
1338 	    for (i = 0; i < pstr->size; i++)
1339 		pstr->data[i] = (byte)gs_c_decode(gid[i], ei);
1340 	    return 0;
1341 	}
1342     }
1343     return_error(gs_error_rangecheck);
1344 }
1345 
1346 
1347 /* Get/make font resource for the font with a known encoding. */
1348 private int
pdf_obtain_font_resource_encoded(gx_device_pdf * pdev,gs_font * font,pdf_font_resource_t ** ppdfont,pdf_char_glyph_pairs_t * cgp)1349 pdf_obtain_font_resource_encoded(gx_device_pdf *pdev, gs_font *font,
1350 	pdf_font_resource_t **ppdfont, pdf_char_glyph_pairs_t *cgp)
1351 {
1352     int code;
1353     pdf_font_resource_t *pdfont_not_allowed = NULL;
1354 
1355     if (*ppdfont != 0) {
1356 	gs_font_base *cfont = pdf_font_resource_font(*ppdfont, false);
1357 
1358 	if (font->FontType != ft_user_defined) {
1359 	    code = gs_copied_can_copy_glyphs((gs_font *)cfont, font,
1360 			&cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars,
1361 			sizeof(pdf_char_glyph_pair_t), true);
1362 	    if (code < 0)
1363 		return code;
1364 	} else
1365 	    code = 1;
1366 	if (code == 0) {
1367 	    pdfont_not_allowed = *ppdfont;
1368 	    *ppdfont = 0;
1369 	} else if(!pdf_is_compatible_encoding(pdev, *ppdfont, font,
1370 			cgp->s, cgp->num_all_chars)) {
1371 	    pdfont_not_allowed = *ppdfont;
1372 	    *ppdfont = 0;
1373 	}
1374     }
1375     if (*ppdfont == 0) {
1376 	gs_font *base_font = font;
1377 	gs_font *below;
1378 	bool same_encoding = true;
1379 
1380 	/*
1381 	 * Find the "lowest" base font that has the same outlines.
1382 	 * We use its FontName for font resource.
1383 	 */
1384 	while ((below = base_font->base) != base_font &&
1385 	       base_font->procs.same_font(base_font, below, FONT_SAME_OUTLINES))
1386 	    base_font = below;
1387 	if (base_font != font)
1388 	    same_encoding = ((base_font->procs.same_font(base_font, font,
1389 	                      FONT_SAME_ENCODING) & FONT_SAME_ENCODING) != 0);
1390 	/* Find or make font resource. */
1391 	pdf_attached_font_resource(pdev, base_font, ppdfont, NULL, NULL, NULL, NULL);
1392 	if (*ppdfont != NULL && base_font != font) {
1393 	    if (pdfont_not_allowed == *ppdfont)
1394 		*ppdfont = NULL;
1395 	    else if(!pdf_is_compatible_encoding(pdev, *ppdfont,
1396 				    base_font, cgp->s, cgp->num_all_chars))
1397 		*ppdfont = NULL;
1398 	}
1399 	if (*ppdfont == NULL || *ppdfont == pdfont_not_allowed) {
1400 	    pdf_resource_type_t type =
1401 		(pdf_is_CID_font(base_font) ? resourceCIDFont
1402 					    : resourceFont);
1403 	    *ppdfont = NULL;
1404     	    code = pdf_find_font_resource(pdev, base_font, type, ppdfont, cgp);
1405 	    if (code < 0)
1406 		return code;
1407 	    if (*ppdfont == NULL) {
1408 		code = pdf_make_font_resource(pdev, base_font, ppdfont, cgp);
1409 		if (code < 0)
1410 		    return code;
1411 	    }
1412 	    if (base_font != font && same_encoding) {
1413 		code = pdf_attach_font_resource(pdev, base_font, *ppdfont);
1414 		if (code < 0)
1415 		    return code;
1416 	    }
1417 	}
1418 	code = pdf_attach_font_resource(pdev, font, *ppdfont);
1419 	if (code < 0)
1420 	    return code;
1421     }
1422     return 0;
1423 }
1424 
1425 /* Mark glyphs used in the text with the font resource. */
1426 private int
pdf_mark_text_glyphs(const gs_text_enum_t * penum,const gs_string * pstr,byte * glyph_usage,int char_cache_size)1427 pdf_mark_text_glyphs(const gs_text_enum_t *penum, const gs_string *pstr,
1428 	    byte *glyph_usage, int char_cache_size)
1429 {
1430     gs_text_enum_t scan = *penum;
1431     gs_font *font = (gs_font *)penum->current_font;
1432     bool font_is_simple = pdf_is_simple_font(font);
1433     gs_char char_code, cid;
1434     gs_glyph glyph;
1435 
1436     if (pstr != NULL) {
1437 	scan.text.data.bytes = pstr->data;
1438 	scan.text.size = pstr->size;
1439 	scan.index = 0;
1440         /* if TEXT_FROM_CHARS the data was converted to bytes earlier */
1441         if ( scan.text.operation & TEXT_FROM_CHARS )
1442             scan.text.operation =
1443                 ((scan.text.operation & ~TEXT_FROM_CHARS) | TEXT_FROM_STRING);
1444     }
1445     for (;;) {
1446 	int code = pdf_next_char_glyph(&scan, pstr, font, font_is_simple,
1447 				       &char_code, &cid, &glyph);
1448 
1449 	if (code == 2)		/* end of string */
1450 	    break;
1451 	if (code == 3)		/* no glyph */
1452 	    continue;
1453 	if (code < 0)
1454 	    return code;
1455 	if (glyph_usage != 0 && cid >= char_cache_size)
1456 	    continue;
1457 	glyph_usage[cid / 8] |= 0x80 >> (cid & 7);
1458     }
1459     return 0;
1460 }
1461 
1462 /* Mark glyphs used in the glyphshow text with the font resource. */
1463 private int
pdf_mark_text_glyphs_unencoded(const gs_text_enum_t * penum,const gs_string * pstr,byte * glyph_usage,int char_cache_size)1464 pdf_mark_text_glyphs_unencoded(const gs_text_enum_t *penum, const gs_string *pstr,
1465 	    byte *glyph_usage, int char_cache_size)
1466 {
1467     int i;
1468 
1469     for(i = 0; i < pstr->size; i++) {
1470 	byte ch = pstr->data[i];
1471 
1472 	if (ch >= char_cache_size)
1473 	    return_error(gs_error_rangecheck);
1474 	glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1475     }
1476     return 0;
1477 }
1478 
1479 /*
1480  * Create or find a font resource object for a text.
1481  */
1482 int
pdf_obtain_font_resource(pdf_text_enum_t * penum,const gs_string * pstr,pdf_font_resource_t ** ppdfont)1483 pdf_obtain_font_resource(pdf_text_enum_t *penum,
1484 	    const gs_string *pstr, pdf_font_resource_t **ppdfont)
1485 {
1486     gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
1487     gs_font *font = (gs_font *)penum->current_font;
1488     byte *glyph_usage = 0;
1489     double *real_widths;
1490     int char_cache_size, width_cache_size;
1491     int code;
1492 
1493     if (font->FontType == ft_composite) {
1494 	/* Must not happen, because we always split composite fonts into descendents. */
1495 	return_error(gs_error_unregistered);
1496     }
1497     code = pdf_attached_font_resource(pdev, font, ppdfont,
1498 			       &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1499     /* *ppdfont is NULL if no resource attached. */
1500     if (code < 0)
1501 	return code;
1502     if (penum->cgp == NULL) {
1503 	code = pdf_alloc_text_glyphs_table(pdev, penum, pstr);
1504 	if (code < 0)
1505 	    return code;
1506 	code = pdf_make_text_glyphs_table(penum, pstr,
1507 			    glyph_usage, char_cache_size);
1508 	if (code < 0)
1509 	    return code;
1510     }
1511     code = pdf_obtain_font_resource_encoded(pdev, font, ppdfont, penum->cgp);
1512     if (code < 0)
1513 	return code;
1514     code = pdf_attached_font_resource(pdev, font, ppdfont,
1515 			       &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1516     if (code < 0)
1517 	return code;
1518     return pdf_mark_text_glyphs((const gs_text_enum_t *)penum, pstr, glyph_usage, char_cache_size);
1519 }
1520 
1521 /*
1522  * Create or find a font resource object for a glyphshow text.
1523  */
1524 int
pdf_obtain_font_resource_unencoded(pdf_text_enum_t * penum,const gs_string * pstr,pdf_font_resource_t ** ppdfont,const gs_glyph * gdata)1525 pdf_obtain_font_resource_unencoded(pdf_text_enum_t *penum,
1526 	    const gs_string *pstr, pdf_font_resource_t **ppdfont, const gs_glyph *gdata)
1527 {
1528     gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
1529     gs_font *font = (gs_font *)penum->current_font;
1530     byte *glyph_usage = 0;
1531     double *real_widths = 0;
1532     int char_cache_size = 0, width_cache_size = 0;
1533     int code, ps_encoding_index;
1534 
1535     if (font->FontType == ft_composite) {
1536 	/* Must not happen, because we always split composite fonts into descendents. */
1537 	return_error(gs_error_unregistered);
1538     }
1539     code = pdf_attached_font_resource(pdev, font, ppdfont,
1540 			       &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1541     if (code < 0)
1542 	return code;
1543     /* *ppdfont is NULL if no resource attached. */
1544     if (penum->cgp == NULL) {
1545 	code = pdf_alloc_text_glyphs_table(pdev, penum, pstr);
1546 	if (code < 0)
1547 	    return code;
1548 	code = pdf_make_text_glyphs_table_unencoded(penum->cgp, font, pstr, gdata,
1549 			    &ps_encoding_index);
1550 	if (code < 0)
1551 	    return code;
1552     }
1553     code = pdf_obtain_font_resource_encoded(pdev, font, ppdfont, penum->cgp);
1554     if (code < 0)
1555 	return code;
1556     code = pdf_attached_font_resource(pdev, font, ppdfont,
1557 			       &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1558     if (code < 0)
1559 	return code;
1560     return pdf_mark_text_glyphs_unencoded((const gs_text_enum_t *)penum,
1561 		    pstr, glyph_usage, char_cache_size);
1562 }
1563 
1564 private inline bool
strings_equal(const gs_const_string * s1,const gs_const_string * s2)1565 strings_equal(const gs_const_string *s1, const gs_const_string *s2)
1566 {
1567     return s1->size == s2->size &&
1568 	    !memcmp(s1->data, s2->data, s1->size);
1569 }
1570 
1571 /*
1572  * Create or find a parent Type 0 font resource object for a CID font resource.
1573  */
1574 int
pdf_obtain_parent_type0_font_resource(gx_device_pdf * pdev,pdf_font_resource_t * pdsubf,const gs_const_string * CMapName,pdf_font_resource_t ** pdfont)1575 pdf_obtain_parent_type0_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdsubf,
1576 		const gs_const_string *CMapName, pdf_font_resource_t **pdfont)
1577 {
1578     if (pdsubf->u.cidfont.parent != 0 &&
1579 	    strings_equal(CMapName, &pdsubf->u.cidfont.parent->u.type0.CMapName))
1580 	*pdfont = pdsubf->u.cidfont.parent;
1581     else {
1582 	/*
1583 	 * PDF spec 1.4 section 5.6 "Composite Fonts" says :
1584 	 *
1585 	 * PDF 1.2 introduces a general architecture for composite fonts that theoretically
1586 	 * allows a Type 0 font to have multiple descendants,which might themselves be
1587 	 * Type 0 fonts.However,in versions up to and including PDF 1.4,only a single
1588 	 * descendant is allowed,which must be a CIDFont (not a font).This restriction
1589 	 * may be relaxed in a future PDF version.
1590 	 */
1591 
1592 	if (pdsubf->u.cidfont.parent == NULL ||
1593 		pdf_find_type0_font_resource(pdev, pdsubf, CMapName, pdfont) <= 0) {
1594 	    int code = pdf_font_type0_alloc(pdev, pdfont, gs_no_id, pdsubf, CMapName);
1595 
1596 	    if (code < 0)
1597 		return code;
1598 	}
1599 	pdsubf->u.cidfont.parent = *pdfont;
1600     }
1601     return 0;
1602 }
1603 
1604 /*
1605  * Compute the cached values in the text processing state from the text
1606  * parameters, current_font, and pis->ctm.  Return either an error code (<
1607  * 0) or a mask of operation attributes that the caller must emulate.
1608  * Currently the only such attributes are TEXT_ADD_TO_ALL_WIDTHS and
1609  * TEXT_ADD_TO_SPACE_WIDTH.  Note that this procedure fills in all the
1610  * values in ppts->values, not just the ones that need to be set now.
1611  */
1612 private int
transform_delta_inverse(const gs_point * pdelta,const gs_matrix * pmat,gs_point * ppt)1613 transform_delta_inverse(const gs_point *pdelta, const gs_matrix *pmat,
1614 			gs_point *ppt)
1615 {
1616     int code = gs_distance_transform_inverse(pdelta->x, pdelta->y, pmat, ppt);
1617     gs_point delta;
1618 
1619     if (code < 0)
1620 	return code;
1621     if (ppt->y == 0)
1622 	return 0;
1623     /* Check for numerical fuzz. */
1624     code = gs_distance_transform(ppt->x, 0.0, pmat, &delta);
1625     if (code < 0)
1626 	return 0;		/* punt */
1627     if (fabs(delta.x - pdelta->x) < 0.01 && fabs(delta.y - pdelta->y) < 0.01) {
1628 	/* Close enough to y == 0: device space error < 0.01 pixel. */
1629 	ppt->y = 0;
1630     }
1631     return 0;
1632 }
1633 int
pdf_update_text_state(pdf_text_process_state_t * ppts,const pdf_text_enum_t * penum,pdf_font_resource_t * pdfont,const gs_matrix * pfmat)1634 pdf_update_text_state(pdf_text_process_state_t *ppts,
1635 		      const pdf_text_enum_t *penum,
1636 		      pdf_font_resource_t *pdfont, const gs_matrix *pfmat)
1637 {
1638     gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
1639     gs_font *font = penum->current_font;
1640     gs_fixed_point cpt;
1641     gs_matrix orig_matrix, smat, tmat;
1642     double
1643 	sx = pdev->HWResolution[0] / 72.0,
1644 	sy = pdev->HWResolution[1] / 72.0;
1645     float size;
1646     float c_s = 0, w_s = 0;
1647     int mask = 0;
1648     int code = gx_path_current_point(penum->path, &cpt);
1649 
1650     if (code < 0)
1651 	return code;
1652 
1653     /* Get the original matrix of the base font. */
1654 
1655     {
1656 	gs_font_base *cfont = pdf_font_resource_font(pdfont, false);
1657 
1658 	if (pdfont->FontType == ft_user_defined)
1659 	    orig_matrix = pdfont->u.simple.s.type3.FontMatrix;
1660 	else if (cfont != 0) {
1661 	    /*
1662 	     * The text matrix to be computed relatively to the
1663 	     * embedded font matrix.
1664 	     */
1665 	    orig_matrix = cfont->FontMatrix;
1666 	} else {
1667 	    /*
1668 	     * We don't embed the font.
1669 	     * The text matrix to be computed relatively to
1670 	     * standard font matrix.
1671 	     */
1672 	    pdf_font_orig_matrix(font, &orig_matrix);
1673 	}
1674     }
1675 
1676     /* Compute the scaling matrix and combined matrix. */
1677 
1678     gs_matrix_invert(&orig_matrix, &smat);
1679     gs_matrix_multiply(&smat, pfmat, &smat);
1680     tmat = ctm_only(penum->pis);
1681     tmat.tx = tmat.ty = 0;
1682     gs_matrix_multiply(&smat, &tmat, &tmat);
1683 
1684     /* Try to find a reasonable size value.  This isn't necessary, */
1685     /* but it's worth a little effort. */
1686 
1687     size = hypot(tmat.yx, tmat.yy) / sy;
1688     if (size < 0.01)
1689 	size = hypot(tmat.xx, tmat.xy) / sx;
1690     if (size < 0.01)
1691 	size = 1;
1692 
1693     /* Check for spacing parameters we can handle, and transform them. */
1694 
1695     if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
1696 	if (penum->current_font->WMode == 0) {
1697 	    gs_point pt;
1698 
1699 	    code = transform_delta_inverse(&penum->text.delta_all, &smat, &pt);
1700 	    if (code >= 0 && pt.y == 0)
1701 		c_s = pt.x * size;
1702 	    else
1703 		mask |= TEXT_ADD_TO_ALL_WIDTHS;
1704 	}
1705 	else
1706 	    mask |= TEXT_ADD_TO_ALL_WIDTHS;
1707     }
1708 
1709     if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
1710 	gs_point pt;
1711 
1712 	code = transform_delta_inverse(&penum->text.delta_space, &smat, &pt);
1713 	if (code >= 0 && pt.y == 0 && penum->text.space.s_char == 32)
1714 	    w_s = pt.x * size;
1715 	else
1716 	    mask |= TEXT_ADD_TO_SPACE_WIDTH;
1717     }
1718     /* Store the updated values. */
1719 
1720     tmat.xx /= size;
1721     tmat.xy /= size;
1722     tmat.yx /= size;
1723     tmat.yy /= size;
1724     tmat.tx += fixed2float(cpt.x);
1725     tmat.ty += fixed2float(cpt.y);
1726 
1727     ppts->values.character_spacing = c_s;
1728     ppts->values.pdfont = pdfont;
1729     ppts->values.size = size;
1730     ppts->values.matrix = tmat;
1731     ppts->values.render_mode = (penum->pis->text_rendering_mode == 3 ? 3 :
1732 				font->PaintType == 0 ? 0 : 1);
1733     ppts->values.word_spacing = w_s;
1734     ppts->font = font;
1735 
1736     code = pdf_set_text_process_state(pdev, (const gs_text_enum_t *)penum,
1737 				      ppts);
1738     return (code < 0 ? code : mask);
1739 }
1740 
1741 /*
1742  * Set up commands to make the output state match the processing state.
1743  * General graphics state commands are written now; text state commands
1744  * are written later.
1745  */
1746 private double
font_matrix_scaling(const gs_font * font)1747 font_matrix_scaling(const gs_font *font)
1748 {
1749     return fabs((font->FontMatrix.yy != 0 ? font->FontMatrix.yy :
1750 		 font->FontMatrix.yx));
1751 }
1752 int
pdf_set_text_process_state(gx_device_pdf * pdev,const gs_text_enum_t * pte,pdf_text_process_state_t * ppts)1753 pdf_set_text_process_state(gx_device_pdf *pdev,
1754 			   const gs_text_enum_t *pte,	/* for pdcolor, pis */
1755 			   pdf_text_process_state_t *ppts)
1756 {
1757     /*
1758      * Setting the stroke parameters may exit text mode, causing the
1759      * settings of the text parameters to be lost.  Therefore, we set the
1760      * stroke parameters first.
1761      */
1762     if (pdf_render_mode_uses_stroke(pdev, &ppts->values)) {
1763 	/* Write all the parameters for stroking. */
1764 	gs_imager_state *pis = pte->pis;
1765 	float save_width = pis->line_params.half_width;
1766 	const gs_font *font = ppts->font;
1767 	double scaled_width = font->StrokeWidth;
1768 	int code;
1769 
1770 	/* Note that we compute pis->line_params.half_width in device space,
1771 	 * even though it logically represents a value in user space.
1772 	 * The 'scale' value compensates for this.
1773 	 */
1774 	scaled_width *= font_matrix_scaling(font);
1775 	scaled_width *= min(hypot(pte->pis->ctm.xx, pte->pis->ctm.yx) /
1776                                 pdev->HWResolution[0] * pdev->HWResolution[1],
1777                             hypot(pte->pis->ctm.xy, pte->pis->ctm.yy));
1778 	pis->line_params.half_width = scaled_width / 2;
1779 	code = pdf_prepare_stroke(pdev, pis);
1780 	if (code >= 0) {
1781 	    /*
1782 	     * See stream_to_text in gdevpdfu.c re the computation of
1783 	     * the scaling value.
1784 	     */
1785 	    double scale = 72.0 / pdev->HWResolution[1];
1786 
1787 	    code = gdev_vector_prepare_stroke((gx_device_vector *)pdev,
1788 					      pis, NULL, NULL, scale);
1789 	}
1790 	pis->line_params.half_width = save_width;
1791 	if (code < 0)
1792 	    return code;
1793     }
1794 
1795     /* Now set all the other parameters. */
1796 
1797     return pdf_set_text_state_values(pdev, &ppts->values);
1798 }
1799 
1800 private int
store_glyph_width(pdf_glyph_width_t * pwidth,int wmode,double scale,const gs_glyph_info_t * pinfo)1801 store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, double scale,
1802 		  const gs_glyph_info_t *pinfo)
1803 {
1804     double w, v;
1805 
1806     pwidth->xy.x = pinfo->width[wmode].x * scale;
1807     pwidth->xy.y = pinfo->width[wmode].y * scale;
1808     if (wmode)
1809 	w = pwidth->xy.y, v = pwidth->xy.x;
1810     else
1811 	w = pwidth->xy.x, v = pwidth->xy.y;
1812     if (v != 0)
1813 	return 1;
1814     pwidth->w = w;
1815     pwidth->v.x = pinfo->v.x * scale;
1816     pwidth->v.y = pinfo->v.y * scale;
1817     return 0;
1818 }
1819 
1820 private int
get_missing_width(gs_font_base * cfont,int wmode,double scale_c,pdf_glyph_widths_t * pwidths)1821 get_missing_width(gs_font_base *cfont, int wmode, double scale_c,
1822 		    pdf_glyph_widths_t *pwidths)
1823 {
1824     gs_font_info_t finfo;
1825     int code;
1826 
1827     code = cfont->procs.font_info((gs_font *)cfont, NULL,
1828 				  FONT_INFO_MISSING_WIDTH, &finfo);
1829     if (code < 0)
1830 	return code;
1831     if (wmode) {
1832 	pwidths->Width.xy.x = pwidths->real_width.xy.x = 0;
1833 	pwidths->Width.xy.y = pwidths->real_width.xy.y =
1834 		- finfo.MissingWidth * scale_c;
1835 	pwidths->Width.w = pwidths->real_width.w =
1836 		pwidths->Width.xy.y;
1837 	pwidths->Width.v.x = - pwidths->Width.xy.y / 2;
1838 	pwidths->Width.v.y = - pwidths->Width.xy.y;
1839     } else {
1840 	pwidths->Width.xy.x = pwidths->real_width.xy.x =
1841 		finfo.MissingWidth * scale_c;
1842 	pwidths->Width.w = pwidths->real_width.w =
1843 		pwidths->Width.xy.x;
1844 	pwidths->Width.xy.y = pwidths->real_width.xy.y = 0;
1845 	pwidths->Width.v.x = pwidths->Width.v.y = 0;
1846     }
1847     /*
1848      * Don't mark the width as known, just in case this is an
1849      * incrementally defined font.
1850      */
1851     return 1;
1852 }
1853 
1854 
1855 /*
1856  * Get the widths (unmodified from the copied font,
1857  * and possibly modified from the original font) of a given glyph.
1858  * Return 1 if the width was defaulted to MissingWidth.
1859  * Return TEXT_PROCESS_CDEVPROC if a CDevProc callout is needed.
1860  * cdevproc_result != NULL if we restart after a CDevProc callout.
1861  */
1862 int
pdf_glyph_widths(pdf_font_resource_t * pdfont,int wmode,gs_glyph glyph,gs_font * orig_font,pdf_glyph_widths_t * pwidths,const double cdevproc_result[10])1863 pdf_glyph_widths(pdf_font_resource_t *pdfont, int wmode, gs_glyph glyph,
1864 		 gs_font *orig_font, pdf_glyph_widths_t *pwidths,
1865 		 const double cdevproc_result[10])
1866 {
1867     gs_font_base *cfont = pdf_font_resource_font(pdfont, false);
1868     gs_font *ofont = orig_font;
1869     gs_glyph_info_t info;
1870     /*
1871      * orig_scale is 1.0 for TrueType, 0.001 or 1.0/2048 for Type 1.
1872      */
1873     double sxc, sxo;
1874     double scale_c, scale_o;
1875     int code, rcode = 0;
1876     gs_point v;
1877     int allow_cdevproc_callout = (orig_font->FontType == ft_CID_TrueType
1878 		|| orig_font->FontType == ft_CID_encrypted
1879 		? GLYPH_INFO_CDEVPROC : 0); /* fixme : allow more font types. */
1880 
1881     if (ofont->FontType == ft_composite)
1882 	return_error(gs_error_unregistered); /* Must not happen. */
1883     code = font_orig_scale((const gs_font *)cfont, &sxc);
1884     if (code < 0)
1885 	return code;
1886     code = font_orig_scale(ofont, &sxo);
1887     if (code < 0)
1888 	return code;
1889     scale_c = sxc * 1000.0;
1890     scale_o = sxo * 1000.0;
1891     pwidths->Width.v.x = pwidths->Width.v.y = 0;
1892     pwidths->real_width.v.x = pwidths->real_width.v.y = 0;
1893     pwidths->replaced_v = false;
1894     if (glyph == GS_NO_GLYPH)
1895 	return get_missing_width(cfont, wmode, scale_c, pwidths);
1896     code = cfont->procs.glyph_info((gs_font *)cfont, glyph, NULL,
1897 				    GLYPH_INFO_WIDTH0 |
1898 				    (GLYPH_INFO_WIDTH0 << wmode) |
1899 				    GLYPH_INFO_OUTLINE_WIDTHS |
1900 				    (GLYPH_INFO_VVECTOR0 << wmode),
1901 				    &info);
1902     /* For CID fonts the PDF spec requires the x-component of v-vector
1903        to be equal to half glyph width, and AR5 takes it from W, DW.
1904        So make a compatibe data here.
1905      */
1906     if (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode))) {
1907 	code = get_missing_width(cfont, wmode, scale_c, pwidths);
1908 	if (code < 0)
1909 	    v.y = 0;
1910 	else
1911 	    v.y = pwidths->Width.v.y;
1912 	if (wmode && pdf_is_CID_font(ofont)) {
1913 	    pdf_glyph_widths_t widths1;
1914 
1915 	    if (get_missing_width(cfont, 0, scale_c, &widths1) < 0)
1916 		v.x = 0;
1917 	    else
1918 		v.x = widths1.Width.w / 2;
1919 	} else
1920 	    v.x = pwidths->Width.v.x;
1921     } else if (code < 0)
1922 	return code;
1923     else {
1924 	code = store_glyph_width(&pwidths->Width, wmode, scale_c, &info);
1925 	if (code < 0)
1926 	    return code;
1927 	rcode |= code;
1928 	if (info.members & (GLYPH_INFO_VVECTOR0 << wmode)) {
1929 	    v.y = info.v.y * scale_c;
1930 	} else
1931 	    v.y = 0;
1932 	if (wmode && pdf_is_CID_font(ofont)) {
1933 	    if (info.members & (GLYPH_INFO_WIDTH0 << wmode)) {
1934 		v.x = info.width[0].x * scale_c / 2;
1935 	    } else {
1936 		pdf_glyph_widths_t widths1;
1937 
1938 		if (get_missing_width(cfont, 0, scale_c, &widths1) < 0)
1939 		    v.x = 0;
1940 		else
1941 		    v.x = widths1.Width.w / 2;
1942 	    }
1943 	} else {
1944 	    if (info.members  & (GLYPH_INFO_VVECTOR0 << wmode)) {
1945 		v.x = info.v.x * scale_c;
1946 	    } else
1947 		v.x = 0;
1948 	}
1949     }
1950     pwidths->Width.v = v;
1951 #if 0
1952     if (code > 0)
1953 	pwidths->Width.xy.x = pwidths->Width.xy.y = pwidths->Width.w = 0;
1954 #else /* Skip only if not paralel to the axis. */
1955     if (code > 0 && !pdf_is_CID_font(ofont))
1956 	pwidths->Width.xy.x = pwidths->Width.xy.y = pwidths->Width.w = 0;
1957 #endif
1958     if (cdevproc_result == NULL) {
1959 	code = ofont->procs.glyph_info(ofont, glyph, NULL,
1960 					    (GLYPH_INFO_WIDTH0 << wmode) |
1961 					    (GLYPH_INFO_VVECTOR0 << wmode) |
1962 					    allow_cdevproc_callout,
1963 					    &info);
1964 	/* fixme : Move this call before cfont->procs.glyph_info. */
1965 	if (info.members & GLYPH_INFO_CDEVPROC) {
1966 	    if (allow_cdevproc_callout)
1967 		return TEXT_PROCESS_CDEVPROC;
1968 	    else
1969 		return_error(gs_error_rangecheck);
1970 	}
1971     } else {
1972 	info.width[0].x = cdevproc_result[0];
1973 	info.width[0].y = cdevproc_result[1];
1974 	info.width[1].x = cdevproc_result[6];
1975 	info.width[1].y = cdevproc_result[7];
1976 	info.v.x = (wmode ? cdevproc_result[8] : 0);
1977 	info.v.y = (wmode ? cdevproc_result[9] : 0);
1978 	info.members = (GLYPH_INFO_WIDTH0 << wmode) |
1979 		       (wmode ? GLYPH_INFO_VVECTOR1 : 0);
1980 	code = 0;
1981     }
1982     if (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))
1983 	pwidths->real_width = pwidths->Width;
1984     else if (code < 0)
1985 	return code;
1986     else {
1987 	if ((info.members & (GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1)) != 0)
1988 	    pwidths->replaced_v = true;
1989 	else
1990 	    info.v.x = info.v.y = 0;
1991 	code = store_glyph_width(&pwidths->real_width, wmode, scale_o, &info);
1992 	if (code < 0)
1993 	    return code;
1994 	rcode |= code;
1995 	pwidths->real_width.v.x = info.v.x * scale_o;
1996 	pwidths->real_width.v.y = info.v.y * scale_o;
1997     }
1998     return rcode;
1999 }
2000 /* ---------------- Main entry ---------------- */
2001 
2002 /*
2003  * Fall back to the default text processing code when needed.
2004  */
2005 int
pdf_default_text_begin(gs_text_enum_t * pte,const gs_text_params_t * text,gs_text_enum_t ** ppte)2006 pdf_default_text_begin(gs_text_enum_t *pte, const gs_text_params_t *text,
2007 		       gs_text_enum_t **ppte)
2008 {
2009     gs_text_params_t text1 = *text;
2010 
2011     if(pte->current_font->FontType == 3 && (text1.operation & TEXT_DO_NONE)) {
2012 	/* We need a real drawing to accumulate charproc. */
2013 	text1.operation &= ~TEXT_DO_NONE;
2014 	text1.operation |= TEXT_DO_DRAW;
2015     }
2016     return gx_default_text_begin(pte->dev, pte->pis, &text1, pte->current_font,
2017 				 pte->path, pte->pdcolor, pte->pcpath,
2018 				 pte->memory, ppte);
2019 }
2020 
2021 /*
2022  * Continue processing text.  This is the 'process' procedure in the text
2023  * enumerator.  Per the check in pdf_text_begin, we know the operation is
2024  * not a charpath, but it could be anything else.
2025  */
2026 int
pdf_text_process(gs_text_enum_t * pte)2027 pdf_text_process(gs_text_enum_t *pte)
2028 {
2029     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
2030     uint operation = pte->text.operation;
2031     uint size = pte->text.size - pte->index;
2032     gs_text_enum_t *pte_default;
2033     PROCESS_TEXT_PROC((*process));
2034     int code;
2035     gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
2036 #define BUF_SIZE 100		/* arbitrary > 0 */
2037     /* Use a union to ensure alignment. */
2038     union bu_ {
2039 	byte bytes[BUF_SIZE];
2040 	gs_char chars[BUF_SIZE / sizeof(gs_char)];
2041 	gs_glyph glyphs[BUF_SIZE / sizeof(gs_glyph)];
2042     } buf;
2043 
2044     if (!penum->pte_default && !penum->charproc_accum) {
2045 	/* Don't need to sync before exiting charproc. */
2046 	code = pdf_prepare_text_drawing(pdev, pte);
2047 	if (code == gs_error_rangecheck) {
2048 	    /* Fallback to the default implermentation for handling
2049 	       a transparency with CompatibilityLevel<=1.3 . */
2050 	    goto default_impl;
2051 	}
2052 	if (penum->outer_CID != GS_NO_GLYPH) {
2053 	    /* Fallback to the default implermentation for handling
2054 	       Type 3 fonts with CIDs, because currently Type 3
2055 	       font resource arrays' sizes are hardcoded to 256 glyphs.
2056 	       A better solution would be to re-encode the CID text with
2057 	       Type 3 glyph variations. */
2058 	    goto default_impl;
2059 	}
2060 	if (code < 0)
2061 	    return code;
2062     }
2063     if (!penum->pte_default) {
2064 	pdev->charproc_just_accumulated = false;
2065 	if (penum->cdevproc_callout) {
2066 	    /* Restore after TEXT_PROCESS_CDEVPROC in scan_cmap_text. */
2067 	    penum->current_font = penum->orig_font;
2068 	}
2069     }
2070     code = -1;		/* to force default implementation */
2071 
2072     /*
2073      * If we fell back to the default implementation, continue using it.
2074      */
2075  top:
2076     pte_default = penum->pte_default;
2077     if (pte_default) {
2078 	if (penum->charproc_accum) {
2079 	    code = pdf_end_charproc_accum(pdev, penum->current_font, penum->cgp);
2080 	    if (code < 0)
2081 		return code;
2082 	    penum->charproc_accum = false;
2083 	    code = gx_default_text_restore_state(pte_default);
2084 	    if (code < 0)
2085 		return code;
2086 	    gs_text_release(pte_default, "pdf_text_process");
2087 	    penum->pte_default = 0;
2088 	    goto top;
2089 	}
2090 	pdev->pte = pte_default; /* CAUTION: See comment in gdevpdfx.h . */
2091 	code = gs_text_process(pte_default);
2092 	pdev->pte = NULL;	 /* CAUTION: See comment in gdevpdfx.h . */
2093 	if (pte->orig_font->FontType != ft_user_defined)
2094 	    gs_text_enum_copy_dynamic(pte, pte_default, true);
2095 	else {
2096 	    penum->returned.current_char = pte_default->returned.current_char;
2097 	    penum->returned.current_glyph = pte_default->returned.current_glyph;
2098 	}
2099 	pdev->charproc_just_accumulated = false;
2100 	if (code == TEXT_PROCESS_RENDER) {
2101 	    pdev->charproc_ctm = penum->pis->ctm;
2102 	    if (penum->current_font->FontType == ft_user_defined &&
2103 		    penum->orig_font->FontType != ft_composite &&
2104 		    penum->outer_CID == GS_NO_GLYPH &&
2105 		    !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
2106 		/* The condition above must be consistent with one in pdf_text_set_cache,
2107 		   which decides to apply pdf_set_charproc_attrs. */
2108 		gs_matrix m;
2109 
2110 		code = pdf_start_charproc_accum(pdev);
2111 		if (code < 0)
2112 		    return code;
2113 		pdf_viewer_state_from_imager_state(pdev, pte->pis, pte->pdcolor);
2114 		/* Set line params to unallowed values so that
2115 		   they'll synchronize with writing them out on the first use.
2116 		   Doing so because PDF viewer inherits them from the
2117 		   contents stream when executing the charproc,
2118 		   but at this moment we don't know in what contexts
2119 		   it will be used. */
2120 		pdev->state.line_params.half_width = -1;
2121 		pdev->state.line_params.cap = gs_cap_unknown;
2122 		pdev->state.line_params.join = gs_join_unknown;
2123 		pdev->state.line_params.miter_limit = -1;
2124 		pdev->state.line_params.dash.pattern_size = -1;
2125 		/* Must set an identity CTM for the charproc accumulation.
2126 		   The function show_proceed (called from gs_text_process above)
2127 		   executed gsave, so we are safe to change CTM now.
2128 		   Note that BuildChar may change CTM before calling setcachedevice. */
2129 		gs_make_identity(&m);
2130 		gs_matrix_fixed_from_matrix(&penum->pis->ctm, &m);
2131 		return TEXT_PROCESS_RENDER;
2132 	    }
2133 	}
2134 	if (code)
2135 	    return code;
2136 	gs_text_release(pte_default, "pdf_text_process");
2137 	penum->pte_default = 0;
2138 	return 0;
2139     }
2140     {
2141 	gs_font *font = pte->orig_font; /* Not sure. Changed for CDevProc callout. Was pte->current_font */
2142 
2143 	switch (font->FontType) {
2144 	case ft_CID_encrypted:
2145 	case ft_CID_TrueType:
2146 	    process = process_cid_text;
2147 	    break;
2148 	case ft_encrypted:
2149 	case ft_encrypted2:
2150 	case ft_TrueType:
2151 	case ft_user_defined:
2152 	    /* The data may be either glyphs or characters. */
2153 	    process = process_plain_text;
2154 	    break;
2155 	case ft_composite:
2156 	    process =
2157 		(((gs_font_type0 *)font)->data.FMapType == fmap_CMap ?
2158 		 process_cmap_text :
2159 		 process_composite_text);
2160 	    break;
2161 	default:
2162 	    goto skip;
2163 	}
2164     }
2165 
2166     /*
2167      * We want to process the entire string in a single call, but we may
2168      * need to modify it.  Copy it to a buffer.  Note that it may consist
2169      * of bytes, gs_chars, or gs_glyphs.
2170      */
2171 
2172     if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES))
2173 	DO_NOTHING;
2174     else if (operation & TEXT_FROM_CHARS)
2175 	size *= sizeof(gs_char);
2176     else if (operation & TEXT_FROM_SINGLE_CHAR)
2177 	size = sizeof(gs_char);
2178     else if (operation & TEXT_FROM_GLYPHS)
2179 	size *= sizeof(gs_glyph);
2180     else if (operation & TEXT_FROM_SINGLE_GLYPH)
2181 	size = sizeof(gs_glyph);
2182     else
2183 	goto skip;
2184 
2185     if (size <= sizeof(buf)) {
2186 	code = process(pte, buf.bytes, size);
2187     } else {
2188 	byte *buf = gs_alloc_string(pte->memory, size, "pdf_text_process");
2189 
2190 	if (buf == 0)
2191 	    return_error(gs_error_VMerror);
2192 	code = process(pte, buf, size);
2193 	gs_free_string(pte->memory, buf, size, "pdf_text_process");
2194     }
2195  skip:
2196     if (code < 0 ||
2197 	    (pte->current_font->FontType == ft_user_defined &&
2198 	     code != TEXT_PROCESS_INTERVENE &&
2199 	    penum->index < penum->text.size)) {
2200 	if (code == gs_error_unregistered) /* Debug purpose only. */
2201 	    return code;
2202 	if (code == gs_error_VMerror)
2203 	    return code;
2204  default_impl:
2205 	/* Fall back to the default implementation. */
2206 	code = pdf_default_text_begin(pte, &pte->text, &pte_default);
2207 	if (code < 0)
2208 	    return code;
2209 	penum->pte_default = pte_default;
2210 	gs_text_enum_copy_dynamic(pte_default, pte, false);
2211     }
2212     /* The 'process' procedure might also have set pte_default itself. */
2213     if (penum->pte_default && !code)
2214 	goto top;
2215     return code;
2216     /*
2217      * This function uses an unobvious algorithm while handling type 3 fonts.
2218      * It runs 'process' to copy text until a glyph, which was not copied to
2219      * output font. Then it installs pte_default and falls back to default
2220      * implementation with PS interpreter callout. The callout executes
2221      * BuildChar/BuildGlyph with setcachedevice. The latter calls
2222      * pdf_set_charproc_attrs, which sets up an accumulator
2223      * of graphic objects to a pdf_begin_resource stream.
2224      * When the callout completes, pdf_text_process calls pdf_end_charproc_accum
2225      * and later resumes the normal (non-default) text enumeration, repeating the
2226      * the "callouted" glyph AT SECOND TIME. We can't do without the second pass
2227      * becauase in the first pass the glyph widths is unknown.
2228      */
2229      /*
2230       * Another unobvious thing is a CDevProc callout.
2231       * If 'process' returns with TEXT_PROCESS_CDEVPROC,
2232       * an interpreter callout will happen, and the function will be called again
2233       * with pte->cdevproc_result_valid = true. Then it restatrs with taking
2234       * glyph metrics from pte->cdevproc_result instead obtaining them with
2235       * font->procs.glyph_info .
2236       */
2237 }
2238