1/*---------------------------------------------------------------------------*
2 |              PDFlib - A library for generating PDF on the fly             |
3 +---------------------------------------------------------------------------+
4 | Copyright (c) 1997-2004 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 14574 2005-10-29 16:27:43Z bonefish $
14 *
15 * PDFlib font handling routines
16 *
17 */
18
19#define P_FONT_C
20
21#include "p_intern.h"
22#include "p_font.h"
23#include "p_truetype.h"
24
25
26static const pdc_keyconn pdf_extension_names[] =
27{
28    {".ttf", 1},
29    {".otf", 1},
30    {".afm", 2},
31    {".pfm", 3},
32    {".ttc", 1},
33    {".TTF", 1},
34    {".OTF", 1},
35    {".AFM", 2},
36    {".PFM", 3},
37    {".TTC", 1},
38    {".pfa", 4},
39    {".pfb", 4},
40    {".PFA", 4},
41    {".PFB", 4},
42    {NULL, 0}
43};
44
45static const pdc_keyconn pdf_fontstyle_pdfkeys[] =
46{
47    {"Normal",     pdc_Normal},
48    {"Bold",       pdc_Bold},
49    {"Italic",     pdc_Italic},
50    {"BoldItalic", pdc_BoldItalic},
51    {NULL, 0}
52};
53
54const char *
55pdf_get_fontname(PDF *p)
56{
57    if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */
58        pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "fontname", 0, 0, 0);
59
60    return p->fonts[p->tstate[p->sl].f].name;
61}
62
63const char *
64pdf_get_fontstyle(PDF *p)
65{
66    if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */
67        pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "fontstyle", 0, 0, 0);
68
69    return pdc_get_keyword(p->fonts[p->tstate[p->sl].f].style,
70                           pdf_fontstyle_keylist);
71}
72
73const char *
74pdf_get_fontencoding(PDF *p)
75{
76    pdc_font *font;
77    const char *ret;
78
79    if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */
80        pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "fontencoding", 0, 0, 0);
81
82    font = &p->fonts[p->tstate[p->sl].f];
83    switch (font->encoding)
84    {
85        case pdc_cid:
86            ret = (const char *) font->cmapname;
87            break;
88
89        default:
90            ret = pdf_get_encoding_name(p, font->encoding);
91    }
92
93    return ret;
94}
95
96int
97pdf_get_monospace(PDF *p)
98{
99    if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */
100        pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "fontstyle", 0, 0, 0);
101
102    return p->fonts[p->tstate[p->sl].f].monospace;
103}
104
105int
106pdf_get_font(PDF *p)
107{
108    if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */
109        pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "font", 0, 0, 0);
110
111    return p->tstate[p->sl].f;
112}
113
114static void
115pdf_cleanup_font(PDF *p, pdc_font *font)
116{
117    if (font->imgname)
118        pdf_unlock_pvf(p, font->imgname);
119    pdc_cleanup_font_struct(p->pdc, font);
120}
121
122void
123pdf_cleanup_fonts(PDF *p)
124{
125    int slot;
126
127    if (p->fonts)
128    {
129        for (slot = 0; slot < p->fonts_number; slot++)
130            pdf_cleanup_font(p, &p->fonts[slot]);
131
132        if (p->fonts)
133            pdc_free(p->pdc, p->fonts);
134        p->fonts = NULL;
135    }
136}
137
138void
139pdf_init_fonts(PDF *p)
140{
141    p->fonts_number     = 0;
142    p->fonts_capacity   = FONTS_CHUNKSIZE;
143
144    p->fonts = (pdc_font *) pdc_calloc(p->pdc,
145                sizeof(pdc_font) * p->fonts_capacity, "pdf_init_fonts");
146
147    p->t3font = (pdc_t3font *) NULL;
148
149    pdf_init_encoding_ids(p);
150}
151
152void
153pdf_grow_fonts(PDF *p)
154{
155    p->fonts = (pdc_font *) pdc_realloc(p->pdc, p->fonts,
156                sizeof(pdc_font) * 2 * p->fonts_capacity, "pdf_grow_fonts");
157
158    p->fonts_capacity *= 2;
159}
160
161int
162pdf_init_newfont(PDF *p)
163{
164    pdc_font *font;
165    int slot;
166
167    /* slot for font struct */
168    slot = p->fonts_number;
169    if (slot >= p->fonts_capacity)
170        pdf_grow_fonts(p);
171
172    /* initialize font struct */
173    font = &p->fonts[slot];
174    pdc_init_font_struct(p->pdc, font);
175
176    /* inherite global settings */
177    font->verbose = p->debug['F'];
178    font->verbose_open = font->verbose;
179
180    return slot;
181}
182
183static pdc_bool
184pdf_get_metrics_core(PDF *p, pdc_font *font, const char *fontname,
185                     pdc_encoding enc)
186{
187    const pdc_core_metric *metric;
188
189    metric = pdc_get_core_metric(fontname);
190    if (metric != NULL)
191    {
192        /* Fill up the font struct */
193        pdc_fill_font_metric(p->pdc, font, metric);
194        font->encoding = enc;
195
196        /* Process metric data */
197        if (pdf_process_metrics_data(p, font, fontname))
198        {
199            if (!pdf_make_fontflag(p, font))
200                return pdc_false;
201
202            if (font->monospace)
203            {
204                pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0);
205                if (font->verbose == pdc_true)
206                    pdc_error(p->pdc, -1, 0, 0, 0, 0);
207                return pdc_false;
208            }
209            return pdc_true;
210        }
211    }
212    return pdc_undef;
213}
214
215pdc_bool
216pdf_make_fontflag(PDF *p, pdc_font *font)
217{
218    (void) p;
219
220    if (font->type != pdc_Type3)
221    {
222        if (font->isFixedPitch)
223            font->flags |= FIXEDWIDTH;
224
225        if (font->isstdlatin == pdc_true ||
226            font->encoding == pdc_winansi ||
227            font->encoding == pdc_macroman ||
228            font->encoding == pdc_ebcdic)
229            font->flags |= ADOBESTANDARD;
230        else
231            font->flags |= SYMBOL;
232
233        if (font->italicAngle < 0 ||
234            font->style == pdc_Italic || font->style == pdc_BoldItalic)
235            font->flags |= ITALIC;
236        if (font->italicAngle == 0 && font->flags & ITALIC)
237            font->italicAngle = PDC_DEF_ITALICANGLE;
238
239        /* heuristic to identify (small) caps fonts */
240        if (font->name &&
241            (strstr(font->name, "Caps") ||
242            !strcmp(font->name + strlen(font->name) - 2, "SC")))
243            font->flags |= SMALLCAPS;
244
245        if (font->style == pdc_Bold || font->style == pdc_BoldItalic)
246            font->StdVW = PDF_STEMV_BOLD;
247
248        if (strstr(font->name, "Bold") || font->StdVW > PDF_STEMV_SEMIBOLD)
249            font->flags |= FORCEBOLD;
250    }
251
252    if (font->style != pdc_Normal &&
253        (font->embedding || font->type == pdc_Type1 ||
254         font->type == pdc_MMType1 || font->type == pdc_Type3))
255    {
256        pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "fontstyle", 0, 0, 0);
257        if (font->verbose == pdc_true)
258            pdc_error(p->pdc, -1, 0, 0, 0, 0);
259        return pdc_false;
260    }
261    return pdc_true;
262}
263
264#define PDF_KERNING_FLAG PDC_OPT_UNSUPP
265
266#define PDF_SUBSETTING_FLAG  PDC_OPT_UNSUPP
267#define PDF_AUTOSUBSETT_FLAG PDC_OPT_UNSUPP
268
269#define PDF_AUTOCIDFONT_FLAG PDC_OPT_UNSUPP
270
271/* definitions of image options */
272static const pdc_defopt pdf_load_font_options[] =
273{
274    {"fontwarning", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
275
276    {"embedding", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
277
278    {"kerning", pdc_booleanlist, PDF_KERNING_FLAG, 1, 1, 0.0, 0.0, NULL},
279
280    {"subsetting", pdc_booleanlist, PDF_SUBSETTING_FLAG, 1, 1, 0.0, 0.0,
281     NULL},
282
283    {"autosubsetting", pdc_booleanlist, PDF_AUTOSUBSETT_FLAG, 1, 1, 0.0, 0.0,
284     NULL},
285
286    {"subsetlimit", pdc_floatlist, PDF_SUBSETTING_FLAG, 1, 1, 0.0, 100.0,
287     NULL},
288
289    {"subsetminsize", pdc_floatlist, PDF_SUBSETTING_FLAG, 1, 1,
290     0.0, PDC_FLOAT_MAX, NULL},
291
292    {"autocidfont", pdc_booleanlist, PDF_AUTOCIDFONT_FLAG, 1, 1, 0.0, 0.0,
293     NULL},
294
295    {"unicodemap", pdc_booleanlist, PDF_AUTOCIDFONT_FLAG, 1, 1, 0.0, 0.0,
296     NULL},
297
298    {"fontstyle", pdc_keywordlist, 0, 1, 1, 0.0, 0.0,
299     pdf_fontstyle_keylist},
300
301    {"monospace", pdc_integerlist, 0, 1, 1, 1.0, 2048.0,
302     NULL},
303
304    PDC_OPT_TERMINATE
305};
306
307int
308pdf__load_font(PDF *p, const char *fontname, int inlen,
309               const char *encoding, const char *optlist)
310{
311    static const char fn[] = "pdf__load_font";
312    pdc_resopt *results;
313    pdc_encoding enc = pdc_invalidenc;
314    pdc_bool fontwarning;
315    pdc_bool kret;
316    int slot = -1;
317    size_t len;
318    int i;
319    int retval, inum;
320    pdc_font *font;
321    const char *extension = NULL;
322    char *fontname_p = NULL;
323    char *outfilename = NULL;
324    char *filename = NULL, testfilename[PDF_MAX_FONTNAME + 5];
325    char *mmparam, mastername[PDF_MAX_FONTNAME + 1];
326
327    if (encoding == NULL || *encoding == '\0')
328        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "encoding", 0, 0, 0);
329
330    if (fontname == NULL)
331        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
332
333    /* Converting fontname to UTF-8 */
334    if (inlen)
335    {
336        pdc_byte *utf8fontname;
337        pdc_text_format textformat = pdc_bytes2;
338        pdc_text_format targettextformat = pdc_utf8;
339        int outlen;
340
341        if (pdc_convert_string(p->pdc, textformat, NULL,
342                               (pdc_byte *) fontname, inlen,
343                               &targettextformat, NULL,
344                               &utf8fontname, &outlen,
345                               PDC_CONV_WITHBOM | PDC_CONV_TRY7BYTES,
346                               p->debug['F']))
347        {
348            if (p->debug['F'])
349                pdc_error(p->pdc, -1, 0, 0, 0, 0);
350            return -1;
351        }
352
353        fontname = pdc_errprintf(p->pdc, "%s", utf8fontname);
354        pdc_free(p->pdc, utf8fontname);
355    }
356
357    if (*fontname == '\0')
358        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
359
360    /* slot for new font struct */
361    slot = pdf_init_newfont(p);
362    font = &p->fonts[slot];
363
364    /* parsing optlist */
365    font->verbose = p->debug['F'];
366    if (optlist && strlen(optlist))
367    {
368        results = pdc_parse_optionlist(p->pdc, optlist, pdf_load_font_options,
369                                       NULL, font->verbose);
370        if (!results)
371            return -1;
372
373        /* save and check options */
374        pdc_get_optvalues(p->pdc, "fontwarning", results,
375                          &font->verbose, NULL);
376
377        pdc_get_optvalues(p->pdc, "embedding", results,
378                          &font->embedding, NULL);
379
380
381
382
383        if (pdc_get_optvalues(p->pdc, "fontstyle", results, &inum, NULL))
384            font->style = (pdc_fontstyle) inum;
385
386        pdc_get_optvalues(p->pdc, "monospace", results,
387                          &font->monospace, NULL);
388
389        pdc_cleanup_optionlist(p->pdc, results);
390    }
391
392    /* search for a registered encoding */
393    slot = -1;
394    kret = pdc_false;
395    fontwarning = p->debug['F'];
396    p->debug['F'] = (char) font->verbose;
397    enc = pdf_find_encoding(p, encoding);
398
399    if (enc == pdc_unicode || enc == pdc_glyphid)
400        pdc_error(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
401
402    if (enc == pdc_invalidenc)
403    {
404        /* check the known CMap names */
405        slot = pdf_handle_cidfont(p, fontname, encoding);
406        if (slot == -1)
407        {
408            /* look for a new encoding */
409            enc = pdf_insert_encoding(p, encoding);
410            if (enc == pdc_invalidenc)
411                kret = pdc_true;
412        }
413        else
414	{
415            kret = pdc_true;
416	    if (slot == -2)	/* error occurred in pdf_handle_cidfont() */
417		slot = -1;
418	}
419    }
420    p->debug['F'] = (char) fontwarning;
421    if (kret)
422        return slot;
423
424    /*
425     * Look whether font is already in the cache.
426     * If a font with same encoding and same relevant options is found,
427     * return its descriptor.
428     * If a Type 3 font with the same name but different encoding
429     * is found, make a copy in a new slot and attach the requested encoding.
430     */
431
432    for (slot = 0; slot < p->fonts_number; slot++)
433    {
434        if (!strcmp(p->fonts[slot].apiname, fontname) &&
435            p->fonts[slot].style == font->style)
436        {
437            if (p->fonts[slot].type == pdc_Type3)
438            {
439                if (enc < 0 )
440                {
441		    pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC,
442			p->fonts[slot].name,
443			pdf_get_encoding_name(p, enc), 0, 0);
444
445                    if (font->verbose == pdc_true)
446                        pdc_error(p->pdc, -1, 0, 0, 0, 0);
447
448                    return -1;
449                }
450                if (p->fonts[slot].encoding != enc)
451                    slot = pdf_handle_t3font(p, fontname, enc, slot);
452
453                return slot;
454            }
455            else if (p->fonts[slot].monospace == font->monospace)
456            {
457                if (p->fonts[slot].encoding == enc)
458                {
459                    return slot;
460                }
461                else if (p->fonts[slot].encoding >= 0)
462                {
463                    char *encname, *adaptname;
464                    int kc;
465
466                    /* Comparing apiname of encoding */
467                    if (!strcmp(encoding, p->fonts[slot].encapiname))
468                        return slot;
469
470                    /* Name of adapted to font encoding */
471                    encname = (char *) pdf_get_encoding_name(p, enc);
472                    len = strlen(encname) + 1 + strlen(fontname) + 1;
473                    adaptname = (char *) pdc_malloc(p->pdc, len, fn);
474                    strcpy(adaptname, encname);
475                    strcat(adaptname, PDC_ENC_MODSEPAR);
476                    strcat(adaptname, fontname);
477                    kc = strcmp(adaptname,
478                            pdf_get_encoding_name(p, p->fonts[slot].encoding));
479                    pdc_free(p->pdc, adaptname);
480                    if (!kc)
481                        return slot;
482                }
483            }
484        }
485    }
486
487
488    /* Multiple Master handling:
489     * - strip MM parameters to build the master name
490     * - the master name is used to find the metrics
491     * - the instance name (client-supplied font name) is used in all places
492     * - although the master name is used for finding the metrics, the
493     *   instance name is stored in the font struct.
494     */
495
496    len = strlen(fontname);
497    if (len > PDF_MAX_FONTNAME)
498    {
499	pdc_set_errmsg(p->pdc, PDC_E_ILLARG_TOOLONG, "fontname",
500	    pdc_errprintf(p->pdc, "%d", PDF_MAX_FONTNAME), 0, 0);
501
502        if (font->verbose)
503            pdc_error(p->pdc, -1, 0, 0, 0, 0);
504
505        return -1;
506    }
507    strcpy(mastername, fontname);
508
509    /* A Multiple Master font was requested */
510    if ((mmparam = strstr(mastername, "MM_")) != NULL)
511    {
512        if (font->embedding)
513        {
514	    pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDMM, fontname, 0, 0, 0);
515
516            if (font->verbose)
517                pdc_error(p->pdc, -1, 0, 0, 0, 0);
518
519            return -1;
520        }
521        mmparam[2] = '\0';      /* strip the parameter from the master name */
522    }
523
524    /* Font with vertical writing mode */
525    fontname_p = mastername;
526    if (mastername[0] == '@')
527    {
528        font->vertical = pdc_true;
529        fontname_p = &mastername[1];
530    }
531
532    /* API font name */
533    font->apiname = pdc_strdup(p->pdc, fontname);
534
535    /* Font file search hierarchy
536     * - Check "FontOutline" resource entry and check TrueType font
537     * - Check "FontAFM" resource entry
538     * - Check "FontPFM" resource entry
539     * - Check "HostFont" resource entry
540     * - Check available in-core metrics
541     * - Check host font
542     */
543    retval = pdc_false;
544    while (1)
545    {
546#ifdef PDF_TRUETYPE_SUPPORTED
547        /* Check specified TrueType file */
548        filename = pdf_find_resource(p, "FontOutline", fontname_p);
549        if (filename) {
550            outfilename = filename;
551            retval = pdf_check_tt_font(p, filename, fontname_p, font);
552            if (retval == pdc_undef) {
553                retval = pdc_false;
554                break;
555            }
556            if (retval == pdc_true) {
557                retval = pdf_get_metrics_tt(p, font, fontname_p, enc, filename);
558                break;
559            }
560        }
561#endif /* PDF_TRUETYPE_SUPPORTED */
562
563        /* Check specified AFM file */
564        filename = pdf_find_resource(p, "FontAFM", fontname_p);
565        if (filename) {
566            retval = pdf_get_metrics_afm(p, font, fontname_p, enc, filename);
567            break;
568        }
569
570        /* Check specified PFM file */
571        filename = pdf_find_resource(p, "FontPFM", fontname_p);
572        if (filename) {
573            retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, filename);
574            break;
575        }
576
577
578
579        /* Check available in-core metrics */
580        retval = pdf_get_metrics_core(p, font, fontname_p, enc);
581        if (retval != pdc_undef) break;
582        retval = pdc_false;
583
584
585        /* Search for a metric file */
586        font->verbose_open = pdc_false;
587        filename = testfilename;
588        for (i = 0; i < 100; i++)
589        {
590            extension = pdf_extension_names[i].word;
591            if (!extension) break;
592            strcpy(testfilename, fontname_p);
593            strcat(testfilename, extension);
594            switch (pdf_extension_names[i].code)
595            {
596                case 1:
597                if (pdf_check_tt_font(p, filename, fontname_p, font) ==
598                    pdc_true)
599                    retval = pdf_get_metrics_tt(p, font, fontname_p, enc,
600                                                filename);
601                break;
602
603                case 2:
604                retval = pdf_get_metrics_afm(p, font, fontname_p, enc,
605                                             filename);
606                break;
607
608                case 3:
609                retval = pdf_get_metrics_pfm(p, font, fontname_p, enc,
610                                             filename);
611                break;
612            }
613            if (retval == pdc_true)
614            {
615                if (pdf_extension_names[i].code == 1)
616                    outfilename = filename;
617                break;
618            }
619        }
620
621        if (retval == pdc_false)
622	{
623            pdc_set_errmsg(p->pdc, PDF_E_FONT_NOMETRICS, fontname, 0, 0, 0);
624
625	    if (font->verbose)
626		pdc_error(p->pdc, -1, 0, 0, 0, 0);
627	}
628        break;
629    }
630
631    if (retval == pdc_false) {
632        pdf_cleanup_font(p, font);
633        return -1;
634    }
635
636    /* store instance name instead of master name in the font structure */
637    if (mmparam) {
638        pdc_free(p->pdc, font->name);
639        font->name = pdc_strdup(p->pdc, fontname);
640    }
641
642    /* If embedding was requested, check font file (or raise an exception) */
643    font->verbose_open = font->verbose;
644    if (font->embedding) {
645        if (font->img == NULL) {
646            pdc_file *fp = NULL;
647            if (outfilename) {
648                if ((fp = pdf_fopen(p, outfilename, "font ", 0)) == NULL)
649		{
650                    if (font->verbose)
651			pdc_error(p->pdc, -1, 0, 0, 0, 0);
652
653                    retval = pdc_false;
654                }
655                if ((font->type == pdc_Type1 || font->type == pdc_MMType1) &&
656                    (pdf_t1check_fontfile(p, font, fp) == pdc_undef)) {
657                    pdc_fclose(fp);
658                    retval = pdc_false;
659                }
660            } else {
661                outfilename = testfilename;
662                for (i = 0; i < 100; i++) {
663                    extension = pdf_extension_names[i].word;
664                    if (!extension) break;
665                    strcpy(testfilename, fontname_p);
666                    strcat(testfilename, extension);
667                    if (pdf_extension_names[i].code == 4 &&
668                        (fp = pdf_fopen(p, outfilename, NULL, 0)) != NULL) {
669                        if (pdf_t1check_fontfile(p, font, fp) != pdc_undef)
670                            break;
671                        pdc_fclose(fp);
672                        fp = NULL;
673                    }
674                }
675                if (fp == NULL)
676		{
677		    pdc_set_errmsg(p->pdc, PDF_E_FONT_NOOUTLINE, fontname,
678			0, 0, 0);
679
680                    if (font->verbose)
681                        pdc_error(p->pdc, -1, 0, 0, 0, 0);
682
683                    retval = pdc_false;
684                }
685            }
686            if (retval == pdc_true) {
687                if (pdc_file_isvirtual(fp) == pdc_true) {
688                    font->imgname = pdc_strdup(p->pdc, outfilename);
689                    pdf_lock_pvf(p, font->imgname);
690                }
691                pdc_fclose(fp);
692                font->fontfilename = pdc_strdup(p->pdc, outfilename);
693            }
694        }
695    } else if (font->img) {
696        if (!font->imgname) {
697            pdc_free(p->pdc, font->img);
698        } else {
699            pdf_unlock_pvf(p, font->imgname);
700            pdc_free(p->pdc, font->imgname);
701            font->imgname = NULL;
702        }
703        font->img = NULL;
704        font->filelen = 0;
705    }
706
707    if (retval && font->monospace && font->embedding)
708    {
709        pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0);
710        if (font->verbose == pdc_true)
711            pdc_error(p->pdc, -1, 0, 0, 0, 0);
712        retval = pdc_false;
713    }
714
715    if (retval == pdc_false) {
716        pdf_cleanup_font(p, font);
717        return -1;
718    }
719
720    /* Now everything is fine; fill the remaining font cache entries */
721
722    p->fonts_number++;
723
724    font->verbose_open = pdc_true;
725
726    font->encapiname = pdc_strdup(p->pdc, encoding);
727
728    if (enc >= 0)
729        p->encodings[enc].ev->flags |= PDC_ENC_USED;
730
731    font->obj_id = pdc_alloc_id(p->out);
732
733    return slot;
734}
735
736PDFLIB_API int PDFLIB_CALL
737PDF_load_font(PDF *p, const char *fontname, int len,
738              const char *encoding, const char *optlist)
739{
740    static const char fn[] = "PDF_load_font";
741    int slot = -1;
742
743    if (pdf_enter_api(p, fn,
744        (pdf_state) (pdf_state_document | pdf_state_content),
745        "(p[%p], \"%s\", %d, \"%s\", \"%s\")",
746        (void *) p, pdc_strprint(p->pdc, fontname, len), len, encoding,optlist))
747    {
748        slot = pdf__load_font(p, fontname, len, encoding, optlist);
749    }
750
751    PDF_RETURN_HANDLE(p, slot)
752}
753
754PDFLIB_API int PDFLIB_CALL
755PDF_findfont(PDF *p, const char *fontname, const char *encoding, int embed)
756{
757    static const char fn[] = "PDF_findfont";
758    char optlist[256];
759    int slot = -1;
760
761    if (!pdf_enter_api(p, fn,
762        (pdf_state) (pdf_state_document | pdf_state_content),
763        "(p[%p], \"%s\", \"%s\", %d)", (void *) p, fontname, encoding, embed))
764    {
765        PDF_RETURN_HANDLE(p, slot)
766    }
767
768    if (embed < 0 || embed > 1)
769        pdc_error(p->pdc, PDC_E_ILLARG_INT,
770            "embed", pdc_errprintf(p->pdc, "%d", embed), 0, 0);
771
772    optlist[0] = 0;
773    if (embed)
774        strcat(optlist, "embedding true ");
775
776    slot = pdf__load_font(p, fontname, 0, encoding, (const char *) optlist);
777
778    PDF_RETURN_HANDLE(p, slot)
779}
780
781PDFLIB_API int PDFLIB_CALL
782PDF_get_glyphid(PDF *p, int font, int code)
783{
784    static const char fn[] = "PDF_get_glyphid";
785    int gid = 0;
786
787    if (!pdf_enter_api(p, fn,
788        (pdf_state) (pdf_state_document | pdf_state_content | pdf_state_path),
789        "(p[%p], %d, %04X)", (void *) p, font, code))
790    {
791        pdc_trace(p->pdc, "[%d]\n", gid);
792        return gid;
793    }
794
795    PDF_INPUT_HANDLE(p, font)
796    if (font < 0 || font >= p->fonts_number)
797        pdc_error(p->pdc, PDC_E_ILLARG_INT,
798            "font", pdc_errprintf(p->pdc, "%d", font), 0, 0);
799
800    if (code < 0 || code >= p->fonts[font].numOfCodes)
801        pdc_error(p->pdc, PDC_E_ILLARG_INT,
802            "code", pdc_errprintf(p->pdc, "%d", code), 0, 0);
803
804    if (p->fonts[font].code2GID)
805        gid = p->fonts[font].code2GID[code];
806    else
807        pdc_error(p->pdc, PDF_E_FONT_NOGLYPHID, p->fonts[font].apiname, 0, 0,0);
808
809    pdc_trace(p->pdc, "[%d]\n", gid);
810    return gid;
811}
812
813
814static void
815pdf_write_fontdescriptor(
816    PDF *p,
817    pdc_font *font,
818    pdc_id fontdescriptor_id,
819    pdc_id fontfile_id)
820{
821    /*
822     * Font descriptor object
823     */
824    pdc_begin_obj(p->out, fontdescriptor_id);   /* font descriptor obj */
825    pdc_begin_dict(p->out);                     /* font descriptor dict */
826
827    pdc_puts(p->out, "/Type/FontDescriptor\n");
828    pdc_printf(p->out, "/Ascent %d\n", font->ascender);
829    pdc_printf(p->out, "/CapHeight %d\n", font->capHeight);
830    pdc_printf(p->out, "/Descent %d\n", font->descender);
831    pdc_printf(p->out, "/Flags %ld\n", font->flags);
832    pdc_printf(p->out, "/FontBBox[%d %d %d %d]\n",
833        (int) font->llx, (int) font->lly, (int) font->urx, (int) font->ury);
834
835    pdc_printf(p->out, "/FontName");
836    pdc_put_pdfname(p->out, font->name, strlen(font->name));
837    pdc_puts(p->out, "\n");
838
839    pdc_printf(p->out, "/ItalicAngle %d\n", (int) (font->italicAngle));
840    pdc_printf(p->out, "/StemV %d\n", font->StdVW);
841
842    if (font->StdHW > 0)
843        pdc_printf(p->out, "/StemH %d\n", font->StdHW);
844
845    if (font->xHeight > 0)
846        pdc_printf(p->out, "/XHeight %d\n", font->xHeight);
847
848    if (fontfile_id != PDC_BAD_ID)
849    {
850        switch(font->type)
851        {
852            case pdc_Type1:
853            case pdc_MMType1:
854            pdc_printf(p->out, "/FontFile %ld 0 R\n", fontfile_id);
855            break;
856
857#ifdef PDF_TRUETYPE_SUPPORTED
858            case pdc_TrueType:
859            case pdc_CIDFontType2:
860            pdc_printf(p->out, "/FontFile2 %ld 0 R\n", fontfile_id);
861            break;
862
863            case pdc_Type1C:
864            case pdc_CIDFontType0:
865            pdc_printf(p->out, "/FontFile3 %ld 0 R\n", fontfile_id);
866            break;
867#endif /* PDF_TRUETYPE_SUPPORTED */
868
869            default:
870            break;
871        }
872    }
873
874    pdc_end_dict(p->out);                       /* font descriptor dict */
875    pdc_end_obj(p->out);                        /* font descriptor obj */
876}
877
878static void
879pdf_put_font(PDF *p, pdc_font *font)
880{
881    const char        *fontname = font->name;
882    pdc_id             fontdescriptor_id = PDC_BAD_ID;
883    pdc_id             fontfile_id = PDC_BAD_ID;
884    pdc_id             encoding_id = PDC_BAD_ID;
885    const char *Adobe_str = "\101\144\157\142\145";
886    pdc_id             descendant_id = PDC_BAD_ID;
887    pdc_encoding       enc = font->encoding;
888    pdc_bool           base_font = pdc_false;
889    pdc_bool           comp_font = pdc_false;
890    float              a = (float) 1.0;
891    PDF_data_source    src;
892    int                slot, i, j;
893
894    /*
895     * This Type3 font has been defined, but never used. Ignore it.
896     * However, the font's object id has already been allocated.
897     * Write a dummy object in order to avoid a complaint
898     * of the object machinery.
899     */
900    if (enc == pdc_invalidenc)
901    {
902        pdc_begin_obj(p->out, font->obj_id);            /* dummy font obj */
903        pdc_printf(p->out, "null %% unused Type 3 font '%s'\n",
904                   font->apiname);
905        pdc_end_obj(p->out);
906        return;
907    }
908
909
910    /* ID for embedded font */
911    if (font->embedding)
912    {
913        switch(font->type)
914        {
915            case pdc_Type1:
916            case pdc_MMType1:
917            case pdc_TrueType:
918            case pdc_CIDFontType2:
919            case pdc_Type1C:
920            case pdc_CIDFontType0:
921            fontfile_id = pdc_alloc_id(p->out);
922            break;
923
924            default:
925            break;
926        }
927    }
928    else if (font->type == pdc_Type1)
929    {
930        const char *basename;
931
932        /* check whether we have one of the base 14 fonts */
933        for (slot = 0; ; slot++)
934        {
935            basename = pdc_get_base14_name(slot);
936            if (basename == NULL)
937                break;
938            if (!strcmp(basename, fontname))
939            {
940                base_font = pdc_true;
941                break;
942            }
943        }
944    }
945
946    /*
947     * Font dictionary
948     */
949    pdc_begin_obj(p->out, font->obj_id);                /* font obj */
950    pdc_begin_dict(p->out);                             /* font dict */
951    pdc_puts(p->out, "/Type/Font\n");
952
953    /* /Subtype */
954    switch (font->type)
955    {
956        case pdc_Type1:
957        pdc_puts(p->out, "/Subtype/Type1\n");
958        break;
959
960        case pdc_MMType1:
961        pdc_puts(p->out, "/Subtype/MMType1\n");
962        break;
963
964        case pdc_TrueType:
965        pdc_puts(p->out, "/Subtype/TrueType\n");
966        fontname = font->ttname;
967        break;
968
969        case pdc_Type1C:
970        fontname = font->ttname;
971        pdc_puts(p->out, "/Subtype/Type1\n");
972        break;
973
974        case pdc_CIDFontType2:
975        case pdc_CIDFontType0:
976        fontname = font->ttname;
977        pdc_puts(p->out, "/Subtype/Type0\n");
978        comp_font = pdc_true;
979        break;
980
981        case pdc_Type3:
982        pdc_puts(p->out, "/Subtype/Type3\n");
983        break;
984    }
985
986    /* /Name */
987    if (font->type == pdc_Type3)
988    {
989        /*
990         * The name is optional, but if we include it it will show up
991         * in Acrobat's font info box. However, if the same font name
992         * is used with different encodings Acrobat 4 will not be
993         * able to distinguish both. For this reason we add the
994         * encoding name to make the font name unique.
995         */
996        pdc_puts(p->out, "/Name");
997        pdc_put_pdfname(p->out, fontname, strlen(fontname));
998        pdc_puts(p->out, "\n");
999    }
1000
1001    /* /BaseFont */
1002    switch (font->type)
1003    {
1004        case pdc_Type1:
1005        case pdc_MMType1:
1006        case pdc_TrueType:
1007        case pdc_Type1C:
1008        case pdc_CIDFontType2:
1009        case pdc_CIDFontType0:
1010        {
1011            pdc_puts(p->out, "/BaseFont");
1012            pdc_put_pdfname(p->out, fontname, strlen(fontname));
1013            if (font->cmapname)
1014                pdc_printf(p->out, "-%s", font->cmapname);
1015            if (font->style != pdc_Normal && !comp_font)
1016                pdc_printf(p->out, ",%s",
1017                    pdc_get_keyword(font->style, pdf_fontstyle_pdfkeys));
1018            pdc_puts(p->out, "\n");
1019        }
1020        break;
1021
1022        /* /FontBBox, /FontMatrix, /CharProcs /Resources */
1023        case pdc_Type3:
1024        pdc_printf(p->out, "/FontBBox[%f %f %f %f]\n",
1025            font->t3font->bbox.llx, font->t3font->bbox.lly,
1026            font->t3font->bbox.urx, font->t3font->bbox.ury);
1027
1028        pdc_printf(p->out, "/FontMatrix[%f %f %f %f %f %f]\n",
1029            font->t3font->matrix.a, font->t3font->matrix.b,
1030            font->t3font->matrix.c, font->t3font->matrix.d,
1031            font->t3font->matrix.e, font->t3font->matrix.f);
1032        pdc_printf(p->out, "/CharProcs %ld 0 R\n", font->t3font->charprocs_id);
1033        pdc_printf(p->out, "/Resources %ld 0 R\n", font->t3font->res_id);
1034
1035        /* We must apply a correctional factor since Type 3 fonts not
1036         * necessarily use 1000 units per em. We apply the correction
1037         * here, and store the 1000-based width values in the font in
1038         * order to speed up PDF_stringwidth().
1039         */
1040        a = (float) 1000 * font->t3font->matrix.a;
1041        break;
1042    }
1043
1044    /* /FontDescriptor, /FirstChar, /LastChar, /Widths */
1045    switch (font->type)
1046    {
1047        case pdc_Type1:
1048        if (base_font == pdc_true) break;
1049        case pdc_MMType1:
1050        case pdc_TrueType:
1051        case pdc_Type1C:
1052        {
1053            fontdescriptor_id = pdc_alloc_id(p->out);
1054            pdc_printf(p->out, "/FontDescriptor %ld 0 R\n", fontdescriptor_id);
1055        }
1056        case pdc_Type3:
1057        {
1058
1059            pdc_puts(p->out, "/FirstChar 0\n");
1060            pdc_puts(p->out, "/LastChar 255\n");
1061
1062            pdc_puts(p->out, "/Widths[\n");
1063            for (i = 0; i < 16; i++)
1064            {
1065                for (j = 0; j < 16; j++)
1066                    pdc_printf(p->out, " %d",
1067                               (int) ((font->widths[16*i + j]) / a + 0.5));
1068                pdc_puts(p->out, "\n");
1069            }
1070            pdc_puts(p->out, "]\n");
1071        }
1072        break;
1073
1074        default:
1075        break;
1076    }
1077
1078    /* /Encoding */
1079    switch (font->type)
1080    {
1081        case pdc_Type1:
1082        case pdc_MMType1:
1083        case pdc_TrueType:
1084        case pdc_Type1C:
1085        if (enc == pdc_winansi)
1086        {
1087            pdc_printf(p->out, "/Encoding/WinAnsiEncoding\n");
1088            break;
1089        }
1090        if (enc == pdc_macroman && font->hasnomac == pdc_false)
1091        {
1092            pdc_printf(p->out, "/Encoding/MacRomanEncoding\n");
1093            break;
1094        }
1095        case pdc_Type3:
1096        if (enc >= 0)
1097        {
1098            if (p->encodings[enc].id == PDC_BAD_ID)
1099                p->encodings[enc].id = pdc_alloc_id(p->out);
1100            encoding_id = p->encodings[enc].id;
1101        }
1102        if (encoding_id != PDC_BAD_ID)
1103            pdc_printf(p->out, "/Encoding %ld 0 R\n", encoding_id);
1104        break;
1105
1106        case pdc_CIDFontType2:
1107        case pdc_CIDFontType0:
1108        if (font->cmapname)
1109            pdc_printf(p->out, "/Encoding/%s\n", font->cmapname);
1110        break;
1111    }
1112
1113
1114    /* /DescendantFonts */
1115    if (comp_font == pdc_true)
1116    {
1117        descendant_id = pdc_alloc_id(p->out);
1118        pdc_printf(p->out, "/DescendantFonts[%ld 0 R]\n", descendant_id);
1119    }
1120
1121    pdc_end_dict(p->out);                               /* font dict */
1122    pdc_end_obj(p->out);                                /* font obj */
1123
1124    /*
1125     * Encoding dictionary
1126     */
1127    if (encoding_id != PDC_BAD_ID)
1128    {
1129        char *charname;
1130
1131        pdc_begin_obj(p->out, encoding_id);             /* encoding obj */
1132        pdc_begin_dict(p->out);                         /* encoding dict */
1133
1134        pdc_puts(p->out, "/Type/Encoding\n");
1135
1136        {
1137            pdc_encodingvector *ev = p->encodings[enc].ev;
1138            pdc_encodingvector *evb = NULL;
1139            int islatin1 =
1140                !strncmp((const char *) ev->apiname, "iso8859-1",
1141                         strlen("iso8859-1"));
1142
1143            pdf_set_encoding_glyphnames(p, enc);
1144
1145            if (!strncmp(ev->apiname, PDC_ENC_MODWINANSI,
1146                         strlen(PDC_ENC_MODWINANSI))
1147                || islatin1)
1148            {
1149                pdc_puts(p->out, "/BaseEncoding/WinAnsiEncoding\n");
1150                evb = p->encodings[pdc_winansi].ev;
1151                if (!evb)
1152                    p->encodings[pdc_winansi].ev =
1153                        pdc_copy_core_encoding(p->pdc, "winansi");
1154            }
1155            if (!strncmp(ev->apiname, PDC_ENC_MODMACROMAN,
1156                         strlen(PDC_ENC_MODMACROMAN)))
1157            {
1158                pdc_puts(p->out, "/BaseEncoding/MacRomanEncoding\n");
1159                evb = p->encodings[pdc_macroman].ev;
1160                if (!evb)
1161                    p->encodings[pdc_macroman].ev =
1162                        pdc_copy_core_encoding(p->pdc, "macroman");
1163            }
1164
1165            if (evb && font->type != pdc_Type3)
1166            {
1167                int iv = -1;
1168                for (i = 0; i < font->numOfCodes; i++)
1169                {
1170                    if ((ev->chars[i] && !evb->chars[i]) ||
1171                        (!ev->chars[i] && evb->chars[i]) ||
1172                        (ev->chars[i] && evb->chars[i] &&
1173                         strcmp(ev->chars[i], evb->chars[i])))
1174                    {
1175                        if (iv == -1)
1176                            pdc_puts(p->out, "/Differences[");
1177                        if (i > iv + 1)
1178                            pdc_printf(p->out, "%d", i);
1179                        charname = (char *)
1180                            ev->chars[i] ? ev->chars[i] : (char *) ".notdef";
1181                        pdc_put_pdfname(p->out, charname, strlen(charname));
1182                        pdc_puts(p->out, "\n");
1183                        iv = i;
1184                    }
1185                }
1186                if (iv > -1)
1187                    pdc_puts(p->out, "]\n");
1188            }
1189            else
1190            {
1191                pdc_puts(p->out, "/Differences[0");
1192                for (i = 0; i < font->numOfCodes; i++)
1193                {
1194                    charname = (char *) ev->chars[i] ?
1195                                   ev->chars[i] :  (char *) ".notdef";
1196                    pdc_put_pdfname(p->out, charname, strlen(charname));
1197                    pdc_puts(p->out, "\n");
1198                }
1199                pdc_puts(p->out, "]\n");
1200            }
1201        }
1202
1203        pdc_end_dict(p->out);                           /* encoding dict */
1204        pdc_end_obj(p->out);                            /* encoding obj */
1205
1206        if (p->flush & pdf_flush_content)
1207            pdc_flush_stream(p->out);
1208    }
1209
1210
1211    /*
1212     * CID fonts dictionary
1213     */
1214    if (descendant_id != PDC_BAD_ID)
1215    {
1216        const char *tmpstr;
1217
1218        pdc_begin_obj(p->out, descendant_id);           /* CID font obj */
1219        pdc_begin_dict(p->out);                         /* CID font dict */
1220        pdc_puts(p->out, "/Type/Font\n");
1221
1222        /* /Subtype */
1223        if (font->type == pdc_CIDFontType0)
1224            pdc_puts(p->out, "/Subtype/CIDFontType0\n");
1225        if (font->type == pdc_CIDFontType2)
1226            pdc_puts(p->out, "/Subtype/CIDFontType2\n");
1227
1228        /* /BaseFont */
1229        pdc_puts(p->out, "/BaseFont");
1230        pdc_put_pdfname(p->out, fontname, strlen(fontname));
1231        if (font->style != pdc_Normal)
1232            pdc_printf(p->out, ",%s",
1233                pdc_get_keyword(font->style, pdf_fontstyle_pdfkeys));
1234        pdc_puts(p->out, "\n");
1235
1236        /* /CIDSystemInfo */
1237        tmpstr = pdf_get_ordering_cid(p, font);
1238        pdc_puts(p->out, "/CIDSystemInfo<</Registry");
1239        pdc_put_pdfstring(p->out, Adobe_str, (int) strlen(Adobe_str));
1240        pdc_puts(p->out, "/Ordering");
1241        pdc_put_pdfstring(p->out, tmpstr, (int) strlen(tmpstr));
1242        pdc_printf(p->out, "/Supplement %d>>\n",
1243                   pdf_get_supplement_cid(p, font));
1244
1245        /* /FontDescriptor */
1246        fontdescriptor_id = pdc_alloc_id(p->out);
1247        pdc_printf(p->out, "/FontDescriptor %ld 0 R\n", fontdescriptor_id);
1248
1249        /* /DW /W */
1250#ifdef PDF_CJKFONTWIDTHS_SUPPORTED
1251        if (enc == pdc_cid)
1252            pdf_put_cidglyph_widths(p, font);
1253#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */
1254
1255
1256        pdc_end_dict(p->out);                           /* CID font dict */
1257        pdc_end_obj(p->out);                            /* CID font obj */
1258    }
1259
1260    /*
1261     * FontDescriptor dictionary
1262     */
1263    if (fontdescriptor_id != PDC_BAD_ID)
1264        pdf_write_fontdescriptor(p, font, fontdescriptor_id, fontfile_id);
1265
1266    /*
1267     * Font embedding
1268     */
1269    if (fontfile_id != PDC_BAD_ID)
1270    {
1271        pdc_id    length_id = PDC_BAD_ID;
1272        pdc_id    length1_id = PDC_BAD_ID;
1273        pdc_id    length2_id = PDC_BAD_ID;
1274        pdc_id    length3_id = PDC_BAD_ID;
1275        pdc_bool  hexencode = pdc_false;
1276        pdc_bool  compress = pdc_false;
1277
1278        /* Prepare embedding */
1279        switch(font->type)
1280        {
1281            case pdc_Type1:
1282            case pdc_MMType1:
1283            {
1284                pdf_make_t1src(p, font, &src);
1285                length1_id = pdc_alloc_id(p->out);
1286                length2_id = pdc_alloc_id(p->out);
1287                length3_id = pdc_alloc_id(p->out);
1288            }
1289            break;
1290
1291#ifdef PDF_TRUETYPE_SUPPORTED
1292            case pdc_TrueType:
1293            case pdc_CIDFontType2:
1294            {
1295                length1_id = pdc_alloc_id(p->out);
1296            }
1297            case pdc_Type1C:
1298            case pdc_CIDFontType0:
1299            {
1300                src.private_data = (void *) font->fontfilename;
1301                if (font->fontfilename)
1302                {
1303                    /* Read the font from file */
1304                    src.init = pdf_data_source_file_init;
1305                    src.fill = pdf_data_source_file_fill;
1306                    src.terminate = pdf_data_source_file_terminate;
1307                    switch(font->type)
1308                    {
1309                        case pdc_TrueType:
1310                        case pdc_CIDFontType2:
1311                        src.offset = (long) 0;
1312                        src.length = (long) 0;
1313                        break;
1314
1315                        case pdc_Type1C:
1316                        case pdc_CIDFontType0:
1317                        src.offset = font->cff_offset;
1318                        src.length = (long) font->cff_length;
1319                        break;
1320
1321                        default:
1322                        break;
1323                    }
1324                }
1325                else
1326                {
1327                    /* Read the font from memory */
1328                    src.init = NULL;
1329                    src.fill = pdf_data_source_buf_fill;
1330                    src.terminate = NULL;
1331                    switch(font->type)
1332                    {
1333                        case pdc_TrueType:
1334                        case pdc_CIDFontType2:
1335                        src.buffer_start = font->img;
1336                        src.buffer_length = font->filelen;
1337                        break;
1338
1339                        case pdc_Type1C:
1340                        case pdc_CIDFontType0:
1341                        src.buffer_start = font->img + font->cff_offset;
1342                        src.buffer_length = font->cff_length;
1343                        break;
1344
1345                        default:
1346                        break;
1347                    }
1348                    src.bytes_available = 0;
1349                    src.next_byte = NULL;
1350                }
1351            }
1352            break;
1353#endif /* PDF_TRUETYPE_SUPPORTED */
1354
1355            default:
1356            break;
1357        }
1358
1359        /* Embedded font stream dictionary */
1360        pdc_begin_obj(p->out, fontfile_id);     /* Embedded font stream obj */
1361        pdc_begin_dict(p->out);                 /* Embedded font stream dict */
1362
1363        /* /Length, /Filter */
1364        length_id = pdc_alloc_id(p->out);
1365        pdc_printf(p->out, "/Length %ld 0 R\n", length_id);
1366        switch(font->type)
1367        {
1368            case pdc_Type1:
1369            case pdc_MMType1:
1370            if (p->debug['a'])
1371            {
1372                hexencode = pdc_true;
1373                pdc_puts(p->out, "/Filter/ASCIIHexDecode\n");
1374            }
1375            break;
1376
1377#ifdef PDF_TRUETYPE_SUPPORTED
1378            case pdc_TrueType:
1379            case pdc_CIDFontType2:
1380            case pdc_Type1C:
1381            case pdc_CIDFontType0:
1382            if (font->filelen != 0L)
1383            {
1384                compress = pdc_true;
1385                if (pdc_get_compresslevel(p->out))
1386                    pdc_puts(p->out, "/Filter/FlateDecode\n");
1387            }
1388            break;
1389#endif /* PDF_TRUETYPE_SUPPORTED */
1390
1391            default:
1392            break;
1393        }
1394
1395        /* /Length1, /Length2, Length3 */
1396        if (length1_id != PDC_BAD_ID)
1397            pdc_printf(p->out, "/Length1 %ld 0 R\n", length1_id);
1398        if (length2_id != PDC_BAD_ID)
1399            pdc_printf(p->out, "/Length2 %ld 0 R\n", length2_id);
1400        if (length3_id != PDC_BAD_ID)
1401            pdc_printf(p->out, "/Length3 %ld 0 R\n", length3_id);
1402
1403#ifdef PDF_TRUETYPE_SUPPORTED
1404        /* /Subtype */
1405        if(font->type == pdc_Type1C)
1406            pdc_puts(p->out, "/Subtype/Type1C\n");
1407        if (font->type == pdc_CIDFontType0)
1408            pdc_puts(p->out, "/Subtype/CIDFontType0C\n");
1409#endif /* PDF_TRUETYPE_SUPPORTED */
1410
1411        pdc_end_dict(p->out);                   /* Embedded font stream dict */
1412
1413        /* Stream */
1414        if (hexencode == pdc_true)
1415            pdf_ASCIIHexEncode(p, &src);
1416        else
1417            pdf_copy_stream(p, &src, compress);
1418
1419        pdc_end_obj(p->out);                    /* Embedded font stream obj */
1420
1421        pdc_put_pdfstreamlength(p->out, length_id);
1422
1423        /* Length objects */
1424        switch(font->type)
1425        {
1426            case pdc_Type1:
1427            case pdc_MMType1:
1428            pdf_put_length_objs(p, &src, length1_id, length2_id, length3_id);
1429            break;
1430
1431#ifdef PDF_TRUETYPE_SUPPORTED
1432            case pdc_TrueType:
1433            case pdc_CIDFontType2:
1434            if (compress)
1435            {
1436                pdc_begin_obj(p->out, length1_id);      /* Length1 obj */
1437                pdc_printf(p->out, "%ld\n", (long) font->filelen);
1438                pdc_end_obj(p->out);                    /* Length1 obj */
1439            }
1440            else
1441            {
1442                /* same as /Length */
1443                pdc_put_pdfstreamlength(p->out, length1_id);
1444            }
1445            break;
1446#endif /* PDF_TRUETYPE_SUPPORTED */
1447
1448            default:
1449            break;
1450        }
1451    }
1452
1453    if (p->flush & pdf_flush_content)
1454        pdc_flush_stream(p->out);
1455}
1456
1457void
1458pdf_write_doc_fonts(PDF *p)
1459{
1460    int slot;
1461
1462    /* output pending font objects */
1463    for (slot = 0; slot < p->fonts_number; slot++)
1464    {
1465        switch(p->fonts[slot].type)
1466        {
1467            case pdc_Type1:
1468            case pdc_MMType1:
1469#ifdef PDF_TRUETYPE_SUPPORTED
1470            case pdc_TrueType:
1471            case pdc_CIDFontType2:
1472            case pdc_Type1C:
1473#endif /* PDF_TRUETYPE_SUPPORTED */
1474            case pdc_CIDFontType0:
1475            case pdc_Type3:
1476            pdf_put_font(p, &p->fonts[slot]);
1477            break;
1478
1479            default:
1480            break;
1481        }
1482    }
1483}
1484
1485void
1486pdf_write_page_fonts(PDF *p)
1487{
1488    int i, total = 0;
1489
1490    /* This doesn't really belong here, but all modules which write
1491     * font resources also need this, so we include it here.
1492     * Note that keeping track of ProcSets is considered obsolete
1493     * starting with PDF 1.4, so we always include the full set.
1494     */
1495
1496    pdc_puts(p->out, "/ProcSet[/PDF/ImageB/ImageC/ImageI/Text]\n");
1497
1498    for (i = 0; i < p->fonts_number; i++)
1499        if (p->fonts[i].used_on_current_page == pdc_true)
1500            total++;
1501
1502    if (total > 0)
1503    {
1504        pdc_puts(p->out, "/Font");
1505
1506        pdc_begin_dict(p->out);         /* font resource dict */
1507
1508        for (i = 0; i < p->fonts_number; i++)
1509            if (p->fonts[i].used_on_current_page == pdc_true) {
1510                p->fonts[i].used_on_current_page = pdc_false;   /* reset */
1511                pdc_printf(p->out, "/F%d %ld 0 R\n", i, p->fonts[i].obj_id);
1512            }
1513
1514        pdc_end_dict(p->out);           /* font resource dict */
1515    }
1516}
1517