1 /*---------------------------------------------------------------------------*
2 | PDFlib - A library for generating PDF on the fly |
3 +---------------------------------------------------------------------------+
4 | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
5 +---------------------------------------------------------------------------+
6 | |
7 | This software is subject to the PDFlib license. It is NOT in the |
8 | public domain. Extended versions and commercial licenses are |
9 | available, please check http://www.pdflib.com. |
10 | |
11 *---------------------------------------------------------------------------*/
12
13 /* $Id: p_font.c,v 1.461.2.80 2011/05/02 10:42:22 kurt Exp $
14 *
15 * PDFlib font handling routines
16 *
17 */
18
19 #define P_FONT_C
20
21 #include "p_intern.h"
22 #include "p_color.h"
23 #include "p_defopt.h"
24 #include "p_font.h"
25 #include "p_tagged.h"
26
27 #include "ft_truetype.h"
28
29
30 #define PDF_TTC_SEPARATOR ':'
31
32 static const pdc_keyconn pdf_fonttype_pdfkeylist[] =
33 {
34 {"Type1", fnt_Type1},
35 {"MMType1", fnt_MMType1},
36 {"TrueType", fnt_TrueType},
37 {"Type0", fnt_CIDFontType2},
38 {"Type1", fnt_Type1C},
39 {"Type0", fnt_CIDFontType0},
40 {"Type3", fnt_Type3},
41 {NULL, 0}
42 };
43
44 typedef enum
45 {
46 font_afm = 1,
47 font_pfm = 2,
48 font_ttot = 3,
49 font_pfab = 4
50 }
51 pdf_fontfile_type;
52
53 static const pdc_keyconn pdf_extension_names[] =
54 {
55 {".tte", font_ttot},
56 {".ttf", font_ttot},
57 {".otf", font_ttot},
58 {".afm", font_afm},
59 {".pfm", font_pfm},
60 {".ttc", font_ttot},
61 {".TTE", font_ttot},
62 {".TTF", font_ttot},
63 {".OTF", font_ttot},
64 {".AFM", font_afm},
65 {".PFM", font_pfm},
66 {".TTC", font_ttot},
67 {".pfa", font_pfab},
68 {".pfb", font_pfab},
69 {".PFA", font_pfab},
70 {".PFB", font_pfab},
71 {NULL, 0}
72 };
73
74 static const pdc_keyconn pdf_fontoption_keylist[] =
75 {
76 {"fontname", fo_fontname},
77 {"encoding", fo_encoding},
78 {"fontstyle", fo_fontstyle},
79 {"monospace", fo_monospace},
80 {NULL, 0}
81 };
82
83
84 void
pdf_init_font(PDF * p,pdf_font * font,pdf_font_options * fo)85 pdf_init_font(PDF *p, pdf_font *font, pdf_font_options *fo)
86 {
87 (void) p;
88
89 /* font metric */
90 fnt_init_font(&font->ft);
91
92 /* font options */
93 font->opt = *fo;
94 font->verbose = fo->fontwarning;
95
96 font->apiname = NULL;
97 font->filename = NULL;
98 font->metricfilename = NULL;
99
100 font->used_in_formfield = pdc_false;
101 font->used_in_current_doc = pdc_false;
102 font->used_on_current_page = pdc_false;
103 font->obj_id = PDC_BAD_ID;
104
105 font->cff_offset = 0;
106 font->cff_length = 0;
107
108 font->t3font = NULL;
109 font->hasoriginal = pdc_false;
110
111 font->encapiname = NULL;
112 font->outcmapname = NULL;
113 font->codepage = 0;
114 font->towinansi = pdc_invalidenc;
115 font->hasnomac = pdc_false;
116 font->passthrough = pdc_false;
117 font->unibyte = pdc_false;
118 font->asciispace = pdc_false;
119 font->issemantic = pdc_false;
120 font->widthsmissing = pdc_false;
121 font->missingglyphs = 0;
122 font->metricflags = 0;
123 font->supplement = 0;
124 font->symenc = pdc_invalidenc;
125 font->replacementchar = -1;
126 font->replacementcode = -1;
127
128 font->codesize = 1;
129 font->lastcode = -1;
130 font->gid0code = -1;
131 font->usedgids = NULL;
132 font->expectglyphs = pdc_false;
133 font->iscidfont = pdc_false;
134
135 font->widths = NULL;
136 font->numwidths = 0;
137 font->konlydef = pdc_false;
138
139 }
140
141 void
pdf_cleanup_font(PDF * p,pdf_font * font)142 pdf_cleanup_font(PDF *p, pdf_font *font)
143 {
144 if (font->ft.imgname)
145 pdc_unlock_pvf(p->pdc, font->ft.imgname);
146
147 /* font metric */
148 fnt_cleanup_font(p->pdc, &font->ft);
149
150 if (font->apiname != NULL)
151 {
152 pdc_free(p->pdc, font->apiname);
153 font->apiname = NULL;
154 }
155
156 if (font->metricfilename != NULL)
157 {
158 pdc_free(p->pdc, font->metricfilename);
159 font->metricfilename = NULL;
160 }
161
162 if (font->encapiname != NULL)
163 {
164 pdc_free(p->pdc, font->encapiname);
165 font->encapiname = NULL;
166 }
167
168 if (font->outcmapname != NULL)
169 {
170 pdc_free(p->pdc, font->outcmapname);
171 font->outcmapname = NULL;
172 }
173
174
175 if (font->usedgids != NULL)
176 {
177 pdc_free(p->pdc, font->usedgids);
178 font->usedgids = NULL;
179 }
180
181 /* Type3 font */
182 if (font->t3font != NULL && font->hasoriginal)
183 {
184 pdf_cleanup_t3font(p, font->t3font);
185 pdc_free(p->pdc, font->t3font);
186 font->t3font = NULL;
187 }
188
189 if (font->widths != NULL)
190 {
191 pdc_free(p->pdc, font->widths);
192 font->widths = NULL;
193 }
194
195 }
196
197 void
pdf_init_fonts(PDF * p)198 pdf_init_fonts(PDF *p)
199 {
200 p->fonts = NULL;
201 p->fonts_number = 0;
202 p->fonts_capacity = 0;
203 p->t3slot = -1;
204
205
206 pdc_init_encoding_info_ids(p->pdc);
207 }
208
209 void
pdf_cleanup_fonts(PDF * p)210 pdf_cleanup_fonts(PDF *p)
211 {
212 int slot;
213
214 if (p->fonts != NULL)
215 {
216 for (slot = 0; slot < p->fonts_number; slot++)
217 pdf_cleanup_font(p, &p->fonts[slot]);
218
219 pdc_free(p->pdc, p->fonts);
220 p->fonts = NULL;
221 }
222
223 }
224
225 int
pdf_insert_font(PDF * p,pdf_font * font)226 pdf_insert_font(PDF *p, pdf_font *font)
227 {
228 static const char fn[] = "pdf_insert_font";
229 int slot = p->fonts_number;
230
231 /* insert font */
232 if (p->fonts_number == p->fonts_capacity)
233 {
234 if (p->fonts_capacity == 0)
235 {
236 p->fonts_capacity = FONTS_CHUNKSIZE;
237 p->fonts = (pdf_font *) pdc_calloc(p->pdc,
238 sizeof(pdf_font) * p->fonts_capacity, fn);
239 }
240 else
241 {
242 p->fonts_capacity *= 2;
243 p->fonts = (pdf_font *) pdc_realloc(p->pdc, p->fonts,
244 sizeof(pdf_font) * p->fonts_capacity, fn);
245 }
246 }
247 p->fonts[slot] = *font;
248
249 p->fonts_number++;
250
251 return slot;
252 }
253
254
255 const char *
pdf_get_pdf_fontname(pdf_font * font)256 pdf_get_pdf_fontname(pdf_font *font)
257 {
258 const char *fontname;
259
260 fontname = fnt_get_abb_std_fontname(font->ft.name);
261 if (fontname == NULL)
262 fontname = fnt_get_abb_cjk_fontname(font->ft.name);
263 if (fontname == NULL)
264 fontname = font->ft.name;
265
266 return (const char *) fontname;
267 }
268
269 const char *
pdf_get_encoding_name(PDF * p,pdc_encoding enc,pdf_font * font)270 pdf_get_encoding_name(PDF *p, pdc_encoding enc, pdf_font *font)
271 {
272 const char *apiname = pdc_get_fixed_encoding_name(enc);
273 if (!apiname[0] && enc >= 0)
274 {
275 pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
276 apiname = (const char *) ev->apiname;
277 }
278 else if (enc == pdc_cid && font != NULL && font->outcmapname != NULL)
279 apiname = (const char *) font->outcmapname;
280 return apiname;
281 }
282
283 char *
pdf_get_encoding_adaptname(PDF * p,pdc_encoding enc,pdf_font * font,const char * fontname)284 pdf_get_encoding_adaptname(PDF *p, pdc_encoding enc, pdf_font *font,
285 const char *fontname)
286 {
287 static const char *fn = "pdf_get_encoding_adaptname";
288 char *encname = (char *) pdf_get_encoding_name(p, enc, font);
289 char *adaptname = NULL;
290 size_t len;
291
292 len = strlen(encname) + 1 + strlen(fontname) + 1;
293 adaptname = (char *) pdc_malloc_tmp(p->pdc, len, fn, 0, 0);
294 strcpy(adaptname, encname);
295 strcat(adaptname, PDC_ENC_MODSEPAR);
296 strcat(adaptname, fontname);
297
298 return adaptname;
299 }
300
301 pdc_encodingvector *
pdf_create_font_encoding(PDF * p,pdc_encoding enc,pdf_font * font,const char * fontname,pdc_bool kreg)302 pdf_create_font_encoding(PDF *p, pdc_encoding enc, pdf_font *font,
303 const char *fontname, pdc_bool kreg)
304 {
305 pdc_encodingvector *ev = NULL;
306 char *adaptname = NULL;
307
308 adaptname = pdf_get_encoding_adaptname(p, enc, font, fontname);
309
310 /* search for a registered encoding */
311 enc = pdc_find_encoding(p->pdc, adaptname);
312 if (enc != pdc_invalidenc)
313 {
314 font->ft.enc = enc;
315 }
316 else
317 {
318 /* create a font encoding */
319 ev = pdc_new_encoding(p->pdc, adaptname);
320 ev->flags |= PDC_ENC_FONT;
321 ev->flags |= PDC_ENC_SETNAMES;
322
323 if (kreg)
324 {
325 enc = pdc_insert_encoding_vector(p->pdc, ev);
326 font->ft.enc = enc;
327 }
328 }
329
330 pdc_free_tmp(p->pdc, adaptname);
331
332 return ev;
333 }
334
335 const char *
pdf_get_font_char_option(PDF * p,pdf_font_optflags fflags)336 pdf_get_font_char_option(PDF *p, pdf_font_optflags fflags)
337 {
338 pdf_text_options *to = p->curr_ppt->currto;
339 pdf_font *currfont;
340
341 if (p->fonts_number == 0 || to->font == -1)
342 pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR,
343 pdc_get_keyword(fflags, pdf_fontoption_keylist), 0, 0, 0);
344 currfont = &p->fonts[to->font];
345
346 switch (fflags)
347 {
348 case fo_fontname:
349 return (const char *) currfont->ft.name;
350
351 case fo_encoding:
352 return pdf_get_encoding_name(p, currfont->ft.enc, currfont);
353
354 case fo_fontstyle:
355 return pdc_get_keyword(currfont->opt.fontstyle,
356 pdf_fontstyle_pdfkeylist);
357
358 default:
359 return NULL;
360 }
361 }
362
363 double
pdf_get_font_float_option(PDF * p,pdf_font_optflags fflags)364 pdf_get_font_float_option(PDF *p, pdf_font_optflags fflags)
365 {
366 pdf_text_options *to = p->curr_ppt->currto;
367 pdf_font *currfont;
368
369 if (p->fonts_number == 0 || to->font == -1)
370 pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR,
371 pdc_get_keyword(fflags, pdf_fontoption_keylist), 0, 0, 0);
372 currfont = &p->fonts[to->font];
373
374 switch (fflags)
375 {
376 case fo_monospace:
377 return (double) currfont->opt.monospace;
378
379 default:
380 return 0;
381 }
382 }
383
384 static const pdc_keyconn pdf_courier_keylist[] =
385 {
386 {"Courier", fnt_Normal},
387 {"Courier-Bold", fnt_Bold},
388 {"Courier-Oblique", fnt_Italic},
389 {"Courier-BoldOblique", fnt_BoldItalic},
390 {NULL, 0}
391 };
392
393 static const pdc_keyconn pdf_helvetica_keylist[] =
394 {
395 {"Helvetica", fnt_Normal},
396 {"Helvetica-Bold", fnt_Bold},
397 {"Helvetica-Oblique", fnt_Italic},
398 {"Helvetica-BoldOblique", fnt_BoldItalic},
399 {NULL, 0}
400 };
401
402 static const pdc_keyconn pdf_times_keylist[] =
403 {
404 {"Times-Roman", fnt_Normal},
405 {"Times-Bold", fnt_Bold},
406 {"Times-Italic", fnt_Italic},
407 {"Times-BoldItalic", fnt_BoldItalic},
408 {NULL, 0}
409 };
410
411 static const char *
pdf_get_fontname_core(pdf_font * font,const char * fontname,pdc_bool checktimes)412 pdf_get_fontname_core(pdf_font *font, const char *fontname, pdc_bool checktimes)
413 {
414 const char *fname = NULL;
415
416 /* font style for core fonts */
417 if (font->opt.fontstyle != fnt_Normal)
418 {
419 if (!strcmp(fontname, "Courier"))
420 fname = pdc_get_keyword(font->opt.fontstyle, pdf_courier_keylist);
421 else if (!strcmp(fontname, "Helvetica"))
422 fname = pdc_get_keyword(font->opt.fontstyle, pdf_helvetica_keylist);
423 else if (!strcmp(fontname, "Times-Roman"))
424 fname = pdc_get_keyword(font->opt.fontstyle, pdf_times_keylist);
425 }
426
427 if (checktimes)
428 {
429 if (!strcmp(fontname, "Times"))
430 fname = pdc_get_keyword(font->opt.fontstyle, pdf_times_keylist);
431 }
432
433 return fname;
434 }
435
436 static pdc_bool
pdf_get_metrics_core(PDF * p,pdf_font * font,const char * fontname,const char * outfilename,pdc_encoding enc,pdc_bool checktimes)437 pdf_get_metrics_core(PDF *p, pdf_font *font, const char *fontname,
438 const char *outfilename, pdc_encoding enc, pdc_bool checktimes)
439 {
440 static const char fn[] = "pdf_get_metrics_core";
441 const char *fname = NULL;
442 const fnt_font_metric *ftm;
443
444 fname = pdf_get_fontname_core(font, fontname, checktimes);
445 if (fname != NULL)
446 {
447 fontname = fname;
448 font->opt.fontstyle = fnt_Normal;
449
450 if (font->apiname != NULL)
451 {
452 pdc_free(p->pdc, font->apiname);
453 font->apiname = pdc_strdup_ext(p->pdc, fontname, 0, fn);
454 }
455 }
456
457 ftm = fnt_get_core_metric(fontname);
458 if (ftm != NULL && (!font->opt.embedding || outfilename != NULL))
459 {
460 pdc_logg_cond(p->pdc, 1, trc_font,
461 "\tLoading metrics data for core font \"%s\":\n", fontname);
462
463 /* Fill up the font struct */
464 fnt_fill_font_metric(p->pdc, &font->ft,
465 pdc_false,
466 ftm);
467 font->ft.enc = enc;
468
469 /* all new glyph names of AGL 2.0 are missing */
470 font->missingglyphs = 0xFFFFFFFF;
471
472 /* Process metrics data */
473 if (pdf_process_metrics_data(p, font, fontname))
474 {
475 if (pdf_make_fontflag(p, font))
476 {
477 if (!font->opt.monospace)
478 return pdc_true;
479 else
480 pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace",
481 0, 0, 0);
482 }
483 }
484
485 return pdc_false;
486 }
487
488 return pdc_undef;
489 }
490
491 void
pdf_font_set_missvalues(PDF * p,pdf_font * font)492 pdf_font_set_missvalues(PDF *p, pdf_font *font)
493 {
494 pdf_font_options *fo = &font->opt;
495 fnt_font_metric *ftm = &font->ft.m;
496
497 (void) p;
498
499 if (ftm->descender > 0)
500 ftm->descender = -(ftm->descender);
501
502 if (fo->mask & (1L << fo_ascender))
503 {
504 font->metricflags |= font_ascender;
505 ftm->ascender = fo->ascender;
506 }
507 else if (ftm->ascender <= 0)
508 {
509 font->metricflags |= font_ascender;
510 ftm->ascender = 720;
511 }
512
513 if (fo->mask & (1L << fo_descender))
514 {
515 font->metricflags |= font_descender;
516 ftm->descender = fo->descender;
517 }
518 else if (ftm->descender == FNT_MISSING_FONTVAL)
519 {
520 font->metricflags |= font_descender;
521 ftm->descender = (int) PDC_ROUND(-0.25 * ftm->ascender);
522 }
523
524 if (fo->mask & (1L << fo_capheight))
525 {
526 font->metricflags |= font_capheight;
527 ftm->capHeight = fo->capheight;
528 }
529 else if (ftm->capHeight <= 0)
530 {
531 font->metricflags |= font_capheight;
532 ftm->capHeight = (int) PDC_ROUND(0.93 * ftm->ascender);
533 }
534
535 if (fo->mask & (1L << fo_xheight))
536 {
537 font->metricflags |= font_xheight;
538 ftm->xHeight = fo->xheight;
539 }
540 else if (ftm->xHeight <= 0)
541 {
542 font->metricflags |= font_xheight;
543 ftm->xHeight = (int) PDC_ROUND(0.66 * ftm->ascender);
544 }
545
546 if (fo->mask & (1L << fo_linegap))
547 {
548 font->metricflags |= font_linegap;
549 font->ft.linegap = fo->linegap;
550 }
551 else if (font->ft.linegap == FNT_MISSING_FONTVAL)
552 {
553 font->metricflags |= font_linegap;
554 font->ft.linegap = (int) PDC_ROUND(0.23 * ftm->ascender);
555 }
556
557 if (ftm->llx == FNT_MISSING_FONTVAL)
558 ftm->llx = -50;
559 if (ftm->lly == FNT_MISSING_FONTVAL)
560 ftm->lly = ftm->descender;
561 if (ftm->urx == FNT_MISSING_FONTVAL)
562 ftm->urx = 1000;
563 if (ftm->ury == FNT_MISSING_FONTVAL)
564 ftm->ury = ftm->ascender;
565
566 /* try to fix broken entries */
567 if (ftm->lly > ftm->ury)
568 ftm->ury = ftm->lly + ftm->ascender;
569 if (ftm->llx > ftm->urx)
570 ftm->urx = ftm->llx + 1000;
571 }
572
573 pdc_bool
pdf_font_get_is_faked(pdf_font * font,pdf_font_values flag)574 pdf_font_get_is_faked(pdf_font *font, pdf_font_values flag)
575 {
576 return (font->metricflags & flag) ? pdc_true : pdc_false;
577 }
578
579 double
pdf_font_get_metric_value(int value)580 pdf_font_get_metric_value(int value)
581 {
582 return (double) value / 1000.0;
583 }
584
585
586 /* --------------------------- font processing ---------------------------- */
587
588 pdc_bool
pdf_make_fontflag(PDF * p,pdf_font * font)589 pdf_make_fontflag(PDF *p, pdf_font *font)
590 {
591 int errcode = 0;
592
593 if (font->ft.m.type != fnt_Type3)
594 {
595 if (font->ft.m.isFixedPitch)
596 font->ft.m.flags |= FNT_FIXEDWIDTH;
597
598 if (font->ft.issymbfont == pdc_false ||
599 font->ft.enc == pdc_winansi ||
600 font->ft.enc == pdc_macroman ||
601 font->ft.enc == pdc_ebcdic ||
602 font->ft.enc == pdc_ebcdic_37 ||
603 font->ft.enc == pdc_ebcdic_winansi)
604 font->ft.m.flags |= FNT_ADOBESTANDARD;
605 else
606 font->ft.m.flags |= FNT_SYMBOL;
607
608 if (font->ft.m.italicAngle < 0 ||
609 font->opt.fontstyle == fnt_Italic ||
610 font->opt.fontstyle == fnt_BoldItalic)
611 font->ft.m.flags |= FNT_ITALIC;
612 if (font->ft.m.italicAngle == 0 &&
613 font->ft.m.flags & FNT_ITALIC)
614 font->ft.m.italicAngle = FNT_DEF_ITALICANGLE;
615
616 /* heuristic to identify (small) caps fonts */
617 if (font->ft.name &&
618 (strstr(font->ft.name, "Caps") ||
619 !strcmp(font->ft.name + strlen(font->ft.name) - 2, "SC")))
620 font->ft.m.flags |= FNT_SMALLCAPS;
621
622 if (font->opt.fontstyle == fnt_Bold ||
623 font->opt.fontstyle == fnt_BoldItalic)
624 font->ft.weight = FNT_FW_BOLD;
625
626 if (strstr(font->ft.name, "Bold") ||
627 font->ft.weight >= FNT_FW_BOLD)
628 font->ft.m.flags |= FNT_FORCEBOLD;
629
630 /* determine values for FontWeight to StemV */
631 if (font->ft.m.StdVW == 0)
632 font->ft.m.StdVW = fnt_weight2stemv(font->ft.weight);
633 else if (font->ft.weight == 0)
634 font->ft.weight = fnt_stemv2weight(font->ft.m.StdVW);
635 }
636
637 fnt_font_logg_protocol(p->pdc, &font->ft);
638
639 switch(font->ft.m.type)
640 {
641 case fnt_Type1:
642 case fnt_MMType1:
643 case fnt_Type3:
644 if (font->opt.fontstyle == fnt_Bold ||
645 font->opt.fontstyle == fnt_BoldItalic)
646 {
647 font->metricflags |= font_bold;
648 }
649
650 if (font->opt.fontstyle == fnt_Italic ||
651 font->opt.fontstyle == fnt_BoldItalic)
652 {
653 font->metricflags |= font_italic;
654 }
655
656 break;
657
658 default:
659 if (font->opt.embedding)
660 {
661 if (font->opt.fontstyle == fnt_Bold ||
662 font->opt.fontstyle == fnt_BoldItalic)
663 {
664 font->metricflags |= font_bold;
665 }
666
667 if (font->opt.fontstyle == fnt_Italic ||
668 font->opt.fontstyle == fnt_BoldItalic)
669 {
670 font->metricflags |= font_italic;
671 }
672 }
673 break;
674 }
675
676
677 return errcode ? pdc_false : pdc_true;
678 }
679
680 int
pdf_get_code_or_glyphid(PDF * p,pdf_font * font,pdc_encodingvector * ev,pdc_ushort uv)681 pdf_get_code_or_glyphid(PDF *p, pdf_font *font, pdc_encodingvector *ev,
682 pdc_ushort uv)
683 {
684 if (ev != NULL)
685 {
686 int code = pdc_get_encoding_bytecode(p->pdc, ev, uv);
687
688 if (code >= 0)
689 {
690 if (fnt_get_glyphid(code, &font->ft) <= 0)
691 code = 0;
692 }
693 return code;
694 }
695
696 return fnt_get_glyphid((int) uv, &font->ft);
697 }
698
699 void
pdf_set_replchar(PDF * p,pdf_font * font)700 pdf_set_replchar(PDF *p, pdf_font *font)
701 {
702 pdc_encoding enc = font->ft.enc;
703
704 switch (enc)
705 {
706 case pdc_glyphid:
707 case pdc_cid:
708 return;
709
710 case pdc_builtin:
711 font->replacementcode = 0;
712 return;
713
714 case pdc_unicode:
715 default:
716 {
717 pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
718 pdc_ushort uv = 0;
719 int cg = 0;
720 uv = PDC_UNICODE_NBSP;
721 cg = pdf_get_code_or_glyphid(p, font, ev, uv);
722 if (cg <= 0)
723 {
724 uv = PDC_UNICODE_SPACE;
725 cg = pdf_get_code_or_glyphid(p, font, ev, uv);
726 if (cg <= 0)
727 {
728 uv = 0;
729 cg = 0;
730 }
731 }
732
733 font->replacementchar = (int) uv;
734 font->replacementcode = cg;
735 }
736 return;
737 }
738 }
739
740 void
pdf_font_issemantic(PDF * p,pdf_font * font)741 pdf_font_issemantic(PDF *p, pdf_font *font)
742 {
743 pdc_encoding enc = font->ft.enc;
744 pdc_ushort spacechar = 0;
745
746 /* Flag: encoding with ASCII space for wordspacing */
747 if (enc >= 0)
748 {
749 pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
750 int i;
751
752 ev->flags |= PDC_ENC_USED;
753 i = pdc_get_encoding_bytecode(p->pdc, ev, PDC_UNICODE_SPACE);
754 if (i > -1)
755 {
756 spacechar = (pdc_ushort) i;
757 if (spacechar == PDC_UNICODE_SPACE)
758 font->asciispace = pdc_true;
759 }
760 }
761
762 /* Flag: encoding is Unicode interpretable */
763 if ((enc >= 0) ||
764 (enc == pdc_cid && font->codesize == 2) ||
765 (enc == pdc_unicode))
766 font->issemantic = pdc_true;
767
768 /* determine code of space character */
769 switch(enc)
770 {
771 case pdc_cid:
772 if (font->codesize == 2)
773 font->ft.spacechar = PDC_UNICODE_SPACE;
774 break;
775
776 case pdc_unicode:
777 font->ft.spacechar = PDC_UNICODE_SPACE;
778 break;
779
780 case pdc_glyphid:
781 font->ft.spacechar =
782 (pdc_ushort) MAX(fnt_get_glyphid(PDC_UNICODE_SPACE, &font->ft), 0);
783 break;
784
785 default:
786 font->ft.spacechar = spacechar;
787 break;
788 }
789 }
790
791 /* definitions of font options */
792 static const pdc_defopt pdf_load_font_options[] =
793 {
794 PDF_FONT_OPTIONS2
795 PDF_FONT_OPTIONS3
796 PDF_ERRORPOLICY_OPTION
797 PDC_OPT_TERMINATE
798 };
799
800 void
pdf_init_font_options(PDF * p,pdf_font_options * fo)801 pdf_init_font_options(PDF *p, pdf_font_options *fo)
802 {
803 static const char fn[] = "pdf_init_font_options";
804
805 if (fo == NULL)
806 {
807 p->currfo = (pdf_font_options *) pdc_malloc(p->pdc,
808 sizeof(pdf_font_options), fn);
809
810
811 fo = p->currfo;
812 }
813 else
814 {
815 }
816
817
818 fo->embedding = pdc_false; /* default true if CID custom font */
819 fo->encoding = NULL;
820 fo->flags = 0;
821 fo->fontname = NULL;
822 fo->fontstyle = fnt_Normal;
823 fo->fontwarning = p->debug[(int) 'F'];
824 fo->fontwarning = pdf_get_errorpolicy(p, NULL, fo->fontwarning);
825 fo->mask = 0;
826 fo->monospace = 0;
827 fo->ascender = 0;
828 fo->descender = 0;
829 fo->capheight = 0;
830 fo->xheight = 0;
831 fo->linegap = 0;
832 fo->auxiliary = pdc_false;
833 fo->dropcorewidths = pdc_false;
834
835 }
836
837 void
pdf_cleanup_font_curroptions(PDF * p)838 pdf_cleanup_font_curroptions(PDF *p)
839 {
840 if (p->currfo)
841 {
842 pdc_free(p->pdc, p->currfo);
843 p->currfo = NULL;
844 }
845 }
846
847 void
pdf_cleanup_font_options(PDF * p,pdf_font_options * fo)848 pdf_cleanup_font_options(PDF *p, pdf_font_options *fo)
849 {
850 if (fo->fontname != NULL)
851 {
852 pdc_free(p->pdc, fo->fontname);
853 fo->fontname = NULL;
854 }
855
856 if (fo->encoding != NULL)
857 {
858 pdc_free(p->pdc, fo->encoding);
859 fo->encoding = NULL;
860 }
861 }
862
863 void
pdf_parse_font_options(PDF * p,const char * optlist)864 pdf_parse_font_options(PDF *p, const char *optlist)
865 {
866 pdc_resopt *resopts = pdc_parse_optionlist(p->pdc, optlist,
867 pdf_load_font_options, NULL, pdc_true);
868
869 pdf_get_font_options(p, p->currfo, resopts);
870 pdc_cleanup_optionlist(p->pdc, resopts);
871 }
872
873 void
pdf_get_font_options(PDF * p,pdf_font_options * fo,pdc_resopt * resopts)874 pdf_get_font_options(PDF *p, pdf_font_options *fo, pdc_resopt *resopts)
875 {
876 int inum;
877
878 (void) p;
879
880 if (fo->flags & is_block ||
881 fo->flags & is_textline ||
882 fo->flags & is_textflow)
883 {
884 if (pdc_get_optvalues("fontname", resopts, NULL, NULL))
885 {
886 fo->fontname = (char *)pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
887 fo->mask |= (1L << fo_fontname);
888 }
889
890 if (pdc_get_optvalues("encoding", resopts, NULL, NULL))
891 {
892 fo->encoding = (char *)pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
893 fo->mask |= (1L << fo_encoding);
894 }
895 }
896
897 if (pdc_get_optvalues("fontwarning", resopts, &fo->fontwarning, NULL))
898 fo->mask |= (1L << fo_fontwarning);
899 fo->fontwarning = pdf_get_errorpolicy(p, resopts, fo->fontwarning);
900
901 if (pdc_get_optvalues("embedding", resopts, &fo->embedding, NULL))
902 fo->mask |= (1L << fo_embedding);
903
904
905 if (pdc_get_optvalues("fontstyle", resopts, &inum, NULL))
906 {
907 fo->fontstyle = (fnt_fontstyle) inum;
908 fo->mask |= (1L << fo_fontstyle);
909 }
910
911 if (pdc_get_optvalues("monospace", resopts, &fo->monospace, NULL))
912 fo->mask |= (1L << fo_monospace);
913
914 if (pdc_get_optvalues("ascender", resopts, &fo->ascender, NULL))
915 fo->mask |= (1L << fo_ascender);
916
917 if (pdc_get_optvalues("descender", resopts, &fo->descender, NULL))
918 fo->mask |= (1L << fo_descender);
919
920 if (pdc_get_optvalues("capheight", resopts, &fo->capheight, NULL))
921 fo->mask |= (1L << fo_capheight);
922
923 if (pdc_get_optvalues("xheight", resopts, &fo->xheight, NULL))
924 fo->mask |= (1L << fo_xheight);
925
926 if (pdc_get_optvalues("linegap", resopts, &fo->linegap, NULL))
927 fo->mask |= (1L << fo_linegap);
928
929
930 pdc_get_optvalues("dropcorewidths", resopts, &fo->dropcorewidths, NULL);
931 }
932
933 int
pdf__load_font(PDF * p,const char * fontname,int len,const char * encoding,const char * optlist)934 pdf__load_font(PDF *p, const char *fontname, int len,
935 const char *encoding, const char *optlist)
936 {
937 int slot;
938 pdf_font_options fo;
939
940 if (encoding == NULL || *encoding == '\0')
941 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "encoding", 0, 0, 0);
942
943 /* initialize */
944 pdf_init_font_options(p, &fo);
945
946 /* Converting fontname */
947 fo.fontname = (char *) pdf_convert_name(p, fontname, len,
948 PDC_CONV_WITHBOM);
949 if (fo.fontname == NULL || *fo.fontname == '\0')
950 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
951
952 /* encoding */
953 fo.encoding = (char *) pdc_strdup(p->pdc, encoding);
954
955 /* parsing option list */
956 if (optlist && strlen(optlist))
957 {
958 pdc_resopt *resopts;
959 pdc_clientdata data;
960
961 pdf_set_clientdata(p, &data);
962 resopts = pdc_parse_optionlist(p->pdc, optlist,
963 pdf_load_font_options, &data, pdc_true);
964 if (!resopts)
965 {
966 pdf_cleanup_font_options(p, &fo);
967 return -1;
968 }
969
970 pdf_get_font_options(p, &fo, resopts);
971 pdc_cleanup_optionlist(p->pdc, resopts);
972 }
973
974 slot = pdf_load_font_internal(p, &fo);
975 return slot;
976 }
977
978 static void
pdf_check_font_identical(PDF * p,pdf_font * font,int * slot)979 pdf_check_font_identical(PDF *p, pdf_font *font, int *slot)
980 {
981 pdf_font *oldfont = &p->fonts[*slot];
982 const char *optname = NULL;
983
984 if (!oldfont->opt.embedding && font->opt.embedding)
985 {
986 optname = "embedding";
987 if (p->errorpolicy == errpol_legacy)
988 {
989 pdc_warning(p->pdc, PDF_E_FONT_NOTFULFILL, optname, optname,
990 0, 0);
991 }
992 else
993 {
994 pdc_set_errmsg(p->pdc, PDF_E_FONT_NOTFULFILL, optname, optname,
995 0, 0);
996 *slot = -1;
997 }
998 }
999
1000 }
1001
1002 pdc_bool
pdf_check_font_embedding(PDF * p,pdf_font * font,const char * fontname)1003 pdf_check_font_embedding(PDF *p, pdf_font *font, const char *fontname)
1004 {
1005 (void) p;
1006 (void) font;
1007 (void) fontname;
1008
1009
1010
1011 return pdc_true;
1012 }
1013
1014 int
pdf_load_font_internal(PDF * p,pdf_font_options * fo)1015 pdf_load_font_internal(PDF *p, pdf_font_options *fo)
1016 {
1017 pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_font);
1018 pdc_bool logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_font);
1019 const char *fontname;
1020 const char *encoding;
1021 const char *encoding_aux;
1022 pdc_encoding enc = pdc_invalidenc;
1023 pdf_font tmpfont, *font;
1024 const char *filename = NULL;
1025 const char *extension = NULL;
1026 const char *outfilename = NULL;
1027 char *fontname_p = NULL;
1028 char testfilename[PDF_MAX_FONTNAME + 5];
1029 char *sf, *mmparam, mastername[PDF_MAX_FONTNAME + 1];
1030 char ittc;
1031 size_t len;
1032 pdc_bool retval = pdc_false;
1033 int slot = -1, i;
1034
1035 /* register and skip at sign '@' in font name */
1036 if (fo->fontname[0] == PDF_VERTICAL_SIGN ||
1037 (pdc_is_utf8_bytecode(fo->fontname) &&
1038 fo->fontname[3] == PDF_VERTICAL_SIGN))
1039 {
1040
1041 i = (fo->fontname[0] == PDF_VERTICAL_SIGN) ? 1 : 4;
1042 len = strlen(fo->fontname) + 1 - i;
1043 memmove(&fo->fontname[i - 1], &fo->fontname[i], len);
1044 }
1045
1046 /* host or UTF-8 encoded font name without BOM */
1047 fontname_p = pdc_utf8_to_hostbytes(p->pdc, pdc_false, fo->fontname);
1048 if (fontname_p == NULL)
1049 {
1050 fontname = pdc_utf8strprint(p->pdc, fo->fontname);
1051 }
1052 else
1053 {
1054 fontname = pdc_utf8strprint(p->pdc, fontname_p);
1055 pdc_free_tmp(p->pdc, fontname_p);
1056 }
1057 fontname_p = NULL;
1058
1059 if (logg1)
1060 pdc_logg(p->pdc, "\tCanonical font name: \"%s\"\n",
1061 fontname);
1062
1063 /* font encoding */
1064 encoding = fo->encoding;
1065 encoding_aux = encoding;
1066
1067 /* initialize font struct */
1068 font = &tmpfont;
1069 pdf_init_font(p, font, fo);
1070
1071 /* error message prefix */
1072 pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX, fontname, encoding, 0, 0);
1073
1074
1075
1076
1077 /* API font name */
1078 font->apiname = pdc_strdup(p->pdc, fontname);
1079
1080 /* UTF-8 font name with BOM */
1081 font->ft.utf8name = pdc_strdup(p->pdc, fo->fontname);
1082
1083 if (logg1)
1084 pdc_logg(p->pdc, "\tFont UTF-8 name: \"%s\"\n",
1085 font->ft.utf8name);
1086
1087 /* specified encoding name */
1088 font->encapiname = pdc_strdup(p->pdc, encoding);
1089
1090 /* search for a registered encoding */
1091 enc = pdc_find_encoding(p->pdc, encoding);
1092
1093 if (enc == pdc_unicode || enc == pdc_glyphid)
1094 {
1095 pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
1096 goto PDF_PREMATURE_EXIT;
1097 }
1098
1099 if (enc == pdc_invalidenc || enc == pdc_unicode)
1100 {
1101 /* search for a predefined CMap and registered fonts */
1102 if (!pdf_handle_cidfont(p, fontname, encoding, enc, font, &slot, &enc))
1103 goto PDF_PREMATURE_EXIT;
1104
1105 if (enc == pdc_invalidenc)
1106 {
1107 /* search for a new encoding */
1108 enc = pdc_insert_encoding(p->pdc, encoding, &font->codepage,
1109 font->verbose);
1110 if (enc == pdc_invalidenc)
1111 goto PDF_PREMATURE_EXIT;
1112 }
1113 else if (enc == pdc_cid)
1114 {
1115 if (slot == -1)
1116 goto PDF_NEWFONT_EXIT;
1117 else
1118 goto PDF_PREMATURE_EXIT;
1119 }
1120 else if (enc == pdc_glyphid)
1121 {
1122 encoding_aux = "glyphid";
1123 }
1124 else if (enc == pdc_unicode)
1125 {
1126 encoding_aux = "unicode";
1127 }
1128 }
1129
1130 if (pdc_strcmp(font->encapiname, encoding))
1131 {
1132 pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX2,
1133 fontname, font->encapiname, encoding, 0);
1134 }
1135 encoding = encoding_aux;
1136
1137 encoding = pdc_get_user_encoding(p->pdc, enc);
1138 pdc_logg_cond(p->pdc, 1, trc_encoding, "\tFont encoding: \"%s\"\n",
1139 encoding);
1140
1141 if (enc == pdc_unicode || enc == pdc_glyphid)
1142 {
1143 pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
1144 goto PDF_PREMATURE_EXIT;
1145 }
1146
1147 /*
1148 * Look whether font is already in the cache.
1149 * Look first for the auxiliary font (obj_id == -1).
1150 * If a font with same encoding and same relevant options is found,
1151 * return its handle.
1152 * If a Type 3 font with the same name but different encoding
1153 * is found, make a copy in a new slot and attach the requested encoding.
1154 */
1155
1156 if (logg1)
1157 pdc_logg(p->pdc, "\tFont will be searched in the PDFlib font cache\n");
1158 for (slot = 0; slot < p->fonts_number; slot++)
1159 {
1160 if (p->fonts[slot].obj_id == PDC_BAD_ID &&
1161 p->fonts[slot].ft.m.type != fnt_Type3)
1162 {
1163 if (font->opt.auxiliary)
1164 goto PDF_PREMATURE_EXIT;
1165 }
1166 else if (!font->opt.auxiliary &&
1167 !pdc_strcmp(p->fonts[slot].apiname, fontname) &&
1168 p->fonts[slot].opt.fontstyle == font->opt.fontstyle)
1169 {
1170 if (p->fonts[slot].ft.m.type == fnt_Type3)
1171 {
1172 if (logg2)
1173 pdc_logg(p->pdc, "\t\tType3 font [%d] found\n", slot);
1174
1175 if (enc < pdc_winansi && enc != pdc_unicode)
1176 {
1177 pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0);
1178
1179 slot = -1;
1180 goto PDF_PREMATURE_EXIT;
1181 }
1182
1183 if (p->fonts[slot].ft.enc != enc)
1184 {
1185 if (!pdf_handle_t3font(p, fontname, enc, font, &slot))
1186 {
1187 slot = -1;
1188 goto PDF_PREMATURE_EXIT;
1189 }
1190 if (slot > -1)
1191 font = &p->fonts[slot];
1192 goto PDF_NEWFONT_EXIT;
1193 }
1194
1195 goto PDF_PREMATURE_EXIT;
1196 }
1197 else if (p->fonts[slot].opt.monospace == font->opt.monospace
1198 )
1199 {
1200 if (p->fonts[slot].ft.enc == enc &&
1201 p->fonts[slot].codepage == font->codepage)
1202 {
1203 if (logg2)
1204 pdc_logg(p->pdc,
1205 "\t\tfont [%d] with same encoding found\n",
1206 slot);
1207
1208 pdf_check_font_identical(p, font, &slot);
1209 goto PDF_PREMATURE_EXIT;
1210 }
1211 else
1212 {
1213 char *adaptname;
1214 int kc;
1215
1216 /* Comparing apiname of encoding */
1217 if (!pdc_stricmp(font->encapiname,
1218 p->fonts[slot].encapiname) &&
1219 !pdc_stricmp(font->ft.cmapname,
1220 p->fonts[slot].ft.cmapname))
1221 {
1222 if (logg2)
1223 pdc_logg(p->pdc,
1224 "\t\tfont [%d] with same encoding "
1225 "apiname '%s' found\n", slot, encoding);
1226
1227 pdf_check_font_identical(p, font, &slot);
1228 goto PDF_PREMATURE_EXIT;
1229 }
1230
1231 /* Name of adapted to font encoding */
1232 adaptname =
1233 pdf_get_encoding_adaptname(p, enc, font, fontname);
1234 kc = strcmp(adaptname, pdf_get_encoding_name(p,
1235 p->fonts[slot].ft.enc, &p->fonts[slot]));
1236 if (!kc)
1237 {
1238 if (logg2)
1239 pdc_logg(p->pdc,
1240 "\t\tfont [%d] with same internal "
1241 "encoding name '%s' found\n",
1242 slot, adaptname);
1243 pdc_free_tmp(p->pdc, adaptname);
1244
1245 pdf_check_font_identical(p, font, &slot);
1246 goto PDF_PREMATURE_EXIT;
1247 }
1248 pdc_free_tmp(p->pdc, adaptname);
1249 }
1250 }
1251 }
1252 else if (!font->opt.auxiliary &&
1253 p->fonts[slot].ft.m.type == fnt_Type1 &&
1254 p->fonts[slot].ft.isstdfont && p->fonts[slot].ft.enc == enc)
1255 {
1256 /* different core font specifications */
1257 const char *fname = pdf_get_fontname_core(font, fontname, pdc_true);
1258
1259 if ((fname != NULL && !strcmp(fname, p->fonts[slot].ft.name) &&
1260 p->fonts[slot].opt.fontstyle == fnt_Normal) ||
1261 (!strcmp(fontname, p->fonts[slot].ft.name) &&
1262 p->fonts[slot].opt.fontstyle == font->opt.fontstyle))
1263 {
1264 if (logg2)
1265 pdc_logg(p->pdc,
1266 "\t\tfont [%d] with same font style '%s' found\n",
1267 slot, pdc_get_keyword(font->opt.fontstyle,
1268 pdf_fontstyle_pdfkeylist));
1269
1270 pdf_check_font_identical(p, font, &slot);
1271 goto PDF_PREMATURE_EXIT;
1272 }
1273 }
1274 }
1275
1276 slot = -1;
1277 if (logg1)
1278 pdc_logg(p->pdc, "\tFont not found in the PDFlib font cache\n");
1279
1280 /* embedding check */
1281 if (!pdf_check_font_embedding(p, font, fontname))
1282 {
1283 goto PDF_PREMATURE_EXIT;
1284 }
1285
1286 /* Multiple Master handling:
1287 * - strip MM parameters to build the master name
1288 * - the master name is used to find the metrics
1289 * - the instance name (client-supplied font name) is used in all places
1290 * - although the master name is used for finding the metrics, the
1291 * instance name is stored in the font struct.
1292 */
1293
1294 len = strlen(fontname);
1295 if (len > PDF_MAX_FONTNAME)
1296 {
1297 pdc_set_errmsg(p->pdc, FNT_E_FONT_NAMETOOLONG,
1298 pdc_errprintf(p->pdc, "%d", PDF_MAX_FONTNAME), 0, 0, 0);
1299 goto PDF_PREMATURE_EXIT;
1300 }
1301 strcpy(mastername, fontname);
1302
1303 /* A Multiple Master font was requested */
1304 if ((mmparam = strstr(mastername, "MM_")) != NULL)
1305 {
1306 if (font->opt.embedding)
1307 {
1308 pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDMM, 0, 0, 0, 0);
1309 goto PDF_PREMATURE_EXIT;
1310 }
1311 mmparam[2] = '\0'; /* strip the parameter from the master name */
1312 }
1313 fontname_p = mastername;
1314
1315 /* protocol */
1316 if (logg1)
1317 pdc_logg(p->pdc, "\tPDFlib font name: \"%s\"\n", fontname_p);
1318
1319 /* Font file search hierarchy
1320 * - Check "FontOutline" resource entry and check TrueType font
1321 * - Check "FontAFM" resource entry
1322 * - Check "FontPFM" resource entry
1323 * - Check "HostFont" resource entry
1324 * - Check available in-core metrics
1325 * - Check host font
1326 */
1327 retval = pdc_false;
1328 while (1)
1329 {
1330 if (font->opt.auxiliary)
1331 {
1332 /* only in-core fonts are possible */
1333 retval = pdf_get_metrics_core(p, font, fontname_p, "", enc,
1334 pdc_false);
1335 break;
1336 }
1337
1338 #ifdef PDF_TRUETYPE_SUPPORTED
1339 /* Check specified TrueType file */
1340 filename = pdc_find_resource(p->pdc, "FontOutline", fontname_p);
1341 if (!filename)
1342 {
1343 /* check for TTC font names with index */
1344 ittc = PDF_TTC_SEPARATOR;
1345 sf = strrchr(fontname_p, ittc);
1346
1347 if (sf != NULL)
1348 {
1349 *sf = 0;
1350 filename = pdc_find_resource(p->pdc, "FontOutline", fontname_p);
1351 *sf = ittc;
1352 }
1353 }
1354 if (filename)
1355 {
1356 outfilename = filename;
1357 retval = fnt_check_tt_font(p->pdc, filename, fontname_p, &font->ft,
1358 pdc_false);
1359 if (retval == pdc_true)
1360 {
1361 retval = pdf_get_metrics_tt(p, font, fontname_p, enc, filename);
1362 break;
1363 }
1364 else if (retval == pdc_undef &&
1365 pdc_get_errnum(p->pdc) == PDC_E_IO_RDOPEN_NF)
1366 {
1367 /* file must be exist */
1368 retval = pdc_false;
1369 }
1370 if (retval == pdc_false)
1371 break;
1372 }
1373 #endif /* PDF_TRUETYPE_SUPPORTED */
1374
1375 /* Check specified AFM file */
1376 filename = pdc_find_resource(p->pdc, "FontAFM", fontname_p);
1377 if (filename)
1378 {
1379 retval = pdf_get_metrics_afm(p, font, fontname_p, enc, filename,
1380 pdc_true);
1381 break;
1382 }
1383
1384 /* Check specified PFM file */
1385 filename = pdc_find_resource(p->pdc, "FontPFM", fontname_p);
1386 if (filename)
1387 {
1388 retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, filename,
1389 pdc_true);
1390 break;
1391 }
1392
1393
1394
1395 /* Check available in-core metrics - will be skipped
1396 * in the case of embedding and missing outline file
1397 * to check the possibility of an host font in the next step.
1398 */
1399 retval = pdf_get_metrics_core(p, font, fontname_p, outfilename, enc,
1400 pdc_false);
1401 if (retval != pdc_undef)
1402 break;
1403 retval = pdc_false;
1404
1405
1406 /* Check available in-core metrics */
1407 retval = pdf_get_metrics_core(p, font, fontname_p, "", enc, pdc_true);
1408 if (retval != pdc_undef)
1409 break;
1410 retval = pdc_false;
1411
1412 /* Searching for a metric file */
1413 if (logg1)
1414 pdc_logg(p->pdc, "\tSearching for font metrics data file:\n");
1415
1416 filename = testfilename;
1417 for (i = 0; i < 100; i++)
1418 {
1419 extension = pdf_extension_names[i].word;
1420 if (!extension)
1421 break;
1422
1423 strcpy(testfilename, fontname_p);
1424 sf = strrchr(testfilename, PDF_TTC_SEPARATOR);
1425 if (sf != NULL)
1426 *sf = 0;
1427 strcat(testfilename, extension);
1428
1429 switch (pdf_extension_names[i].code)
1430 {
1431 #ifdef PDF_TRUETYPE_SUPPORTED
1432 case font_ttot:
1433 retval = fnt_check_tt_font(p->pdc, filename, fontname_p,
1434 &font->ft, pdc_false);
1435 if (retval == pdc_true)
1436 retval = pdf_get_metrics_tt(p, font, fontname_p, enc,
1437 filename);
1438 break;
1439 #endif /* PDF_TRUETYPE_SUPPORTED */
1440
1441 case font_afm:
1442 retval = pdf_get_metrics_afm(p, font, fontname_p, enc,
1443 filename, pdc_false);
1444 break;
1445
1446 case font_pfm:
1447 retval = pdf_get_metrics_pfm(p, font, fontname_p, enc,
1448 filename, pdc_false);
1449 break;
1450
1451 default:
1452 break;
1453 }
1454
1455 /* file found or error */
1456 if (retval != pdc_undef)
1457 {
1458 if (retval == pdc_true)
1459 if (pdf_extension_names[i].code == font_ttot)
1460 outfilename = filename;
1461 break;
1462 }
1463 }
1464
1465 if (retval == pdc_undef)
1466 {
1467 retval = pdc_false;
1468
1469 if (logg1)
1470 pdc_logg(p->pdc,
1471 "\tMetric data file for font \"%s\" not available\n",
1472 fontname_p);
1473 pdc_set_errmsg(p->pdc, PDF_E_FONT_NOMETRICS, 0, 0, 0, 0);
1474 }
1475
1476 break;
1477 }
1478
1479 /* metrics data search finished */
1480
1481 if (retval == pdc_false)
1482 {
1483 goto PDF_PREMATURE_EXIT;
1484 }
1485
1486 /* store instance name instead of master name in the font structure */
1487 if (mmparam)
1488 {
1489 pdc_free(p->pdc, font->ft.name);
1490 font->ft.name = pdc_strdup(p->pdc, fontname);
1491 pdc_free(p->pdc, font->ft.m.name);
1492 font->ft.m.name = pdc_strdup(p->pdc, fontname);
1493 }
1494
1495 /* If embedding was requested, check font file (or raise an exception) */
1496 if (font->opt.embedding)
1497 {
1498 if (font->ft.img == NULL)
1499 {
1500 retval = pdc_undef;
1501
1502 if (outfilename)
1503 {
1504 /* Font outline file specified */
1505 if (font->ft.m.type == fnt_Type1 ||
1506 font->ft.m.type == fnt_MMType1)
1507 {
1508 retval = pdf_t1open_fontfile(p, font, outfilename, NULL,
1509 pdc_true);
1510 }
1511 else
1512 {
1513 retval = fnt_check_tt_font(p->pdc, outfilename, NULL,
1514 &font->ft, pdc_true);
1515 }
1516 }
1517 else
1518 {
1519 /* Searching font outline file */
1520 if (logg1)
1521 pdc_logg(p->pdc,
1522 "\tSearching for font outline data file:\n");
1523
1524 outfilename = testfilename;
1525 for (i = 0; i < 100; i++)
1526 {
1527 extension = pdf_extension_names[i].word;
1528 if (!extension)
1529 break;
1530
1531 strcpy(testfilename, fontname_p);
1532 strcat(testfilename, extension);
1533
1534 if (font->ft.m.type == fnt_Type1 ||
1535 font->ft.m.type == fnt_MMType1)
1536 {
1537 if (pdf_extension_names[i].code == font_pfab)
1538 {
1539 retval = pdf_t1open_fontfile(p, font, outfilename,
1540 NULL, pdc_false);
1541 }
1542 }
1543 else if (pdf_extension_names[i].code == font_ttot)
1544 {
1545 retval = fnt_check_tt_font(p->pdc, outfilename,
1546 NULL, &font->ft, pdc_false);
1547 }
1548
1549 /* file found or error */
1550 if (retval != pdc_undef)
1551 break;
1552 }
1553
1554 if (retval == pdc_undef)
1555 {
1556 retval = pdc_false;
1557 if (font->ft.m.type == fnt_Type1 ||
1558 font->ft.m.type == fnt_MMType1)
1559 pdc_set_errmsg(p->pdc, PDF_E_FONT_NOOUTLINE_PS,
1560 0, 0, 0, 0);
1561 else
1562 pdc_set_errmsg(p->pdc, PDF_E_FONT_NOOUTLINE_TT,
1563 0, 0, 0, 0);
1564 }
1565 }
1566
1567 if (retval == pdc_false)
1568 {
1569 if (logg1)
1570 pdc_logg(p->pdc,
1571 "\tOutline data file for font \"%s\" not found\n",
1572 fontname_p);
1573 }
1574 else
1575 {
1576 if (!font->ft.img)
1577 font->filename = font->ft.filename;
1578
1579 if (logg1)
1580 pdc_logg(p->pdc,
1581 "\tFont outline data file \"%s\" available\n",
1582 font->filename ?
1583 font->filename : font->ft.imgname);
1584 }
1585 }
1586 }
1587 else if (font->ft.img)
1588 {
1589 if (!font->ft.imgname)
1590 pdc_free(p->pdc, font->ft.img);
1591 else
1592 {
1593 pdc_unlock_pvf(p->pdc, font->ft.imgname);
1594 pdc_free(p->pdc, font->ft.imgname);
1595 font->ft.imgname = NULL;
1596 }
1597 font->ft.img = NULL;
1598 font->ft.filelen = 0;
1599 }
1600
1601 if (retval && font->opt.monospace && font->opt.embedding)
1602 {
1603 pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0);
1604 retval = pdc_false;
1605 }
1606
1607 if (retval == pdc_false)
1608 {
1609 goto PDF_PREMATURE_EXIT;
1610 }
1611
1612 PDF_NEWFONT_EXIT:
1613
1614 pdf_cleanup_font_options(p, fo);
1615
1616 encoding = pdc_get_user_encoding(p->pdc, font->ft.enc);
1617 if (pdc_strcmp(font->encapiname, encoding))
1618 pdc_logg_cond(p->pdc, 1, trc_encoding,
1619 "\tDetermined font encoding: \"%s\"\n", encoding);
1620
1621 /* set missing font metrics values */
1622 pdf_font_set_missvalues(p, font);
1623
1624 /* font is semantic (Unicode compatible) */
1625 pdf_font_issemantic(p, font);
1626
1627 /* set replacement character and code */
1628 pdf_set_replchar(p, font);
1629
1630 /* font object ID */
1631 if (!font->opt.auxiliary)
1632 font->obj_id = pdc_alloc_id(p->out);
1633
1634 /* Now everything is fine, insert font */
1635 if (slot == -1)
1636 slot = pdf_insert_font(p, font);
1637
1638
1639 pdc_pop_errmsg(p->pdc);
1640
1641 return slot;
1642
1643
1644 PDF_PREMATURE_EXIT:
1645
1646 pdf_cleanup_font_options(p, fo);
1647 pdf_cleanup_font(p, font);
1648
1649 if (slot == -1)
1650 {
1651 if (font->verbose)
1652 pdc_error(p->pdc, -1, 0, 0, 0, 0);
1653 }
1654
1655 pdc_pop_errmsg(p->pdc);
1656
1657 return slot;
1658 }
1659
1660
1661 /* --------------------------- font writing ---------------------------- */
1662
1663 static char *
pdf_code2fontglyphname(pdf_font * font,pdc_encodingvector * ev,int code)1664 pdf_code2fontglyphname(pdf_font *font, pdc_encodingvector *ev, int code)
1665 {
1666 char *glyphname;
1667
1668 glyphname = ev->chars[code];
1669 pdc_get_alter_glyphname(ev->codes[code], font->missingglyphs,
1670 &glyphname);
1671
1672 return glyphname ? glyphname : (char *) pdc_get_notdef_glyphname();
1673 }
1674
1675 void
pdf_transform_fontwidths(PDF * p,pdf_font * font,pdc_encodingvector * evto,pdc_encodingvector * evfrom)1676 pdf_transform_fontwidths(PDF *p, pdf_font *font, pdc_encodingvector *evto,
1677 pdc_encodingvector *evfrom)
1678 {
1679 int widths[256];
1680 pdc_ushort code2gid[256];
1681 int i, j;
1682
1683 for (i = 0; i < 256; i++)
1684 {
1685 widths[i] = font->ft.m.defwidth;
1686 code2gid[i] = 0;
1687 }
1688
1689 for (i = 0; i < 256; i++)
1690 {
1691 j = (int) pdc_transform_bytecode(p->pdc, evto, evfrom, (pdc_byte)i);
1692 widths[j] = font->ft.m.widths[i];
1693 if (font->ft.code2gid != NULL)
1694 code2gid[j] = font->ft.code2gid[i];
1695 }
1696
1697 widths[0] = font->ft.m.defwidth;
1698 memcpy(font->ft.m.widths, widths, 256 * sizeof(int));
1699 if (font->ft.code2gid != NULL)
1700 memcpy(font->ft.code2gid, code2gid, 256 * sizeof(pdc_ushort));
1701 }
1702
1703 void
pdf_prepare_fontwidths(PDF * p,pdf_font * font,int nusedgids)1704 pdf_prepare_fontwidths(PDF *p, pdf_font *font, int nusedgids)
1705 {
1706
1707 (void) p;
1708 (void) nusedgids;
1709
1710 if (font->towinansi != pdc_invalidenc || font->widths != NULL ||
1711 (font->iscidfont && (font->ft.isstdfont || font->opt.monospace)))
1712 {
1713 return;
1714 }
1715
1716 /* exchange widths pointer */
1717 if (!font->iscidfont && font->ft.enc != pdc_unicode)
1718 {
1719 font->widths = font->ft.m.widths;
1720 font->numwidths = font->ft.m.numwidths;
1721 font->ft.m.widths = NULL;
1722 font->ft.m.numwidths = 0;
1723 return;
1724 }
1725
1726 /* already defined or no basic data */
1727 if (font->ft.m.widths == NULL && font->ft.m.ciw == NULL
1728 )
1729 {
1730 return;
1731 }
1732
1733 }
1734
1735
1736
1737 static void
pdf_write_fontdescriptor(PDF * p,pdf_font * font,int missingwidth,pdc_id fontdescriptor_id,pdc_id cidset_id,pdc_id fontfile_id,int nusedgids)1738 pdf_write_fontdescriptor(
1739 PDF *p,
1740 pdf_font *font,
1741 int missingwidth,
1742 pdc_id fontdescriptor_id,
1743 pdc_id cidset_id,
1744 pdc_id fontfile_id,
1745 int nusedgids)
1746 {
1747 (void) cidset_id;
1748 (void) nusedgids;
1749
1750 /*
1751 * Font descriptor object
1752 */
1753 pdc_begin_obj(p->out, fontdescriptor_id); /* font descriptor obj */
1754 pdc_begin_dict(p->out); /* font descriptor dict */
1755
1756 pdc_puts(p->out, "/Type/FontDescriptor\n");
1757 pdc_printf(p->out, "/Flags %ld\n", font->ft.m.flags);
1758
1759
1760 pdc_printf(p->out, "/Ascent %d\n", font->ft.m.ascender);
1761 pdc_printf(p->out, "/CapHeight %d\n", font->ft.m.capHeight);
1762 pdc_printf(p->out, "/Descent %d\n", font->ft.m.descender);
1763
1764 if (font->ft.m.type != fnt_Type3)
1765 pdc_printf(p->out, "/FontBBox[%d %d %d %d]\n",
1766 (int) font->ft.m.llx, (int) font->ft.m.lly,
1767 (int) font->ft.m.urx, (int) font->ft.m.ury);
1768
1769 pdc_printf(p->out, "/FontName");
1770 pdf_put_pdfname(p, font->ft.m.name);
1771 pdc_puts(p->out, "\n");
1772
1773 pdc_printf(p->out, "/ItalicAngle %d\n", (int) (font->ft.m.italicAngle));
1774
1775 if (font->ft.m.type != fnt_Type3)
1776 pdc_printf(p->out, "/StemV %d\n", font->ft.m.StdVW);
1777
1778 if (font->ft.m.StdHW > 0)
1779 pdc_printf(p->out, "/StemH %d\n", font->ft.m.StdHW);
1780
1781 if (font->ft.m.xHeight > 0)
1782 pdc_printf(p->out, "/XHeight %d\n", font->ft.m.xHeight);
1783
1784 if (missingwidth > 0)
1785 pdc_printf(p->out, "/MissingWidth %d\n", missingwidth);
1786
1787 if (fontfile_id != PDC_BAD_ID)
1788 {
1789 switch(font->ft.m.type)
1790 {
1791 case fnt_Type1:
1792 case fnt_MMType1:
1793 pdc_objref(p->out, "/FontFile", fontfile_id);
1794 break;
1795
1796 #ifdef PDF_TRUETYPE_SUPPORTED
1797 case fnt_TrueType:
1798 case fnt_CIDFontType2:
1799 pdc_objref(p->out, "/FontFile2", fontfile_id);
1800 break;
1801
1802 case fnt_Type1C:
1803 case fnt_CIDFontType0:
1804 pdc_objref(p->out, "/FontFile3", fontfile_id);
1805 break;
1806 #endif /* PDF_TRUETYPE_SUPPORTED */
1807
1808 default:
1809 break;
1810 }
1811 }
1812
1813
1814 pdc_end_dict(p->out); /* font descriptor dict */
1815 pdc_end_obj(p->out); /* font descriptor obj */
1816 }
1817
1818 static void
pdf_put_font(PDF * p,pdf_font * font)1819 pdf_put_font(PDF *p, pdf_font *font)
1820 {
1821 const char *fontname = font->ft.name;
1822 fnt_fonttype fonttype = font->ft.m.type;
1823 pdc_id fontdescriptor_id = PDC_BAD_ID;
1824 pdc_id fontfile_id = PDC_BAD_ID;
1825 pdc_id encoding_id = PDC_BAD_ID;
1826 pdc_id cidset_id = PDC_BAD_ID;
1827 pdc_id length_id = PDC_BAD_ID;
1828 pdc_id descendant_id = PDC_BAD_ID;
1829 pdc_encoding enc = font->ft.enc;
1830 const char *encoding;
1831 pdc_encoding_info *encinfo = NULL;
1832 pdc_bool comp_font = pdc_false;
1833 pdc_bool acro_fontstyle = pdc_false;
1834 pdc_scalar a = 1.0;
1835 PDF_data_source src;
1836 int nusedgids = 0;
1837
1838 /* save font struct members */
1839 pdc_encodingvector *ev = NULL;
1840 pdc_encoding font_encoding = font->ft.enc;
1841 pdc_encoding font_towinansi = font->towinansi;
1842 int font_numcodes = font->ft.numcodes;
1843 int font_codesize = font->codesize;
1844
1845 int missingwidth = 0;
1846 int i;
1847
1848 encoding = pdc_get_user_encoding(p->pdc, enc);
1849 if (!pdc_strcmp(font->encapiname, encoding))
1850 {
1851 pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX,
1852 font->apiname, font->encapiname, 0, 0);
1853 }
1854 else
1855 {
1856 pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX2,
1857 font->apiname, font->encapiname, encoding, 0);
1858 }
1859
1860
1861 /* ID for embedded font */
1862 if (font->opt.embedding)
1863 {
1864 switch(fonttype)
1865 {
1866 case fnt_Type1:
1867 case fnt_MMType1:
1868 case fnt_TrueType:
1869 case fnt_CIDFontType2:
1870 case fnt_Type1C:
1871 case fnt_CIDFontType0:
1872 fontfile_id = pdc_alloc_id(p->out);
1873 break;
1874
1875 default:
1876 break;
1877 }
1878 }
1879
1880 /*
1881 * Font dictionary
1882 */
1883 pdc_begin_obj(p->out, font->obj_id); /* font obj */
1884 pdc_begin_dict(p->out); /* font dict */
1885 pdc_puts(p->out, "/Type/Font\n");
1886
1887 /* /Subtype */
1888 pdc_printf(p->out, "/Subtype/%s\n",
1889 pdc_get_keyword(fonttype, pdf_fonttype_pdfkeylist));
1890 comp_font = fonttype == fnt_CIDFontType0 || fonttype == fnt_CIDFontType2;
1891
1892 /* Acrobat font style */
1893 acro_fontstyle = font->opt.fontstyle != fnt_Normal &&
1894 !(font->metricflags & (font_bold | font_italic));
1895
1896 /* /Name */
1897 if (fonttype == fnt_Type3 || font->used_in_formfield)
1898 {
1899 /*
1900 * The name is optional, but if we include it it will show up
1901 * in Acrobat's font info box. However, if the same font name
1902 * is used with different encodings Acrobat 4 will not be
1903 * able to distinguish both. For this reason we add the
1904 * encoding name to make the font name unique.
1905 */
1906
1907 const char *name = fontname;
1908
1909 if (font->used_in_formfield)
1910 name = pdf_get_pdf_fontname(font);
1911
1912 pdc_puts(p->out, "/Name");
1913 pdf_put_pdfname(p, name);
1914 pdc_puts(p->out, "\n");
1915 }
1916
1917 /* /BaseFont */
1918 switch (fonttype)
1919 {
1920 case fnt_Type1:
1921 case fnt_MMType1:
1922 case fnt_TrueType:
1923 case fnt_Type1C:
1924 case fnt_CIDFontType2:
1925 case fnt_CIDFontType0:
1926 {
1927 pdc_puts(p->out, "/BaseFont");
1928 pdf_put_pdfname(p, fontname);
1929 if (font->outcmapname)
1930 pdc_printf(p->out, "-%s", font->outcmapname);
1931 if (acro_fontstyle && !comp_font)
1932 pdc_printf(p->out, ",%s", pdc_get_keyword(font->opt.fontstyle,
1933 pdf_fontstyle_pdfkeylist));
1934 pdc_puts(p->out, "\n");
1935 }
1936 break;
1937
1938 /* /FontBBox, /FontMatrix, /CharProcs /Resources */
1939 case fnt_Type3:
1940 if (font->t3font->charprocs_id == PDC_BAD_ID)
1941 pdc_error(p->pdc, PDF_E_T3_OUTLINESMISSING, fontname, 0, 0, 0);
1942
1943 pdc_printf(p->out, "/FontBBox[%f %f %f %f]\n",
1944 font->ft.bbox.llx, font->ft.bbox.lly,
1945 font->ft.bbox.urx, font->ft.bbox.ury);
1946
1947 pdc_printf(p->out, "/FontMatrix[%f %f %f %f %f %f]\n",
1948 font->ft.matrix.a, font->ft.matrix.b,
1949 font->ft.matrix.c, font->ft.matrix.d,
1950 font->ft.matrix.e, font->ft.matrix.f);
1951 pdc_objref(p->out, "/CharProcs", font->t3font->charprocs_id);
1952 pdc_objref(p->out, "/Resources", font->t3font->res_id);
1953
1954 /* We must apply a correctional factor since Type 3 fonts not
1955 * necessarily use 1000 units per em. We apply the correction
1956 * here, and store the 1000-based width values in the font in
1957 * order to speed up PDF_stringwidth().
1958 */
1959 a = 1000 * font->ft.matrix.a;
1960 break;
1961
1962 default:
1963 break;
1964 }
1965
1966 /* changing 8-bit font encoding to builtin */
1967 if (enc >= 0 && font->symenc != pdc_invalidenc)
1968 {
1969 ev = NULL;
1970 enc = pdc_builtin;
1971 font->ft.enc = enc;
1972 }
1973
1974 /* changing 8-bit font encoding to winansi */
1975 if (font->towinansi != pdc_invalidenc)
1976 {
1977 pdc_encodingvector *evfrom;
1978
1979 ev = pdc_get_encoding_vector(p->pdc, font->towinansi);
1980 evfrom = pdc_get_encoding_vector(p->pdc, enc);
1981 pdf_transform_fontwidths(p, font, ev, evfrom);
1982
1983 enc = font->towinansi;
1984 font->ft.enc = enc;
1985 font->towinansi = pdc_invalidenc;
1986 }
1987
1988 /* preparation for font widths array */
1989 pdf_prepare_fontwidths(p, font, nusedgids);
1990
1991 /* /FontDescriptor, /FirstChar, /LastChar, /Widths */
1992 switch (fonttype)
1993 {
1994 case fnt_Type1:
1995 /* disabled, because of PDF 1.7 reference
1996 if (font->ft.isstdfont == pdc_true) break;
1997 */
1998 case fnt_MMType1:
1999 case fnt_TrueType:
2000 case fnt_Type1C:
2001 case fnt_Type3:
2002 {
2003 int firstchar = 0;
2004 int lastchar = 255;
2005 int defwidth = 0;
2006
2007 if (fonttype != fnt_Type3
2008 )
2009 {
2010 fontdescriptor_id = pdc_alloc_id(p->out);
2011 pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id);
2012
2013 /* bug #1036 */
2014 if (font->ft.isstdfont == pdc_true && font->opt.dropcorewidths)
2015 break;
2016 }
2017
2018 /* determine missing width.
2019 * Only for embedded fonts because of a bug in Acrobat,
2020 * which arises if the font is not installed at host.
2021 */
2022 if (font->opt.embedding && !font->used_in_formfield)
2023 {
2024 if (fonttype != fnt_Type3)
2025 defwidth = font->widths[0];
2026
2027 {
2028 for (i = 1; i < 255; i++)
2029 {
2030 if (font->widths[i] != defwidth)
2031 break;
2032 }
2033 if (i > 1)
2034 firstchar = i;
2035 for (i = 255; i > 0; i--)
2036 {
2037 if (i == firstchar || font->widths[i] != defwidth)
2038 break;
2039 }
2040 lastchar = i;
2041 }
2042
2043 if (firstchar > 0 || lastchar < 255)
2044 missingwidth = (int) (defwidth / a + 0.5);
2045 }
2046
2047 pdc_printf(p->out, "/FirstChar %d\n", firstchar);
2048 pdc_printf(p->out, "/LastChar %d\n", lastchar);
2049
2050 pdc_puts(p->out, "/Widths");
2051 pdc_begin_array(p->out);
2052 for (i = firstchar; i <= lastchar; i++)
2053 {
2054 pdc_printf(p->out, "%d",
2055 (int) (font->widths[i] / a + .5));
2056 if (i < 255)
2057 pdc_printf(p->out, "%s", ((i + 1) % 16) ? " " : "\n");
2058 }
2059 pdc_end_array(p->out);
2060 }
2061 break;
2062
2063 default:
2064 break;
2065 }
2066
2067 /* /Encoding */
2068 switch (fonttype)
2069 {
2070 case fnt_Type1:
2071 case fnt_MMType1:
2072 case fnt_TrueType:
2073 case fnt_Type1C:
2074 if (!font->used_in_formfield)
2075 {
2076 if (enc == pdc_winansi)
2077 {
2078 pdc_printf(p->out, "/Encoding/WinAnsiEncoding\n");
2079 break;
2080 }
2081 if (enc == pdc_macroman && font->hasnomac == pdc_false)
2082 {
2083 pdc_printf(p->out, "/Encoding/MacRomanEncoding\n");
2084 break;
2085 }
2086 }
2087 case fnt_Type3:
2088 if (enc >= 0)
2089 {
2090 encinfo = pdc_get_encoding_info(p->pdc, enc);
2091 if (encinfo->id == PDC_BAD_ID)
2092 encinfo->id = pdc_alloc_id(p->out);
2093 encoding_id = encinfo->id;
2094 }
2095
2096 if (encoding_id != PDC_BAD_ID)
2097 pdc_objref(p->out, "/Encoding", encoding_id);
2098
2099 if (encinfo != NULL)
2100 {
2101 if (!encinfo->stored)
2102 encinfo->stored = pdc_true;
2103 else
2104 encoding_id = PDC_BAD_ID;
2105 }
2106
2107 break;
2108
2109 case fnt_CIDFontType2:
2110 case fnt_CIDFontType0:
2111 if (font->outcmapname)
2112 {
2113 pdc_printf(p->out, "/Encoding/%s\n", font->outcmapname);
2114 }
2115 break;
2116
2117 default:
2118 break;
2119 }
2120
2121 /* /ToUnicode . Only reasonable if nusedgids != 1
2122 * (== 1: only notdef character in a font subset)
2123 */
2124
2125
2126 /* /DescendantFonts */
2127 if (comp_font == pdc_true)
2128 {
2129 descendant_id = pdc_alloc_id(p->out);
2130 pdc_puts(p->out, "/DescendantFonts");
2131 pdc_begin_array(p->out);
2132 pdc_objref(p->out, "", descendant_id);
2133 pdc_end_array(p->out);
2134 }
2135
2136 pdc_end_dict(p->out); /* font dict */
2137 pdc_end_obj(p->out); /* font obj */
2138
2139 /*
2140 * Encoding dictionary
2141 */
2142 if (encoding_id != PDC_BAD_ID)
2143 {
2144 char *glyphname;
2145
2146 pdc_begin_obj(p->out, encoding_id); /* encoding obj */
2147 pdc_begin_dict(p->out); /* encoding dict */
2148
2149 pdc_puts(p->out, "/Type/Encoding\n");
2150
2151 {
2152 pdc_encodingvector *evb = NULL;
2153
2154 pdc_set_encoding_glyphnames(p->pdc, enc);
2155 ev = pdc_get_encoding_vector(p->pdc, enc);
2156
2157 /* See Implementation Note 46. The restrictions described there
2158 * are also valid for Acrobat versions up to now.
2159 */
2160 if (fonttype != fnt_Type3 && !font->used_in_formfield)
2161 {
2162 if (!strncmp(ev->apiname, PDC_ENC_MODWINANSI,
2163 strlen(PDC_ENC_MODWINANSI)) ||
2164 !strncmp(ev->apiname, PDC_ENC_ISO8859,
2165 strlen(PDC_ENC_ISO8859)) ||
2166 !strncmp(ev->apiname, PDC_ENC_CP125,
2167 strlen(PDC_ENC_CP125)))
2168 {
2169 pdc_puts(p->out, "/BaseEncoding/WinAnsiEncoding\n");
2170 evb = pdc_get_encoding_vector(p->pdc, pdc_winansi);
2171 }
2172 else if (!strncmp(ev->apiname, PDC_ENC_MODMACROMAN,
2173 strlen(PDC_ENC_MODMACROMAN)))
2174 {
2175 pdc_puts(p->out, "/BaseEncoding/MacRomanEncoding\n");
2176 evb = pdc_get_encoding_vector(p->pdc, pdc_macroman);
2177 }
2178 else
2179 {
2180 /* /BaseEncoding/StandardEncoding */
2181 evb = pdc_get_encoding_vector(p->pdc, pdc_stdenc);
2182 }
2183 }
2184
2185 if (evb != NULL)
2186 {
2187 int iv = -1;
2188 for (i = 0; i < font->ft.numcodes; i++)
2189 {
2190 glyphname = pdf_code2fontglyphname(font, ev, i);
2191
2192 /* enforce first three names because of bug in Acrobat 6 */
2193 if (i < 3 ||
2194 (glyphname && !evb->chars[i]) ||
2195 (!glyphname && evb->chars[i]) ||
2196 (glyphname && evb->chars[i] &&
2197 strcmp(glyphname, evb->chars[i])))
2198 {
2199 if (iv == -1)
2200 pdc_puts(p->out, "/Differences[0");
2201 if (i > iv + 1)
2202 pdc_printf(p->out, "%d", i);
2203 pdf_put_pdfname(p, glyphname);
2204 pdc_puts(p->out, "\n");
2205 iv = i;
2206 }
2207 }
2208 if (iv > -1)
2209 pdc_end_array(p->out);
2210 }
2211 else
2212 {
2213 pdc_puts(p->out, "/Differences[0");
2214 for (i = 0; i < font->ft.numcodes; i++)
2215 {
2216 glyphname = pdf_code2fontglyphname(font, ev, i);
2217 pdf_put_pdfname(p, glyphname);
2218 pdc_puts(p->out, "\n");
2219 }
2220 pdc_end_array(p->out);
2221 }
2222 }
2223
2224 pdc_end_dict(p->out); /* encoding dict */
2225 pdc_end_obj(p->out); /* encoding obj */
2226
2227 if (p->flush & pdc_flush_content)
2228 pdc_flush_stream(p->out);
2229 }
2230
2231
2232 /*
2233 * CID fonts dictionary
2234 */
2235 if (descendant_id != PDC_BAD_ID)
2236 {
2237 pdc_begin_obj(p->out, descendant_id); /* CID font obj */
2238 pdc_begin_dict(p->out); /* CID font dict */
2239 pdc_puts(p->out, "/Type/Font\n");
2240
2241 /* /Subtype */
2242 if (fonttype == fnt_CIDFontType0)
2243 pdc_puts(p->out, "/Subtype/CIDFontType0\n");
2244 if (fonttype == fnt_CIDFontType2)
2245 pdc_puts(p->out, "/Subtype/CIDFontType2\n");
2246
2247 /* /BaseFont */
2248 pdc_puts(p->out, "/BaseFont");
2249 pdf_put_pdfname(p, fontname);
2250 if (acro_fontstyle)
2251 pdc_printf(p->out, ",%s",
2252 pdc_get_keyword(font->opt.fontstyle, pdf_fontstyle_pdfkeylist));
2253 pdc_puts(p->out, "\n");
2254
2255 /* /CIDSystemInfo */
2256 pdc_puts(p->out, "/CIDSystemInfo<</Registry");
2257 pdf_put_hypertext(p, "Adobe");
2258 pdc_puts(p->out, "/Ordering");
2259 pdf_put_hypertext(p, fnt_get_ordering_cid(font->ft.m.charcoll));
2260 pdc_printf(p->out, "/Supplement %d>>\n", MAX(font->supplement, 0));
2261
2262 /* /FontDescriptor */
2263 fontdescriptor_id = pdc_alloc_id(p->out);
2264 pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id);
2265
2266
2267
2268 /* /DW /W */
2269 #ifdef PDF_CJKFONTWIDTHS_SUPPORTED
2270 if (font->ft.isstdfont)
2271 pdf_put_cidglyph_widths(p, font);
2272 #endif /* PDF_CJKFONTWIDTHS_SUPPORTED */
2273
2274
2275 pdc_end_dict(p->out); /* CID font dict */
2276 pdc_end_obj(p->out); /* CID font obj */
2277
2278 }
2279
2280
2281 /*
2282 * FontDescriptor dictionary
2283 */
2284 if (fontdescriptor_id != PDC_BAD_ID)
2285 pdf_write_fontdescriptor(p, font, missingwidth, fontdescriptor_id,
2286 cidset_id, fontfile_id, nusedgids);
2287
2288
2289
2290 /*
2291 * Font embedding
2292 */
2293 if (fontfile_id != PDC_BAD_ID)
2294 {
2295 pdc_id length1_id = PDC_BAD_ID;
2296 pdc_id length2_id = PDC_BAD_ID;
2297 pdc_id length3_id = PDC_BAD_ID;
2298 pdc_bool compress = pdc_false;
2299
2300 /* Prepare embedding */
2301 switch(fonttype)
2302 {
2303 case fnt_Type1:
2304 case fnt_MMType1:
2305 {
2306 pdf_make_t1src(p, font, &src);
2307 length1_id = pdc_alloc_id(p->out);
2308 length2_id = pdc_alloc_id(p->out);
2309 length3_id = pdc_alloc_id(p->out);
2310 }
2311 break;
2312
2313 #ifdef PDF_TRUETYPE_SUPPORTED
2314 case fnt_TrueType:
2315 case fnt_CIDFontType2:
2316 {
2317 length1_id = pdc_alloc_id(p->out);
2318 }
2319 case fnt_Type1C:
2320 case fnt_CIDFontType0:
2321 case fnt_OpenType:
2322 {
2323 src.private_data = (void *) font->filename;
2324 if (font->filename)
2325 {
2326 /* Read the font from file */
2327 src.init = pdf_data_source_file_init;
2328 src.fill = pdf_data_source_file_fill;
2329 src.terminate = pdf_data_source_file_terminate;
2330 switch(fonttype)
2331 {
2332 case fnt_TrueType:
2333 case fnt_CIDFontType2:
2334 case fnt_OpenType:
2335 src.offset = (long) 0;
2336 src.length = (long) 0;
2337 break;
2338
2339 case fnt_Type1C:
2340 case fnt_CIDFontType0:
2341 src.offset = font->cff_offset;
2342 src.length = (long) font->cff_length;
2343 break;
2344
2345 default:
2346 break;
2347 }
2348 }
2349 else
2350 {
2351 /* Read the font from memory */
2352 src.init = NULL;
2353 src.fill = pdf_data_source_buf_fill;
2354 src.terminate = NULL;
2355 switch(fonttype)
2356 {
2357 case fnt_TrueType:
2358 case fnt_CIDFontType2:
2359 case fnt_OpenType:
2360 src.buffer_start = font->ft.img;
2361 src.buffer_length = font->ft.filelen;
2362 break;
2363
2364 case fnt_Type1C:
2365 case fnt_CIDFontType0:
2366 src.buffer_start = font->ft.img + font->cff_offset;
2367 src.buffer_length = font->cff_length;
2368 break;
2369
2370 default:
2371 break;
2372 }
2373 src.bytes_available = 0;
2374 src.next_byte = NULL;
2375 }
2376 }
2377 break;
2378 #endif /* PDF_TRUETYPE_SUPPORTED */
2379
2380 default:
2381 break;
2382 }
2383
2384 /* Embedded font stream dictionary */
2385 pdc_begin_obj(p->out, fontfile_id); /* Embedded font stream obj */
2386 pdc_begin_dict(p->out); /* Embedded font stream dict */
2387
2388 /* /Length, /Filter */
2389 length_id = pdc_alloc_id(p->out);
2390 pdc_objref(p->out, "/Length", length_id);
2391 switch(fonttype)
2392 {
2393 case fnt_Type1:
2394 case fnt_MMType1:
2395 break;
2396
2397 #ifdef PDF_TRUETYPE_SUPPORTED
2398 case fnt_TrueType:
2399 case fnt_CIDFontType2:
2400 case fnt_Type1C:
2401 case fnt_CIDFontType0:
2402 case fnt_OpenType:
2403 if (font->ft.filelen != 0L)
2404 {
2405 compress = pdc_true;
2406 if (pdc_get_compresslevel(p->out))
2407 pdc_puts(p->out, "/Filter/FlateDecode\n");
2408 }
2409 break;
2410 #endif /* PDF_TRUETYPE_SUPPORTED */
2411
2412 default:
2413 break;
2414 }
2415
2416 /* /Length1, /Length2, Length3 */
2417 if (length1_id != PDC_BAD_ID)
2418 pdc_objref(p->out, "/Length1", length1_id);
2419 if (length2_id != PDC_BAD_ID)
2420 pdc_objref(p->out, "/Length2", length2_id);
2421 if (length3_id != PDC_BAD_ID)
2422 pdc_objref(p->out, "/Length3", length3_id);
2423
2424 #ifdef PDF_TRUETYPE_SUPPORTED
2425 /* /Subtype */
2426 if(fonttype == fnt_Type1C)
2427 pdc_puts(p->out, "/Subtype/Type1C\n");
2428 if (fonttype == fnt_CIDFontType0)
2429 pdc_puts(p->out, "/Subtype/CIDFontType0C\n");
2430 if (fonttype == fnt_OpenType)
2431 pdc_puts(p->out, "/Subtype/OpenType\n");
2432 #endif /* PDF_TRUETYPE_SUPPORTED */
2433
2434
2435 pdc_end_dict(p->out); /* Embedded font stream dict */
2436
2437 /* Stream */
2438 pdf_copy_stream(p, &src, compress);
2439
2440 pdc_end_obj(p->out); /* Embedded font stream obj */
2441
2442 pdc_put_pdfstreamlength(p->out, length_id);
2443
2444 /* Length objects */
2445 switch(fonttype)
2446 {
2447 case fnt_Type1:
2448 case fnt_MMType1:
2449 pdf_put_length_objs(p, &src, length1_id, length2_id, length3_id);
2450 break;
2451
2452 #ifdef PDF_TRUETYPE_SUPPORTED
2453 case fnt_TrueType:
2454 case fnt_CIDFontType2:
2455 if (compress)
2456 {
2457 pdc_begin_obj(p->out, length1_id); /* Length1 obj */
2458 pdc_printf(p->out, "%ld\n", (long) font->ft.filelen);
2459 pdc_end_obj(p->out); /* Length1 obj */
2460 }
2461 else
2462 {
2463 /* same as /Length */
2464 pdc_put_pdfstreamlength(p->out, length1_id);
2465 }
2466 break;
2467 #endif /* PDF_TRUETYPE_SUPPORTED */
2468
2469 default:
2470 break;
2471 }
2472 }
2473
2474 if (p->flush & pdc_flush_content)
2475 pdc_flush_stream(p->out);
2476
2477 /* restore font struct members */
2478 font->ft.enc = font_encoding;
2479 font->towinansi = font_towinansi;
2480 font->ft.numcodes = font_numcodes;
2481 font->codesize = font_codesize;
2482
2483 pdc_pop_errmsg(p->pdc);
2484 }
2485
2486 void
pdf_write_doc_fonts(PDF * p)2487 pdf_write_doc_fonts(PDF *p)
2488 {
2489 int slot;
2490 pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_font);
2491
2492 /* output pending font objects */
2493 for (slot = 0; slot < p->fonts_number; slot++)
2494 {
2495 pdf_font *font = &p->fonts[slot];
2496
2497 switch(p->fonts[slot].ft.m.type)
2498 {
2499 case fnt_Type1:
2500 case fnt_MMType1:
2501 #ifdef PDF_TRUETYPE_SUPPORTED
2502 case fnt_TrueType:
2503 case fnt_CIDFontType2:
2504 case fnt_Type1C:
2505 #endif /* PDF_TRUETYPE_SUPPORTED */
2506 case fnt_CIDFontType0:
2507 case fnt_Type3:
2508 if (font->obj_id != PDC_BAD_ID)
2509 {
2510 if (logg1)
2511 {
2512 pdc_logg(p->pdc,
2513 "\tProcessing font %d: \"%s\" "
2514 "with encoding \"%s\" and PDF object id %ld",
2515 slot, font->ft.name,
2516 pdf_get_encoding_name(p, font->ft.enc, font),
2517 font->obj_id);
2518 }
2519
2520 if (font->ft.enc == pdc_invalidenc ||
2521 font->used_in_current_doc == pdc_false)
2522 {
2523 if (logg1)
2524 pdc_logg(p->pdc, " - but not used\n", font->obj_id);
2525
2526 /*
2527 * This font has been defined, but never used in the
2528 * document. Ignore it. However, the font's object id
2529 * has already been allocated, so we mark the object
2530 * as free in order to avoid a complaint of the object
2531 * machinery.
2532 */
2533 pdc_mark_free(p->out, font->obj_id);
2534 }
2535 else
2536 {
2537 if (logg1)
2538 pdc_logg(p->pdc, "\n");
2539
2540 pdf_put_font(p, font);
2541 }
2542 }
2543 break;
2544
2545 default:
2546 break;
2547 }
2548 }
2549 }
2550
2551 void
pdf_write_page_fonts(PDF * p)2552 pdf_write_page_fonts(PDF *p)
2553 {
2554 int i, total = 0;
2555
2556 /* This doesn't really belong here, but all modules which write
2557 * font resources also need this, so we include it here.
2558 * Note that keeping track of ProcSets is considered obsolete
2559 * starting with PDF 1.4, so we always include the full set which
2560 * is written as a constant object at the beginning of the file.
2561 */
2562
2563 pdc_objref(p->out, "/ProcSet", p->procset_id);
2564
2565 for (i = 0; i < p->fonts_number; i++)
2566 if (p->fonts[i].used_on_current_page == pdc_true)
2567 total++;
2568
2569 if (total > 0)
2570 {
2571 pdc_puts(p->out, "/Font");
2572 pdc_begin_dict(p->out); /* font resource dict */
2573 }
2574
2575 if (total > 0)
2576 {
2577 for (i = 0; i < p->fonts_number; i++)
2578 {
2579 if (p->fonts[i].used_on_current_page == pdc_true) {
2580 p->fonts[i].used_on_current_page = pdc_false; /* reset */
2581 pdc_printf(p->out, "/F%d", i);
2582 pdc_objref(p->out, "", p->fonts[i].obj_id);
2583 }
2584 }
2585
2586 pdc_end_dict(p->out); /* font resource dict */
2587 }
2588 }
2589
2590 void
pdf_get_page_fonts(PDF * p,pdf_reslist * rl)2591 pdf_get_page_fonts(PDF *p, pdf_reslist *rl)
2592 {
2593 int i;
2594
2595 for (i = 0; i < p->fonts_number; i++)
2596 {
2597 if (p->fonts[i].used_on_current_page)
2598 {
2599 p->fonts[i].used_on_current_page = pdc_false; /* reset */
2600 pdf_add_reslist(p, rl, i);
2601 }
2602 }
2603 }
2604
2605 void
pdf_mark_page_font(PDF * p,int ft)2606 pdf_mark_page_font(PDF *p, int ft)
2607 {
2608 p->fonts[ft].used_on_current_page = pdc_true;
2609 }
2610