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