1 /* Copyright (C) 1999, 2000 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gdevpdff.c,v 1.22.2.2.2.1 2003/01/17 00:49:01 giles Exp $ */
20 /* Font handling for pdfwrite driver. */
21 #include "ctype_.h"
22 #include "math_.h"
23 #include "memory_.h"
24 #include "string_.h"
25 #include <stdlib.h>
26 #include "gx.h"
27 #include "gserrors.h"
28 #include "gsmalloc.h"		/* for patching font memory */
29 #include "gsmatrix.h"
30 #include "gspath.h"
31 #include "gsutil.h"		/* for bytes_compare */
32 #include "gxfixed.h"		/* for gxfcache.h */
33 #include "gxfont.h"
34 #include "gxfcache.h"		/* for orig_fonts list */
35 #include "gxfcid.h"
36 #include "gxfont1.h"
37 #include "gxfont42.h"
38 #include "gxpath.h"		/* for getting current point */
39 #include "gdevpdfx.h"
40 #include "gdevpdff.h"
41 #include "gdevpdfo.h"
42 #include "gdevpsf.h"
43 #include "scommon.h"
44 
45 /*
46  * In our quest to work around Acrobat Reader quirks, we're resorting to
47  * making all font names in the output unique by adding a suffix derived
48  * from the PDF object number.  We hope to get rid of this someday....
49  */
50 private const bool MAKE_FONT_NAMES_UNIQUE = true;
51 
52 /* GC descriptors */
53 public_st_pdf_font();
54 public_st_pdf_char_proc();
55 public_st_pdf_font_descriptor();
56 private_st_pdf_encoding_element();
ENUM_PTRS_WITH(pdf_encoding_elt_enum_ptrs,pdf_encoding_element_t * pe)57 private ENUM_PTRS_WITH(pdf_encoding_elt_enum_ptrs, pdf_encoding_element_t *pe) {
58     uint count = size / (uint)sizeof(*pe);
59 
60     if (index >= count)
61 	return 0;
62     return ENUM_CONST_STRING(&pe[index].str);
63 } ENUM_PTRS_END
64 private RELOC_PTRS_WITH(pdf_encoding_elt_reloc_ptrs, pdf_encoding_element_t *pe)
65     uint count = size / (uint)sizeof(*pe);
66     uint i;
67 
68     for (i = 0; i < count; ++i)
69 	RELOC_CONST_STRING_VAR(pe[i].str);
70 RELOC_PTRS_END
71 
72 /* Define the 14 standard built-in fonts. */
73 const pdf_standard_font_t pdf_standard_fonts[] = {
74 #define m(name, enc) {name, enc},
75     pdf_do_std_fonts(m)
76 #undef m
77     {0}
78 };
79 
80 /* ---------------- Embedding status ---------------- */
81 
82 /* Return the index of a standard font name, or -1 if missing. */
83 int
pdf_find_standard_font(const byte * str,uint size)84 pdf_find_standard_font(const byte *str, uint size)
85 {
86     const pdf_standard_font_t *ppsf;
87 
88     for (ppsf = pdf_standard_fonts; ppsf->fname; ++ppsf)
89 	if (strlen(ppsf->fname) == size &&
90 	    !strncmp(ppsf->fname, (const char *)str, size)
91 	    )
92 	    return ppsf - pdf_standard_fonts;
93     return -1;
94 }
95 
96 /*
97  * If there is a standard font with the same appearance (CharStrings,
98  * Private, WeightVector) as the given font, set *psame to the mask of
99  * identical properties, and return the standard-font index; otherwise,
100  * set *psame to 0 and return -1.
101  */
102 private int
find_std_appearance(const gx_device_pdf * pdev,const gs_font_base * bfont,int mask,int * psame)103 find_std_appearance(const gx_device_pdf *pdev, const gs_font_base *bfont,
104 		    int mask, int *psame)
105 {
106     bool has_uid = uid_is_UniqueID(&bfont->UID) && bfont->UID.id != 0;
107     const pdf_std_font_t *psf = pdev->std_fonts;
108     int i;
109 
110     mask |= FONT_SAME_OUTLINES;
111     for (i = 0; i < PDF_NUM_STD_FONTS; ++psf, ++i) {
112 	if (has_uid) {
113 	    if (!uid_equal(&bfont->UID, &psf->uid))
114 		continue;
115 	    if (!psf->font) {
116 		/*
117 		 * Identity of UIDs is supposed to guarantee that the
118 		 * fonts have the same outlines and metrics.
119 		 */
120 		*psame = FONT_SAME_OUTLINES | FONT_SAME_METRICS;
121 		return i;
122 	    }
123 	}
124 	if (psf->font) {
125 	    int same = *psame =
126 		bfont->procs.same_font((const gs_font *)bfont, psf->font,
127 				       mask);
128 
129 	    if (same & FONT_SAME_OUTLINES)
130 		return i;
131 	}
132     }
133     *psame = 0;
134     return -1;
135 }
136 
137 /*
138  * We register the fonts in pdev->std_fonts so that the pointers can
139  * be weak (get set to 0 when the font is freed).
140  */
141 private GS_NOTIFY_PROC(pdf_std_font_notify_proc);
142 typedef struct pdf_std_font_notify_s {
143     gx_device_pdf *pdev;
144     int index;			/* in std_fonts */
145     gs_font *font;	/* for checking */
146 } pdf_std_font_notify_t;
147 gs_private_st_ptrs2(st_pdf_std_font_notify, pdf_std_font_notify_t,
148 		    "pdf_std_font_notify_t",
149 		    pdf_std_font_notify_enum_ptrs,
150 		    pdf_std_font_notify_reloc_ptrs,
151 		    pdev, font);
152 private int
pdf_std_font_notify_proc(void * vpsfn,void * event_data)153 pdf_std_font_notify_proc(void *vpsfn /*proc_data*/, void *event_data)
154 {
155     pdf_std_font_notify_t *const psfn = vpsfn;
156     gx_device_pdf *const pdev = psfn->pdev;
157     gs_font *const font = psfn->font;
158 
159     if (event_data)
160 	return 0;		/* unknown event */
161     if_debug4('_',
162 	      "[_]  notify 0x%lx: gs_font 0x%lx, id %ld, index=%d\n",
163 	      (ulong)psfn, (ulong)font, font->id, psfn->index);
164 #ifdef DEBUG
165     if (pdev->std_fonts[psfn->index].font != font)
166 	lprintf3("pdf_std_font_notify font = 0x%lx, std_fonts[%d] = 0x%lx\n",
167 		 (ulong)font, psfn->index,
168 		 (ulong)pdev->std_fonts[psfn->index].font);
169     else
170 #endif
171 	pdev->std_fonts[psfn->index].font = 0;
172     gs_font_notify_unregister(font, pdf_std_font_notify_proc, vpsfn);
173     gs_free_object(pdev->pdf_memory, vpsfn, "pdf_std_font_notify_proc");
174     return 0;
175 }
176 
177 /* Unregister the standard fonts when cleaning up. */
178 private void
pdf_std_font_unreg_proc(void * vpsfn)179 pdf_std_font_unreg_proc(void *vpsfn /*proc_data*/)
180 {
181     pdf_std_font_notify_proc(vpsfn, NULL);
182 }
183 void
pdf_unregister_fonts(gx_device_pdf * pdev)184 pdf_unregister_fonts(gx_device_pdf *pdev)
185 {
186     int j;
187 
188     for (j = 0; j < PDF_NUM_STD_FONTS; ++j)
189 	if (pdev->std_fonts[j].font != 0)
190 	    gs_notify_unregister_calling(&pdev->std_fonts[j].font->notify_list,
191 					 pdf_std_font_notify_proc, NULL,
192 					 pdf_std_font_unreg_proc);
193 }
194 
195 /*
196  * Scan a font directory for standard fonts.  Return true if any new ones
197  * were found.
198  */
199 private bool
scan_for_standard_fonts(gx_device_pdf * pdev,const gs_font_dir * dir)200 scan_for_standard_fonts(gx_device_pdf *pdev, const gs_font_dir *dir)
201 {
202     bool found = false;
203     gs_font *orig = dir->orig_fonts;
204 
205     for (; orig; orig = orig->next) {
206 	gs_font_base *obfont;
207 
208 	if (orig->FontType == ft_composite || !orig->is_resource)
209 	    continue;
210 	obfont = (gs_font_base *)orig;
211 	if (uid_is_UniqueID(&obfont->UID)) {
212 	    /* Is it one of the standard fonts? */
213 	    int i = pdf_find_standard_font(orig->key_name.chars,
214 					   orig->key_name.size);
215 	    pdf_std_font_t *psf;
216 
217 	    if (i >= 0 && (psf = &pdev->std_fonts[i])->font == 0) {
218 		pdf_std_font_notify_t *psfn =
219 		    gs_alloc_struct(pdev->pdf_memory, pdf_std_font_notify_t,
220 				    &st_pdf_std_font_notify,
221 				    "scan_for_standard_fonts");
222 
223 		if (psfn == 0)
224 		    continue;	/* can't register */
225 		psfn->pdev = pdev;
226 		psfn->index = i;
227 		psfn->font = orig;
228 		if_debug4('_',
229 			  "[_]register 0x%lx: gs_font 0x%lx, id %ld, index=%d\n",
230 			  (ulong)psfn, (ulong)orig, orig->id, i);
231 		gs_font_notify_register(orig, pdf_std_font_notify_proc, psfn);
232 		psf->font = orig;
233 		psf->orig_matrix = obfont->FontMatrix;
234 		psf->uid = obfont->UID;
235 		found = true;
236 	    }
237 	}
238     }
239     return found;
240 }
241 
242 /*
243  * Determine the embedding status of a font.  If the font is in the base
244  * 14, store its index (0..13) in *pindex, otherwise store -1 there.
245  */
246 private bool
font_is_symbolic(const gs_font * font)247 font_is_symbolic(const gs_font *font)
248 {
249     if (font->FontType == ft_composite)
250 	return true;		/* arbitrary */
251     switch (((const gs_font_base *)font)->nearest_encoding_index) {
252     case ENCODING_INDEX_STANDARD:
253     case ENCODING_INDEX_ISOLATIN1:
254     case ENCODING_INDEX_WINANSI:
255     case ENCODING_INDEX_MACROMAN:
256 	return false;
257     default:
258 	return true;
259     }
260 }
261 private bool
embed_list_includes(const gs_param_string_array * psa,const byte * chars,uint size)262 embed_list_includes(const gs_param_string_array *psa, const byte *chars,
263 		    uint size)
264 {
265     uint i;
266 
267     for (i = 0; i < psa->size; ++i)
268 	if (!bytes_compare(psa->data[i].data, psa->data[i].size, chars, size))
269 	    return true;
270     return false;
271 }
272 pdf_font_embed_t
pdf_font_embed_status(gx_device_pdf * pdev,gs_font * font,int * pindex,int * psame)273 pdf_font_embed_status(gx_device_pdf *pdev, gs_font *font, int *pindex,
274 		      int *psame)
275 {
276     const byte *chars = font->font_name.chars;
277     uint size = font->font_name.size;
278 
279     /* CIDFonts has null string in font_name, key_name is used */
280     if (0 == size) {
281 	chars = font->key_name.chars;
282 	size = font->key_name.size;
283     }
284     /*
285      * The behavior of Acrobat Distiller changed between 3.0 (PDF 1.2),
286      * which will never embed the base 14 fonts, and 4.0 (PDF 1.3), which
287      * doesn't treat them any differently from any other fonts.
288      */
289     if (pdev->CompatibilityLevel < 1.3) {
290 	/* Check whether the font is in the base 14. */
291 	int index = pdf_find_standard_font(chars, size);
292 
293 	if (index >= 0) {
294 	    *pindex = index;
295 	    if (font->is_resource) {
296 		*psame = ~0;
297 		return FONT_EMBED_STANDARD;
298 	    } else if (font->FontType != ft_composite &&
299 		       find_std_appearance(pdev, (gs_font_base *)font, -1,
300 					   psame) == index)
301 		return FONT_EMBED_STANDARD;
302 	}
303     }
304     *pindex = -1;
305     *psame = 0;
306     /* Check the Embed lists. */
307     if (embed_list_includes(&pdev->params.NeverEmbed, chars, size))
308 	return FONT_EMBED_NO;
309     if (pdev->params.EmbedAllFonts || font_is_symbolic(font) ||
310 	embed_list_includes(&pdev->params.AlwaysEmbed, chars, size))
311 	return FONT_EMBED_YES;
312     return FONT_EMBED_NO;
313 }
314 
315 /* ---------------- Everything else ---------------- */
316 
317 /*
318  * Compute and return the orig_matrix of a font.
319  */
320 int
pdf_font_orig_matrix(const gs_font * font,gs_matrix * pmat)321 pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat)
322 {
323     switch (font->FontType) {
324     case ft_composite:		/* subfonts have their own FontMatrix */
325     case ft_TrueType:
326     case ft_CID_TrueType:
327 	/* The TrueType FontMatrix is 1 unit per em, which is what we want. */
328 	gs_make_identity(pmat);
329 	break;
330     case ft_encrypted:
331     case ft_encrypted2:
332     case ft_CID_encrypted:
333 	/*
334          * Type 1 fonts are supposed to use a standard FontMatrix of
335          * [0.001 0 0 0.001 0 0], with a 1000-unit cell.  However,
336          * Windows NT 4.0 creates Type 1 fonts, apparently derived from
337          * TrueType fonts, that use a 2048-unit cell and corresponding
338          * FontMatrix.
339          *
340          * Also some PS programs perform font scaling by replacing
341          * FontMatrix like this :
342          *
343          *   /f12 /Times-Roman findfont
344          *   copyfont	  % (remove FID)
345          *   dup /FontMatrix [0.012 0 0 0.012 0 0] put
346          *   definefont
347          *   /f12 1 selectfont
348          *
349          * Such fonts are their own "base font", but the orig_matrix
350          * must still be set to 0.001, not 0.012 .
351          *
352          * Detect and correct for this here.
353 	 */
354 	{
355 	    const gs_font *base_font = font;
356 	    double scale;
357 
358 	    while (base_font->base != base_font)
359 		base_font = base_font->base;
360 	    if (base_font->FontMatrix.xx == 1.0/2048 &&
361 		base_font->FontMatrix.xy == 0 &&
362 		base_font->FontMatrix.yx == 0 &&
363 		base_font->FontMatrix.yy == 1.0/2048
364 		)
365 		scale = 1.0/2048;
366 	    else
367 		scale = 0.001;
368 	    gs_make_scaling(scale, scale, pmat);
369 	}
370 	break;
371     default:
372 	return_error(gs_error_rangecheck);
373     }
374     return 0;
375 }
376 
377 /*
378  * Find the original (unscaled) standard font corresponding to an
379  * arbitrary font, if any.  Return its index in standard_fonts, or -1.
380  */
381 int
pdf_find_orig_font(gx_device_pdf * pdev,gs_font * font,gs_matrix * pfmat)382 pdf_find_orig_font(gx_device_pdf *pdev, gs_font *font, gs_matrix *pfmat)
383 {
384     bool scan = true;
385     int i;
386 
387     if (font->FontType == ft_composite)
388 	return -1;
389     for (;; font = font->base) {
390 	gs_font_base *bfont = (gs_font_base *)font;
391 	int same;
392 
393 	/* Look for a standard font with the same appearance. */
394 	i = find_std_appearance(pdev, bfont, 0, &same);
395 	if (i >= 0)
396 	    break;
397 	if (scan) {
398 	    /* Scan for fonts with any of the standard names that */
399 	    /* have a UID. */
400 	    bool found = scan_for_standard_fonts(pdev, font->dir);
401 
402 	    scan = false;
403 	    if (found) {
404 		i = find_std_appearance(pdev, bfont, 0, &same);
405 		if (i >= 0)
406 		    break;
407 	    }
408 	}
409 	if (font->base == font)
410 	    return -1;
411     }
412     *pfmat = pdev->std_fonts[i].orig_matrix;
413     return i;
414 }
415 
416 /*
417  * Determine the resource type (resourceFont or resourceCIDFont) for
418  * a font.
419  */
420 pdf_resource_type_t
pdf_font_resource_type(const gs_font * font)421 pdf_font_resource_type(const gs_font *font)
422 {
423     switch (font->FontType) {
424     case ft_CID_encrypted:	/* CIDFontType 0 */
425     case ft_CID_user_defined:	/* CIDFontType 1 */
426     case ft_CID_TrueType:	/* CIDFontType 2 */
427     case ft_CID_bitmap:		/* CIDFontType 4 */
428 	return resourceCIDFont;
429     default:
430 	return resourceFont;
431     }
432 }
433 
434 /*
435  * Determine the chars_count (number of entries in chars_used and Widths)
436  * for a font.  For CIDFonts, this is CIDCount.
437  */
438 private int
pdf_font_chars_count(const gs_font * font)439 pdf_font_chars_count(const gs_font *font)
440 {
441     switch (font->FontType) {
442     case ft_composite:
443 	/* Composite fonts don't use chars_used or Widths. */
444 	return 0;
445     case ft_CID_encrypted:
446 	return ((const gs_font_cid0 *)font)->cidata.common.CIDCount;
447     case ft_CID_TrueType:
448 	return ((const gs_font_cid2 *)font)->cidata.common.CIDCount;
449     default:
450 	return 256;		/* Encoding size */
451     }
452 }
453 
454 /*
455  * Determine the glyphs_count (number of entries in glyphs_used) for a font.
456  * This is only non-zero for TrueType-based fonts.
457  */
458 private int
pdf_font_glyphs_count(const gs_font * font)459 pdf_font_glyphs_count(const gs_font *font)
460 {
461     switch (font->FontType) {
462     case ft_TrueType:
463     case ft_CID_TrueType:
464 	return ((const gs_font_type42 *)font)->data.numGlyphs;
465     default:
466 	return 0;
467     }
468 }
469 
470 /*
471  * Allocate a font resource.  If pfd != 0, a FontDescriptor is allocated,
472  * with its id, values, and chars_count taken from *pfd_in.
473  * If font != 0, its FontType is used to determine whether the resource
474  * is of type Font or of (pseudo-)type CIDFont; in this case, pfres->font
475  * and pfres->FontType are also set.
476  */
477 int
pdf_alloc_font(gx_device_pdf * pdev,gs_id rid,pdf_font_t ** ppfres,const pdf_font_descriptor_t * pfd_in,gs_font * font)478 pdf_alloc_font(gx_device_pdf *pdev, gs_id rid, pdf_font_t **ppfres,
479 	       const pdf_font_descriptor_t *pfd_in, gs_font *font)
480 {
481     gs_memory_t *mem = pdev->v_memory;
482     pdf_font_descriptor_t *pfd = 0;
483     pdf_resource_type_t rtype = resourceFont;
484     gs_string chars_used, glyphs_used;
485     int *Widths = 0;
486     byte *widths_known = 0;
487     ushort *CIDToGIDMap = 0;
488     int code;
489     pdf_font_t *pfres;
490 
491     chars_used.data = 0;
492     glyphs_used.data = 0;
493     if (pfd_in) {
494 	uint chars_count = pfd_in->chars_count;
495 	uint glyphs_count = pfd_in->glyphs_count;
496 
497 	code = pdf_alloc_resource(pdev, resourceFontDescriptor,
498 				  pfd_in->rid, (pdf_resource_t **)&pfd, 0L);
499 	if (code < 0)
500 	    return code;
501 	chars_used.size = (chars_count + 7) >> 3;
502 	chars_used.data = gs_alloc_string(mem, chars_used.size,
503 					  "pdf_alloc_font(chars_used)");
504 	if (chars_used.data == 0)
505 	    goto vmfail;
506 	if (glyphs_count) {
507 	    glyphs_used.size = (glyphs_count + 7) >> 3;
508 	    glyphs_used.data = gs_alloc_string(mem, glyphs_used.size,
509 					       "pdf_alloc_font(glyphs_used)");
510 	    if (glyphs_used.data == 0)
511 		goto vmfail;
512 	    memset(glyphs_used.data, 0, glyphs_used.size);
513 	}
514 	memset(chars_used.data, 0, chars_used.size);
515 	pfd->values = pfd_in->values;
516 	pfd->chars_count = chars_count;
517 	pfd->chars_used = chars_used;
518 	pfd->glyphs_count = glyphs_count;
519 	pfd->glyphs_used = glyphs_used;
520 	pfd->do_subset = FONT_SUBSET_OK;
521 	pfd->FontFile_id = 0;
522 	pfd->base_font = 0;
523 	pfd->notified = false;
524 	pfd->written = false;
525     }
526     if (font) {
527 	uint chars_count = pdf_font_chars_count(font);
528 	uint widths_known_size = (chars_count + 7) >> 3;
529 
530 	Widths = (void *)gs_alloc_byte_array(mem, chars_count, sizeof(*Widths),
531 					     "pdf_alloc_font(Widths)");
532 	widths_known = gs_alloc_bytes(mem, widths_known_size,
533 				      "pdf_alloc_font(widths_known)");
534 	if (Widths == 0 || widths_known == 0)
535 	    goto vmfail;
536 	if (font->FontType == ft_CID_TrueType) {
537 	    CIDToGIDMap = (void *)
538 		gs_alloc_byte_array(mem, chars_count, sizeof(*CIDToGIDMap),
539 				    "pdf_alloc_font(CIDToGIDMap)");
540 	    if (CIDToGIDMap == 0)
541 		goto vmfail;
542 	    memset(CIDToGIDMap, 0, chars_count * sizeof(*CIDToGIDMap));
543 	}
544 	memset(widths_known, 0, widths_known_size);
545 	rtype = pdf_font_resource_type(font);
546     }
547     code = pdf_alloc_resource(pdev, rtype, rid, (pdf_resource_t **)ppfres, 0L);
548     if (code < 0)
549 	goto fail;
550     pfres = *ppfres;
551     memset((byte *)pfres + sizeof(pdf_resource_t), 0,
552 	   sizeof(*pfres) - sizeof(pdf_resource_t));
553     pfres->font = font;
554     if (font)
555 	pfres->FontType = font->FontType;
556     pfres->index = -1;
557     pfres->is_MM_instance = false;
558     pfres->FontDescriptor = pfd;
559     pfres->write_Widths = false;
560     pfres->Widths = Widths;
561     pfres->widths_known = widths_known;
562     pfres->BaseEncoding = ENCODING_INDEX_UNKNOWN;
563     pfres->Differences = 0;
564     pfres->DescendantFont = 0;
565     pfres->glyphshow_font = 0;
566     pfres->CIDToGIDMap = CIDToGIDMap;
567     pfres->char_procs = 0;
568     return 0;
569  vmfail:
570     code = gs_note_error(gs_error_VMerror);
571  fail:
572     gs_free_object(mem, CIDToGIDMap, "pdf_alloc_font(CIDToGIDMap)");
573     gs_free_object(mem, widths_known, "pdf_alloc_font(widths_known)");
574     gs_free_object(mem, Widths, "pdf_alloc_font(Widths)");
575     if (glyphs_used.data)
576 	gs_free_string(mem, glyphs_used.data, glyphs_used.size,
577 		       "pdf_alloc_font(glyphs_used)");
578     if (chars_used.data)
579 	gs_free_string(mem, chars_used.data, chars_used.size,
580 		       "pdf_alloc_font(chars_used)");
581     gs_free_object(mem, pfd, "pdf_alloc_font(descriptor)");
582     return code;
583 }
584 
585 /*
586  * Create a new pdf_font for a gs_font.  This procedure is only intended
587  * to be called from a few places in gdevpdft.c.
588  */
589 int
pdf_create_pdf_font(gx_device_pdf * pdev,gs_font * font,const gs_matrix * pomat,pdf_font_t ** pppf)590 pdf_create_pdf_font(gx_device_pdf *pdev, gs_font *font, const gs_matrix *pomat,
591 		    pdf_font_t **pppf)
592 {
593     int index = -1;
594     int ftemp_Widths[256];
595     byte ftemp_widths_known[256/8];
596     int BaseEncoding = ENCODING_INDEX_UNKNOWN;
597     int same = 0, base_same = 0;
598     pdf_font_embed_t embed =
599 	pdf_font_embed_status(pdev, font, &index, &same);
600     bool have_widths = false;
601     bool is_standard = false;
602     long ffid = 0;
603     pdf_font_descriptor_t *pfd = 0;
604     pdf_std_font_t *psf = 0;
605     gs_font *base_font = font;
606     gs_font *below;
607     pdf_font_descriptor_t fdesc;
608     pdf_font_t *ppf;
609     int code;
610 #define BASE_UID(fnt) (&((const gs_font_base *)(fnt))->UID)
611 
612     /* Find the "lowest" base font that has the same outlines. */
613     while ((below = base_font->base) != base_font &&
614 	   base_font->procs.same_font(base_font, below,
615 				      FONT_SAME_OUTLINES))
616 	base_font = below;
617     /*
618      * set_base is the head of a logical loop; we return here if we
619      * decide to change the base_font to one registered as a resource.
620      */
621  set_base:
622     if (base_font == font)
623 	base_same = same;
624     else
625 	embed = pdf_font_embed_status(pdev, base_font, &index, &base_same);
626     if (embed == FONT_EMBED_STANDARD) {
627 	psf = &pdev->std_fonts[index];
628 	if (psf->font != 0 || psf->pfd != 0) {
629 	    /*
630 	     * Use the standard font as the base font.  Either base_font
631 	     * or pfd may be zero, but not both.
632 	     */
633 	    base_font = psf->font;
634 	    pfd = psf->pfd;
635 	}
636 	is_standard = true;
637     } else if (embed == FONT_EMBED_YES &&
638 	       base_font->FontType != ft_composite &&
639 	       uid_is_valid(BASE_UID(base_font)) &&
640 	       !base_font->is_resource
641 	       ) {
642 	/*
643 	 * The base font has a UID, but it isn't a resource.  Look for a
644 	 * resource with the same UID, in the hope that that will be
645 	 * longer-lived.
646 	 */
647 	gs_font *orig = base_font->dir->orig_fonts;
648 
649 	for (; orig; orig = orig->next)
650 	    if (orig != base_font && orig->FontType == base_font->FontType &&
651 		orig->is_resource &&
652 		uid_equal(BASE_UID(base_font), BASE_UID(orig))
653 		) {
654 		/* Use this as the base font instead. */
655 		base_font = orig;
656 		/*
657 		 * Recompute the embedding status of the base font.  This
658 		 * can't lead to a loop, because base_font->is_resource is
659 		 * now known to be true.
660 		 */
661 		goto set_base;
662 	    }
663     }
664 
665     /* Composite fonts don't have descriptors. */
666     if (font->FontType == ft_composite) {
667 	code = pdf_alloc_font(pdev, font->id, &ppf, NULL, font);
668 	if (code < 0)
669 	    return code;
670 	if_debug2('_',
671 		  "[_]created ft_composite pdf_font_t 0x%lx, id %ld\n",
672 		  (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf));
673 	ppf->index = -1;
674 	code = pdf_register_font(pdev, font, ppf);
675 	*pppf = ppf;
676 	return code;
677     }
678 
679     /* See if we already have a descriptor for this base font. */
680     if (pfd == 0)		/* if non-zero, was standard font */
681 	pfd = (pdf_font_descriptor_t *)
682 	    pdf_find_resource_by_gs_id(pdev, resourceFontDescriptor,
683 				       base_font->id);
684     if (pfd != 0 && pfd->base_font != base_font && pfd->base_font != 0)
685 	pfd = 0;
686 
687     /* Create an appropriate font and descriptor. */
688 
689     switch (embed) {
690     case FONT_EMBED_YES:
691 	/*
692 	 * HACK: Acrobat Reader 3 has a bug that makes cmap formats 4
693 	 * and 6 not work in embedded TrueType fonts.  Consequently, it
694 	 * can only handle embedded TrueType fonts if all the glyphs
695 	 * referenced by the Encoding have numbers 0-255.  Check for
696 	 * this now.
697 	 */
698 	if ((font->FontType == ft_TrueType ||
699 	     font->FontType == ft_CID_TrueType) &&
700 	    pdev->CompatibilityLevel <= 1.2
701 	    ) {
702 	    int i;
703 
704 	    for (i = 0; i <= 0xff; ++i) {
705 		gs_glyph glyph =
706 		    font->procs.encode_char(font, (gs_char)i,
707 					    GLYPH_SPACE_INDEX);
708 
709 		if (glyph == gs_no_glyph ||
710 		    (glyph >= gs_min_cid_glyph &&
711 		     glyph <= gs_min_cid_glyph + 0xff)
712 		    )
713 		    continue;
714 		/* Can't embed, punt. */
715 		return_error(gs_error_rangecheck);
716 	    }
717 	}
718 	if (!pfd) {
719 	    code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
720 	    if (code < 0)
721 		return code;
722 	    ffid = pdf_obj_ref(pdev);
723 	}
724 	/* The font isn't standard: make sure we write the Widths. */
725 	same &= ~FONT_SAME_METRICS;
726 	break;
727     case FONT_EMBED_NO:
728 	if (!(font->FontType == ft_CID_encrypted ||
729 	      font->FontType == ft_CID_TrueType)) {
730 	    /*
731 	     * Per the PDF 1.3 documentation, there are only 3 BaseEncoding
732 	     * values allowed for non-embedded fonts.  Pick one here.
733 	     */
734 	    BaseEncoding =
735 	        ((const gs_font_base *)base_font)->nearest_encoding_index;
736 	    switch (BaseEncoding) {
737 	    default:
738 	        BaseEncoding = ENCODING_INDEX_WINANSI;
739 	    case ENCODING_INDEX_WINANSI:
740 	    case ENCODING_INDEX_MACROMAN:
741 	    case ENCODING_INDEX_MACEXPERT:
742 	        break;
743 	    }
744 	}
745 	code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
746 	if (code < 0)
747 	    return code;
748 	/* The font isn't standard: make sure we write the Widths. */
749 	same &= ~FONT_SAME_METRICS;
750 	break;
751     case FONT_EMBED_STANDARD:
752 	break;
753     }
754     if (~same & (FONT_SAME_METRICS | FONT_SAME_ENCODING)) {
755 	/*
756 	 * Before allocating the font resource, check that we can
757 	 * get all the widths for non-CID-keyed fonts.
758 	 */
759 	switch (font->FontType) {
760 	case ft_composite:
761 	case ft_CID_encrypted:
762 	case ft_CID_TrueType:
763 	    break;
764 	default:
765 	    {
766 		pdf_font_t ftemp;
767 		int i;
768 
769 		memset(&ftemp, 0, sizeof(ftemp));
770 		pdf_font_orig_matrix(font, &ftemp.orig_matrix);
771 		ftemp.Widths = ftemp_Widths;
772 		ftemp.widths_known = ftemp_widths_known;
773 		memset(ftemp.widths_known, 0, sizeof(ftemp_widths_known));
774 		for (i = 0; i <= 255; ++i) {
775 		    code = pdf_char_width(&ftemp, i, font, NULL);
776 		    if (code < 0 && code != gs_error_undefined)
777 			return code;
778 		}
779 		have_widths = true;
780 	    }
781 	}
782     }
783     if (pfd) {
784 	code = pdf_alloc_font(pdev, font->id, &ppf, NULL, font);
785 	if (code < 0)
786 	    return code;
787 	if_debug4('_',
788 		  "[_]created pdf_font_t 0x%lx, id %ld, FontDescriptor 0x%lx, id %ld (old)\n",
789 		  (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf),
790 		  (ulong)pfd, pdf_resource_id((pdf_resource_t *)pfd));
791 	ppf->FontDescriptor = pfd;
792     } else {
793 	int name_index = index;
794 
795 	fdesc.rid = base_font->id;
796 	fdesc.chars_count = pdf_font_chars_count(base_font);
797 	fdesc.glyphs_count = pdf_font_glyphs_count(base_font);
798 	code = pdf_alloc_font(pdev, font->id, &ppf, &fdesc, font);
799 	if (code < 0)
800 	    return code;
801 	pfd = ppf->FontDescriptor;
802 	if_debug4('_',
803 		  "[_]created pdf_font_t 0x%lx, id %ld, FontDescriptor 0x%lx, id %ld (new)\n",
804 		  (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf),
805 		  (ulong)pfd, pdf_resource_id((pdf_resource_t *)pfd));
806 	if (index < 0) {
807 	    int ignore_same;
808 	    const gs_font_name *pfname = &base_font->font_name;
809 
810 	    /* CIDFonts may have a key_name but no font_name. */
811 	    if (pfname->size == 0)
812 		pfname = &base_font->key_name;
813 	    memcpy(pfd->FontName.chars, pfname->chars, pfname->size);
814 	    pfd->FontName.size = pfname->size;
815 	    pfd->FontFile_id = ffid;
816 	    pfd->base_font = base_font;
817 	    /* Don't allow non-standard fonts with standard names. */
818 	    pdf_font_embed_status(pdev, base_font, &name_index,
819 				  &ignore_same);
820 	} else {
821 	    /* Use the standard name. */
822 	    const pdf_standard_font_t *ppsf = &pdf_standard_fonts[index];
823 	    const char *fnchars = ppsf->fname;
824 	    uint fnsize = strlen(fnchars);
825 
826 	    memcpy(pfd->FontName.chars, fnchars, fnsize);
827 	    pfd->FontName.size = fnsize;
828 	    memset(&pfd->values, 0, sizeof(&pfd->values));
829 	}
830 	pfd->orig_matrix = *pomat;
831 	if (is_standard) {
832 	    psf->pfd = pfd;
833 	    if (embed == FONT_EMBED_STANDARD)
834 		pfd->base_font = 0;
835 	} else {
836 	    code = pdf_adjust_font_name(pdev, pfd, name_index >= 0);
837 	    if (code < 0)
838 		return code;
839 	}
840     } /* end else (!pfd) */
841     ppf->index = index;
842 
843     switch (font->FontType) {
844     case ft_encrypted:
845     case ft_encrypted2:
846 	ppf->is_MM_instance =
847 	    ((const gs_font_type1 *)font)->data.WeightVector.count > 0;
848 	break;
849     case ft_CID_encrypted:
850     case ft_CID_TrueType:
851 	/*
852 	 * Write the CIDSystemInfo now, so we don't try to access it after
853 	 * the font may no longer be available.
854 	 */
855 	{
856 	    long cidsi_id = pdf_begin_separate(pdev);
857 
858 	    pdf_write_CIDFont_system_info(pdev, font);
859 	    pdf_end_separate(pdev);
860 	    ppf->CIDSystemInfo_id = cidsi_id;
861 	}
862     default:
863 	DO_NOTHING;
864     }
865 
866     ppf->BaseEncoding = BaseEncoding;
867     ppf->fname = pfd->FontName;
868     ppf->orig_matrix = *pomat;
869     if (~same & FONT_SAME_METRICS) {
870 	/*
871 	 * Contrary to the PDF 1.3 documentation, FirstChar and
872 	 * LastChar are *not* simply a way to strip off initial and
873 	 * final entries in the Widths array that are equal to
874 	 * MissingWidth.  Acrobat Reader assumes that characters
875 	 * with codes less than FirstChar or greater than LastChar
876 	 * are undefined, without bothering to consult the Encoding.
877 	 * Therefore, the implicit value of MissingWidth is pretty
878 	 * useless, because there must be explicit Width entries for
879 	 * every character in the font that is ever used.
880 	 * Furthermore, if there are several subsets of the same
881 	 * font in a document, it appears to be random as to which
882 	 * one Acrobat Reader uses to decide what the FirstChar and
883 	 * LastChar values are.  Therefore, we must write the Widths
884 	 * array for the entire font even for subsets.
885 	 */
886 	ppf->write_Widths = true;
887 	/*
888 	 * If the font is being downloaded incrementally, the range we
889 	 * determine here will be too small.  The character encoding
890 	 * loop in pdf_process_string takes care of expanding it.
891 	 */
892 	pdf_find_char_range(font, &ppf->FirstChar, &ppf->LastChar);
893     }
894     if (have_widths) {
895 	memcpy(ppf->Widths, ftemp_Widths, sizeof(ftemp_Widths));
896 	memcpy(ppf->widths_known, ftemp_widths_known,
897 	       sizeof(ftemp_widths_known));
898     }
899     ppf->embed = embed;
900     code = pdf_register_font(pdev, font, ppf);
901 
902     *pppf = ppf;
903     return code;
904 }
905 
906 /*
907  * Determine whether a font is a subset font by examining the name.
908  */
909 bool
pdf_has_subset_prefix(const byte * str,uint size)910 pdf_has_subset_prefix(const byte *str, uint size)
911 {
912     int i;
913 
914     if (size < SUBSET_PREFIX_SIZE || str[SUBSET_PREFIX_SIZE - 1] != '+')
915 	return false;
916     for (i = 0; i < SUBSET_PREFIX_SIZE - 1; ++i)
917 	if ((uint)(str[i] - 'A') >= 26)
918 	    return false;
919     return true;
920 }
921 
922 /*
923  * Make the prefix for a subset font from the font's resource ID.
924  */
925 void
pdf_make_subset_prefix(const gx_device_pdf * pdev,byte * str,ulong id)926 pdf_make_subset_prefix(const gx_device_pdf *pdev, byte *str, ulong id)
927 {
928     int i;
929     ulong v;
930 
931     /* We disregard the id and generate a random prefix. */
932     v = (ulong)(pdev->random_offset + rand());
933     for (i = 0; i < SUBSET_PREFIX_SIZE - 1; ++i, v /= 26)
934 	str[i] = 'A' + (v % 26);
935     str[SUBSET_PREFIX_SIZE - 1] = '+';
936 }
937 
938 /*
939  * Adjust the FontName of a newly created FontDescriptor so that it is
940  * unique if necessary.
941  */
942 int
pdf_adjust_font_name(const gx_device_pdf * pdev,pdf_font_descriptor_t * pfd,bool is_standard)943 pdf_adjust_font_name(const gx_device_pdf *pdev, pdf_font_descriptor_t *pfd,
944 		     bool is_standard)
945 {
946     int code = 0;
947 
948     if (MAKE_FONT_NAMES_UNIQUE) {
949 	/* Check whether this name has already been used. */
950 	int j = 0;
951 	pdf_font_descriptor_t *old;
952 	byte *chars = pfd->FontName.chars;
953 	uint size = pfd->FontName.size;
954 
955 #define SUFFIX_CHAR '~'
956 	/*
957 	 * If the name looks as though it has one of our unique suffixes,
958 	 * remove the suffix.
959 	 */
960 	{
961 	    int i;
962 
963 	    for (i = size;
964 		 i > 0 && isxdigit(chars[i - 1]);
965 		 --i)
966 		DO_NOTHING;
967 	    if (i < size && i > 0 && chars[i - 1] == SUFFIX_CHAR) {
968 		do {
969 		    --i;
970 		} while (i > 0 && chars[i - 1] == SUFFIX_CHAR);
971 		size = i + 1;
972 	    }
973 	    code = size != pfd->FontName.size;
974 	}
975 	/*
976 	 * Non-standard fonts with standard names must always use a suffix
977 	 * to avoid being confused with the standard fonts.
978 	 */
979 	if (!is_standard)
980 	    for (; j < NUM_RESOURCE_CHAINS; ++j)
981 		for (old = (pdf_font_descriptor_t *)pdev->resources[resourceFontDescriptor].chains[j];
982 		     old != 0; old = old->next
983 		     ) {
984 		    const byte *old_chars = old->FontName.chars;
985 		    uint old_size = old->FontName.size;
986 
987 		    if (old == pfd)
988 			continue;
989 		    if (pdf_has_subset_prefix(old_chars, old_size))
990 			old_chars += SUBSET_PREFIX_SIZE,
991 			    old_size -= SUBSET_PREFIX_SIZE;
992 		    if (!bytes_compare(old_chars, old_size, chars, size))
993 			goto found; /* do a double 'break' */
994 		}
995     found:			/* only used for double 'break' above */
996 	if (j < NUM_RESOURCE_CHAINS) {
997 	    /* Create a unique name. */
998 	    char suffix[sizeof(long) * 2 + 2];
999 	    uint suffix_size;
1000 
1001 	    sprintf(suffix, "%c%lx", SUFFIX_CHAR,
1002 		    pdf_resource_id((pdf_resource_t *)pfd));
1003 	    suffix_size = strlen(suffix);
1004 	    if (size + suffix_size > sizeof(pfd->FontName.chars))
1005 		return_error(gs_error_rangecheck);
1006 	    memcpy(chars + size, (const byte *)suffix, suffix_size);
1007 	    size += suffix_size;
1008 	    code = 1;
1009 	}
1010 	pfd->FontName.size = size;
1011 #undef SUFFIX_CHAR
1012     }
1013     return code;
1014 }
1015 
1016 /* Add an encoding difference to a font. */
1017 int
pdf_add_encoding_difference(gx_device_pdf * pdev,pdf_font_t * ppf,int chr,gs_font_base * bfont,gs_glyph glyph)1018 pdf_add_encoding_difference(gx_device_pdf *pdev, pdf_font_t *ppf, int chr,
1019 			    gs_font_base *bfont, gs_glyph glyph)
1020 {
1021     pdf_encoding_element_t *pdiff = ppf->Differences;
1022     /*
1023      * Since the font Widths are indexed by character code, changing the
1024      * encoding also changes the Widths.
1025      */
1026     int width;
1027     int code = pdf_glyph_width(ppf, glyph, (gs_font *)bfont, &width);
1028 
1029     if (code < 0)
1030 	return code;
1031     if (pdiff == 0) {
1032 	pdiff = gs_alloc_struct_array(pdev->pdf_memory, 256,
1033 				      pdf_encoding_element_t,
1034 				      &st_pdf_encoding_element,
1035 				      "Differences");
1036 	if (pdiff == 0)
1037 	    return_error(gs_error_VMerror);
1038 	memset(pdiff, 0, sizeof(pdf_encoding_element_t) * 256);
1039 	ppf->Differences = pdiff;
1040     }
1041     pdiff[chr].glyph = glyph;
1042     pdiff[chr].str.data = (const byte *)
1043 	bfont->procs.callbacks.glyph_name(glyph, &pdiff[chr].str.size);
1044     ppf->Widths[chr] = width;
1045     if (code == 0)
1046 	ppf->widths_known[chr >> 3] |= 0x80 >> (chr & 7);
1047     else
1048 	ppf->widths_known[chr >> 3] &= ~(0x80 >> (chr & 7));
1049     return 0;
1050 }
1051 
1052 /*
1053  * Get the width of a given character in a (base) font.  May add the width
1054  * to the widths cache (ppf->Widths).
1055  */
1056 int
pdf_char_width(pdf_font_t * ppf,int ch,gs_font * font,int * pwidth)1057 pdf_char_width(pdf_font_t *ppf, int ch, gs_font *font,
1058 	       int *pwidth /* may be NULL */)
1059 {
1060     if (ch < 0 || ch > 255)
1061 	return_error(gs_error_rangecheck);
1062     if (!(ppf->widths_known[ch >> 3] & (0x80 >> (ch & 7)))) {
1063 	gs_font_base *bfont = (gs_font_base *)font;
1064 	gs_glyph glyph = bfont->procs.encode_char(font, (gs_char)ch,
1065 						  GLYPH_SPACE_INDEX);
1066 	int width = 0;
1067 	int code = pdf_glyph_width(ppf, glyph, font, &width);
1068 
1069 	if (code < 0)
1070 	    return code;
1071 	ppf->Widths[ch] = width;
1072 	if (code == 0)
1073 	    ppf->widths_known[ch >> 3] |= 0x80 >> (ch & 7);
1074     }
1075     if (pwidth)
1076 	*pwidth = ppf->Widths[ch];
1077     return 0;
1078 }
1079 
1080 /*
1081  * Get the width of a glyph in a (base) font.  Return 1 if the width was
1082  * defaulted to MissingWidth.
1083  */
1084 int
pdf_glyph_width(pdf_font_t * ppf,gs_glyph glyph,gs_font * font,int * pwidth)1085 pdf_glyph_width(pdf_font_t *ppf, gs_glyph glyph, gs_font *font,
1086 		int *pwidth /* must not be NULL */)
1087 {
1088     int wmode = font->WMode;
1089     gs_glyph_info_t info;
1090     /*
1091      * orig_matrix.xx is 1.0 for TrueType, 0.001 or 1.0/2048 for Type 1.
1092      */
1093     double scale = ppf->orig_matrix.xx * 1000.0;
1094     int code;
1095 
1096     if (glyph != gs_no_glyph &&
1097 	(code = font->procs.glyph_info(font, glyph, NULL,
1098 				       GLYPH_INFO_WIDTH0 << wmode,
1099 				       &info)) >= 0
1100 	) {
1101 	double w, v;
1102 
1103 	if (wmode && (w = info.width[wmode].y) != 0)
1104 	    v = info.width[wmode].x;
1105 	else
1106 	    w = info.width[wmode].x, v = info.width[wmode].y;
1107 	if (v != 0)
1108 	    return_error(gs_error_rangecheck);
1109 	*pwidth = (int)(w * scale);
1110 	/*
1111 	 * If the character is .notdef, don't cache the width,
1112 	 * just in case this is an incrementally defined font.
1113 	 */
1114 	return (gs_font_glyph_is_notdef((gs_font_base *)font, glyph) ? 1 : 0);
1115     } else {
1116 	/* Try for MissingWidth. */
1117 	gs_point scale2;
1118 	const gs_point *pscale = 0;
1119 	gs_font_info_t finfo;
1120 
1121 	if (scale != 1)
1122 	    scale2.x = scale2.y = scale, pscale = &scale2;
1123 	code = font->procs.font_info(font, pscale, FONT_INFO_MISSING_WIDTH,
1124 				     &finfo);
1125 	if (code < 0)
1126 	    return code;
1127 	*pwidth = finfo.MissingWidth;
1128 	/*
1129 	 * Don't mark the width as known, just in case this is an
1130 	 * incrementally defined font.
1131 	 */
1132 	return 1;
1133     }
1134 }
1135 
1136 /*
1137  * Find the range of character codes that includes all the defined
1138  * characters in a font.  This is a separate procedure only for
1139  * readability: it is only called from one place in pdf_update_text_state.
1140  */
1141 void
pdf_find_char_range(gs_font * font,int * pfirst,int * plast)1142 pdf_find_char_range(gs_font *font, int *pfirst, int *plast)
1143 {
1144     gs_glyph notdef = gs_no_glyph;
1145     int first = 0, last = 255;
1146     gs_glyph glyph;
1147 
1148     switch (font->FontType) {
1149     case ft_encrypted:
1150     case ft_encrypted2: {
1151 	/* Scan the Encoding vector looking for .notdef. */
1152 	gs_font_base *const bfont = (gs_font_base *)font;
1153 	int ch;
1154 
1155 	for (ch = 0; ch <= 255; ++ch) {
1156 	    gs_glyph glyph =
1157 		font->procs.encode_char(font, (gs_char)ch,
1158 					GLYPH_SPACE_INDEX);
1159 
1160 	    if (glyph == gs_no_glyph)
1161 		continue;
1162 	    if (gs_font_glyph_is_notdef(bfont, glyph)) {
1163 		notdef = glyph;
1164 		break;
1165 	    }
1166 	}
1167 	break;
1168     }
1169     default:
1170 	DO_NOTHING;
1171     }
1172     while (last >= first &&
1173 	   ((glyph =
1174 	     font->procs.encode_char(font, (gs_char)last,
1175 				     GLYPH_SPACE_INDEX))== gs_no_glyph ||
1176 	    glyph == notdef || glyph == gs_min_cid_glyph)
1177 	   )
1178 	--last;
1179     while (first <= last &&
1180 	   ((glyph =
1181 	     font->procs.encode_char(font, (gs_char)first,
1182 				     GLYPH_SPACE_INDEX))== gs_no_glyph ||
1183 	    glyph == notdef || glyph == gs_min_cid_glyph)
1184 	   )
1185 	++first;
1186     if (first > last)
1187 	last = first;	/* no characters used */
1188     *pfirst = first;
1189     *plast = last;
1190 }
1191 
1192 /* Compute the FontDescriptor.values for a font. */
1193 private int
font_char_bbox(gs_rect * pbox,gs_glyph * pglyph,gs_font * font,int ch,const gs_matrix * pmat)1194 font_char_bbox(gs_rect *pbox, gs_glyph *pglyph, gs_font *font, int ch,
1195 	       const gs_matrix *pmat)
1196 {
1197     gs_glyph glyph;
1198     gs_glyph_info_t info;
1199     int code;
1200 
1201     glyph = font->procs.encode_char(font, (gs_char)ch, GLYPH_SPACE_INDEX);
1202     if (glyph == gs_no_glyph)
1203 	return gs_error_undefined;
1204     code = font->procs.glyph_info(font, glyph, pmat, GLYPH_INFO_BBOX, &info);
1205     if (code < 0)
1206 	return code;
1207     *pbox = info.bbox;
1208     if (pglyph)
1209 	*pglyph = glyph;
1210     return 0;
1211 }
1212 int
pdf_compute_font_descriptor(gx_device_pdf * pdev,pdf_font_descriptor_t * pfd,gs_font * font,const byte * used)1213 pdf_compute_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd,
1214 			    gs_font *font, const byte *used /*[32]*/)
1215 {
1216     gs_font_base *bfont = (gs_font_base *)font;
1217     gs_glyph glyph, notdef;
1218     int index;
1219     int wmode = font->WMode;
1220     int members = (GLYPH_INFO_WIDTH0 << wmode) |
1221 	GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES;
1222     gs_glyph letters[52];
1223     int num_letters = 0;
1224     pdf_font_descriptor_values_t desc;
1225     gs_matrix smat;
1226     gs_matrix *pmat = NULL;
1227     int fixed_width = 0;
1228     int small_descent = 0, small_height = 0;
1229     int code;
1230 
1231     memset(&desc, 0, sizeof(desc));
1232     desc.FontType = font->FontType;
1233     desc.FontBBox.p.x = desc.FontBBox.p.y = max_int;
1234     desc.FontBBox.q.x = desc.FontBBox.q.y = min_int;
1235     /*
1236      * Embedded TrueType fonts use a 1000-unit character space, but the
1237      * font itself uses a 1-unit space.  Compensate for this here.
1238      */
1239     switch (font->FontType) {
1240     case ft_TrueType:
1241     case ft_CID_TrueType:
1242 	gs_make_scaling(1000.0, 1000.0, &smat);
1243 	pmat = &smat;
1244     default:
1245 	break;
1246     }
1247     /*
1248      * See the note on FONT_IS_ADOBE_ROMAN / FONT_USES_STANDARD_ENCODING
1249      * in gdevpdff.h for why the following substitution is made.
1250      */
1251 #if 0
1252 #  define CONSIDER_FONT_SYMBOLIC(font) font_is_symbolic(font)
1253 #else
1254 #  define CONSIDER_FONT_SYMBOLIC(font)\
1255   ((font)->FontType == ft_composite ||\
1256    ((const gs_font_base *)(font))->encoding_index != ENCODING_INDEX_STANDARD)
1257 #endif
1258     if (CONSIDER_FONT_SYMBOLIC(font))
1259 	desc.Flags |= FONT_IS_SYMBOLIC;
1260     else {
1261 	/*
1262 	 * Look at various specific characters to guess at the remaining
1263 	 * descriptor values (CapHeight, ItalicAngle, StemV, XHeight,
1264 	 * and flags SERIF, SCRIPT, ITALIC, ALL_CAPS, and SMALL_CAPS).
1265 	 * The algorithms are pretty crude.
1266 	 */
1267 	/*
1268 	 * Look at the glyphs for the lower-case letters.  If they are
1269 	 * all missing, this is an all-cap font; if any is present, check
1270 	 * the relative heights to determine whether this is a small-cap font.
1271 	 */
1272 	bool small_present = false;
1273 	int ch;
1274 	int x_height = min_int;
1275 	int cap_height = 0;
1276 	gs_rect bbox, bbox2;
1277 
1278 	desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */
1279 	for (ch = 'a'; ch <= 'z'; ++ch) {
1280 	    int y0, y1;
1281 
1282 	    code =
1283 		font_char_bbox(&bbox, &letters[num_letters], font, ch, pmat);
1284 	    if (code < 0)
1285 		continue;
1286 	    ++num_letters;
1287 	    rect_merge(desc.FontBBox, bbox);
1288 	    small_present = true;
1289 	    y0 = (int)bbox.p.y;
1290 	    y1 = (int)bbox.q.y;
1291 	    switch (ch) {
1292 	    case 'b': case 'd': case 'f': case 'h':
1293 	    case 'k': case 'l': case 't': /* ascender */
1294 		small_height = max(small_height, y1);
1295 	    case 'i':		/* anomalous ascent */
1296 		break;
1297 	    case 'j':		/* descender with anomalous ascent */
1298 		small_descent = min(small_descent, y0);
1299 		break;
1300 	    case 'g': case 'p': case 'q': case 'y': /* descender */
1301 		small_descent = min(small_descent, y0);
1302 	    default:		/* no ascender or descender */
1303 		x_height = max(x_height, y1);
1304 	    }
1305 	}
1306 	desc.XHeight = (int)x_height;
1307 	if (!small_present)
1308 	    desc.Flags |= FONT_IS_ALL_CAPS;
1309 	for (ch = 'A'; ch <= 'Z'; ++ch) {
1310 	    code =
1311 		font_char_bbox(&bbox, &letters[num_letters], font, ch, pmat);
1312 	    if (code < 0)
1313 		continue;
1314 	    ++num_letters;
1315 	    rect_merge(desc.FontBBox, bbox);
1316 	    cap_height = max(cap_height, (int)bbox.q.y);
1317 	}
1318 	desc.CapHeight = cap_height;
1319 	/*
1320 	 * Look at various glyphs to determine ItalicAngle, StemV,
1321 	 * SERIF, SCRIPT, and ITALIC.
1322 	 */
1323 	if ((code = font_char_bbox(&bbox, NULL, font, ':', pmat)) >= 0 &&
1324 	    (code = font_char_bbox(&bbox2, NULL, font, '.', pmat)) >= 0
1325 	    ) {
1326 	    /* Calculate the dominant angle. */
1327 	    int angle =
1328 		(int)(atan2((bbox.q.y - bbox.p.y) - (bbox2.q.y - bbox2.p.y),
1329 			    (bbox.q.x - bbox.p.x) - (bbox2.q.x - bbox2.p.x)) *
1330 		      radians_to_degrees) - 90;
1331 
1332 	    /* Normalize to [-90..90]. */
1333 	    while (angle > 90)
1334 		angle -= 180;
1335 	    while (angle < -90)
1336 		angle += 180;
1337 	    if (angle < -30)
1338 		angle = -30;
1339 	    else if (angle > 30)
1340 		angle = 30;
1341 	    /*
1342 	     * For script or embellished fonts, we can get an angle that is
1343 	     * slightly off from zero even for non-italic fonts.
1344 	     * Compensate for this now.
1345 	     */
1346 	    if (angle <= 2 && angle >= -2)
1347 		angle = 0;
1348 	    desc.ItalicAngle = angle;
1349 	}
1350 	if (desc.ItalicAngle)
1351 	    desc.Flags |= FONT_IS_ITALIC;
1352 	if (code >= 0) {
1353 	    double wdot = bbox2.q.x - bbox2.p.x;
1354 
1355 	    if ((code = font_char_bbox(&bbox2, NULL, font, 'I', pmat)) >= 0) {
1356 		double wcolon = bbox.q.x - bbox.p.x;
1357 		double wI = bbox2.q.x - bbox2.p.x;
1358 
1359 		desc.StemV = (int)wdot;
1360 		if (wI > wcolon * 2.5 || wI > (bbox2.q.y - bbox2.p.y) * 0.25)
1361 		    desc.Flags |= FONT_IS_SERIF;
1362 	    }
1363 	}
1364     }
1365     /*
1366      * Scan the entire glyph space to compute Ascent, Descent, FontBBox,
1367      * and the fixed width if any.  Avoid computing the bounding box of
1368      * letters a second time.
1369      */
1370     num_letters = psf_sort_glyphs(letters, num_letters);
1371     desc.Ascent = desc.FontBBox.q.y;
1372     notdef = gs_no_glyph;
1373     for (index = 0;
1374 	 (code = font->procs.enumerate_glyph(font, &index, GLYPH_SPACE_INDEX, &glyph)) >= 0 &&
1375 	     index != 0;
1376 	 ) {
1377 	gs_glyph_info_t info;
1378 
1379 	if (psf_sorted_glyphs_include(letters, num_letters, glyph)) {
1380 	    /* We don't need the bounding box. */
1381 	    code = font->procs.glyph_info(font, glyph, pmat,
1382 					  members - GLYPH_INFO_BBOX, &info);
1383 	    if (code < 0)
1384 		return code;
1385 	} else {
1386 	    code = font->procs.glyph_info(font, glyph, pmat, members, &info);
1387 	    if (code < 0)
1388 		return code;
1389 	    rect_merge(desc.FontBBox, info.bbox);
1390 	    if (!info.num_pieces)
1391 		desc.Ascent = max(desc.Ascent, info.bbox.q.y);
1392 	}
1393 	if (notdef == gs_no_glyph && gs_font_glyph_is_notdef(bfont, glyph)) {
1394 	    notdef = glyph;
1395 	    desc.MissingWidth = info.width[wmode].x;
1396 	}
1397 	if (info.width[wmode].y != 0)
1398 	    fixed_width = min_int;
1399 	else if (fixed_width == 0)
1400 	    fixed_width = info.width[wmode].x;
1401 	else if (info.width[wmode].x != fixed_width)
1402 	    fixed_width = min_int;
1403     }
1404     if (code < 0)
1405 	return code;
1406     if (desc.Ascent == 0)
1407 	desc.Ascent = desc.FontBBox.q.y;
1408     desc.Descent = desc.FontBBox.p.y;
1409     if (!(desc.Flags & (FONT_IS_SYMBOLIC | FONT_IS_ALL_CAPS)) &&
1410 	(small_descent > desc.Descent / 3 || desc.XHeight > small_height * 0.9)
1411 	)
1412 	desc.Flags |= FONT_IS_SMALL_CAPS;
1413     if (fixed_width > 0) {
1414 	desc.Flags |= FONT_IS_FIXED_WIDTH;
1415 	desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width;
1416     }
1417     if (desc.CapHeight == 0)
1418 	desc.CapHeight = desc.Ascent;
1419     if (desc.StemV == 0)
1420 	desc.StemV = (int)(desc.FontBBox.q.x * 0.15);
1421     pfd->values = desc;
1422     return 0;
1423 }
1424