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