summaryrefslogtreecommitdiff
path: root/src/pdflib/pdflib/p_font.c
diff options
context:
space:
mode:
authorscuri <scuri>2008-10-17 06:10:33 +0000
committerscuri <scuri>2008-10-17 06:10:33 +0000
commit7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf (patch)
treed0857278bde2eff784227c57dcaf930346ceb7ac /src/pdflib/pdflib/p_font.c
First commit - moving from LuaForge to SourceForge
Diffstat (limited to 'src/pdflib/pdflib/p_font.c')
-rw-r--r--src/pdflib/pdflib/p_font.c2513
1 files changed, 2513 insertions, 0 deletions
diff --git a/src/pdflib/pdflib/p_font.c b/src/pdflib/pdflib/p_font.c
new file mode 100644
index 0000000..5dfce77
--- /dev/null
+++ b/src/pdflib/pdflib/p_font.c
@@ -0,0 +1,2513 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: p_font.c,v 1.1 2008/10/17 06:11:49 scuri Exp $
+ *
+ * PDFlib font handling routines
+ *
+ */
+
+#define P_FONT_C
+
+#include "p_intern.h"
+#include "p_color.h"
+#include "p_defopt.h"
+#include "p_font.h"
+#include "p_tagged.h"
+
+#include "ft_truetype.h"
+
+
+#define PDF_TTC_SEPARATOR ':'
+
+static const pdc_keyconn pdf_fonttype_pdfkeylist[] =
+{
+ {"Type1", fnt_Type1},
+ {"MMType1", fnt_MMType1},
+ {"TrueType", fnt_TrueType},
+ {"Type0", fnt_CIDFontType2},
+ {"Type1", fnt_Type1C},
+ {"Type0", fnt_CIDFontType0},
+ {"Type3", fnt_Type3},
+ {NULL, 0}
+};
+
+typedef enum
+{
+ font_afm = 1,
+ font_pfm = 2,
+ font_ttot = 3,
+ font_pfab = 4
+}
+pdf_fontfile_type;
+
+static const pdc_keyconn pdf_extension_names[] =
+{
+ {".tte", font_ttot},
+ {".ttf", font_ttot},
+ {".otf", font_ttot},
+ {".afm", font_afm},
+ {".pfm", font_pfm},
+ {".ttc", font_ttot},
+ {".TTE", font_ttot},
+ {".TTF", font_ttot},
+ {".OTF", font_ttot},
+ {".AFM", font_afm},
+ {".PFM", font_pfm},
+ {".TTC", font_ttot},
+ {".pfa", font_pfab},
+ {".pfb", font_pfab},
+ {".PFA", font_pfab},
+ {".PFB", font_pfab},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_fontoption_keylist[] =
+{
+ {"fontname", fo_fontname},
+ {"encoding", fo_encoding},
+ {"fontstyle", fo_fontstyle},
+ {"monospace", fo_monospace},
+ {NULL, 0}
+};
+
+
+void
+pdf_init_font(PDF *p, pdf_font *font, pdf_font_options *fo)
+{
+ (void) p;
+
+ /* font metric */
+ fnt_init_font(&font->ft);
+
+ /* font options */
+ font->opt = *fo;
+ font->verbose = fo->fontwarning;
+
+ font->apiname = NULL;
+ font->filename = NULL;
+ font->metricfilename = NULL;
+
+ font->used_in_formfield = pdc_false;
+ font->used_in_current_doc = pdc_false;
+ font->used_on_current_page = pdc_false;
+ font->obj_id = PDC_BAD_ID;
+
+ font->cff_offset = 0;
+ font->cff_length = 0;
+
+ font->t3font = NULL;
+ font->hasoriginal = pdc_false;
+
+ font->encapiname = NULL;
+ font->outcmapname = NULL;
+ font->codepage = 0;
+ font->towinansi = pdc_invalidenc;
+ font->hasnomac = pdc_false;
+ font->passthrough = pdc_false;
+ font->unibyte = pdc_false;
+ font->asciispace = pdc_false;
+ font->issemantic = pdc_false;
+ font->widthsmissing = pdc_false;
+ font->missingglyphs = 0;
+ font->metricflags = 0;
+ font->supplement = 0;
+ font->symenc = pdc_invalidenc;
+ font->replacementchar = -1;
+ font->replacementcode = -1;
+
+ font->codesize = 1;
+ font->lastcode = -1;
+ font->gid0code = -1;
+ font->usedgids = NULL;
+ font->expectglyphs = pdc_false;
+ font->iscidfont = pdc_false;
+
+}
+
+void
+pdf_cleanup_font(PDF *p, pdf_font *font)
+{
+ if (font->ft.imgname)
+ pdc_unlock_pvf(p->pdc, font->ft.imgname);
+
+ /* font metric */
+ fnt_cleanup_font(p->pdc, &font->ft);
+
+ if (font->apiname != NULL)
+ {
+ pdc_free(p->pdc, font->apiname);
+ font->apiname = NULL;
+ }
+
+ if (font->metricfilename != NULL)
+ {
+ pdc_free(p->pdc, font->metricfilename);
+ font->metricfilename = NULL;
+ }
+
+ if (font->encapiname != NULL)
+ {
+ pdc_free(p->pdc, font->encapiname);
+ font->encapiname = NULL;
+ }
+
+ if (font->outcmapname != NULL)
+ {
+ pdc_free(p->pdc, font->outcmapname);
+ font->outcmapname = NULL;
+ }
+
+
+ if (font->usedgids != NULL)
+ {
+ pdc_free(p->pdc, font->usedgids);
+ font->usedgids = NULL;
+ }
+
+ /* Type3 font */
+ if (font->t3font != NULL && font->hasoriginal)
+ {
+ pdf_cleanup_t3font(p, font->t3font);
+ pdc_free(p->pdc, font->t3font);
+ font->t3font = NULL;
+ }
+
+}
+
+void
+pdf_init_fonts(PDF *p)
+{
+ p->fonts = NULL;
+ p->fonts_number = 0;
+ p->fonts_capacity = 0;
+ p->t3slot = -1;
+
+
+ pdc_init_encoding_info_ids(p->pdc);
+}
+
+void
+pdf_cleanup_fonts(PDF *p)
+{
+ int slot;
+
+ if (p->fonts != NULL)
+ {
+ for (slot = 0; slot < p->fonts_number; slot++)
+ pdf_cleanup_font(p, &p->fonts[slot]);
+
+ pdc_free(p->pdc, p->fonts);
+ p->fonts = NULL;
+ }
+
+}
+
+int
+pdf_insert_font(PDF *p, pdf_font *font)
+{
+ static const char fn[] = "pdf_insert_font";
+ int slot = p->fonts_number;
+
+ /* insert font */
+ if (p->fonts_number == p->fonts_capacity)
+ {
+ if (p->fonts_capacity == 0)
+ {
+ p->fonts_capacity = FONTS_CHUNKSIZE;
+ p->fonts = (pdf_font *) pdc_calloc(p->pdc,
+ sizeof(pdf_font) * p->fonts_capacity, fn);
+ }
+ else
+ {
+ p->fonts_capacity *= 2;
+ p->fonts = (pdf_font *) pdc_realloc(p->pdc, p->fonts,
+ sizeof(pdf_font) * p->fonts_capacity, fn);
+ }
+ }
+ p->fonts[slot] = *font;
+
+ p->fonts_number++;
+
+ return slot;
+}
+
+
+const char *
+pdf_get_pdf_fontname(pdf_font *font)
+{
+ const char *fontname;
+
+ fontname = fnt_get_abb_std_fontname(font->ft.name);
+ if (fontname == NULL)
+ fontname = fnt_get_abb_cjk_fontname(font->ft.name);
+ if (fontname == NULL)
+ fontname = font->ft.name;
+
+ return (const char *) fontname;
+}
+
+const char *
+pdf_get_encoding_name(PDF *p, pdc_encoding enc, pdf_font *font)
+{
+ const char *apiname = pdc_get_fixed_encoding_name(enc);
+ if (!apiname[0] && enc >= 0)
+ {
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ apiname = (const char *) ev->apiname;
+ }
+ else if (enc == pdc_cid && font != NULL && font->outcmapname != NULL)
+ apiname = (const char *) font->outcmapname;
+ return apiname;
+}
+
+char *
+pdf_get_encoding_adaptname(PDF *p, pdc_encoding enc, pdf_font *font,
+ const char *fontname)
+{
+ static const char *fn = "pdf_get_encoding_adaptname";
+ char *encname = (char *) pdf_get_encoding_name(p, enc, font);
+ char *adaptname = NULL;
+ size_t len;
+
+ len = strlen(encname) + 1 + strlen(fontname) + 1;
+ adaptname = (char *) pdc_malloc_tmp(p->pdc, len, fn, 0, 0);
+ strcpy(adaptname, encname);
+ strcat(adaptname, PDC_ENC_MODSEPAR);
+ strcat(adaptname, fontname);
+
+ return adaptname;
+}
+
+pdc_encodingvector *
+pdf_create_font_encoding(PDF *p, pdc_encoding enc, pdf_font *font,
+ const char *fontname, pdc_bool kreg)
+{
+ pdc_encodingvector *ev = NULL;
+ char *adaptname = NULL;
+
+ adaptname = pdf_get_encoding_adaptname(p, enc, font, fontname);
+
+ /* search for a registered encoding */
+ enc = pdc_find_encoding(p->pdc, adaptname);
+ if (enc != pdc_invalidenc)
+ {
+ font->ft.enc = enc;
+ }
+ else
+ {
+ /* create a font encoding */
+ ev = pdc_new_encoding(p->pdc, adaptname);
+ ev->flags |= PDC_ENC_FONT;
+ ev->flags |= PDC_ENC_SETNAMES;
+
+ if (kreg)
+ {
+ enc = pdc_insert_encoding_vector(p->pdc, ev);
+ font->ft.enc = enc;
+ }
+ }
+
+ pdc_free_tmp(p->pdc, adaptname);
+
+ return ev;
+}
+
+const char *
+pdf_get_font_char_option(PDF *p, pdf_font_optflags fflags)
+{
+ pdf_text_options *to = p->curr_ppt->currto;
+ pdf_font *currfont;
+
+ if (p->fonts_number == 0 || to->font == -1)
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR,
+ pdc_get_keyword(fflags, pdf_fontoption_keylist), 0, 0, 0);
+ currfont = &p->fonts[to->font];
+
+ switch (fflags)
+ {
+ case fo_fontname:
+ return (const char *) currfont->ft.name;
+
+ case fo_encoding:
+ return pdf_get_encoding_name(p, currfont->ft.enc, currfont);
+
+ case fo_fontstyle:
+ return pdc_get_keyword(currfont->opt.fontstyle,
+ pdf_fontstyle_pdfkeylist);
+
+ default:
+ return NULL;
+ }
+}
+
+double
+pdf_get_font_float_option(PDF *p, pdf_font_optflags fflags)
+{
+ pdf_text_options *to = p->curr_ppt->currto;
+ pdf_font *currfont;
+
+ if (p->fonts_number == 0 || to->font == -1)
+ pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR,
+ pdc_get_keyword(fflags, pdf_fontoption_keylist), 0, 0, 0);
+ currfont = &p->fonts[to->font];
+
+ switch (fflags)
+ {
+ case fo_monospace:
+ return (double) currfont->opt.monospace;
+
+ default:
+ return 0;
+ }
+}
+
+static const pdc_keyconn pdf_courier_keylist[] =
+{
+ {"Courier", fnt_Normal},
+ {"Courier-Bold", fnt_Bold},
+ {"Courier-Oblique", fnt_Italic},
+ {"Courier-BoldOblique", fnt_BoldItalic},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_helvetica_keylist[] =
+{
+ {"Helvetica", fnt_Normal},
+ {"Helvetica-Bold", fnt_Bold},
+ {"Helvetica-Oblique", fnt_Italic},
+ {"Helvetica-BoldOblique", fnt_BoldItalic},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_times_keylist[] =
+{
+ {"Times-Roman", fnt_Normal},
+ {"Times-Bold", fnt_Bold},
+ {"Times-Italic", fnt_Italic},
+ {"Times-BoldItalic", fnt_BoldItalic},
+ {NULL, 0}
+};
+
+static const char *
+pdf_get_fontname_core(pdf_font *font, const char *fontname, pdc_bool checktimes)
+{
+ const char *fname = NULL;
+
+ /* font style for core fonts */
+ if (font->opt.fontstyle != fnt_Normal)
+ {
+ if (!strcmp(fontname, "Courier"))
+ fname = pdc_get_keyword(font->opt.fontstyle, pdf_courier_keylist);
+ else if (!strcmp(fontname, "Helvetica"))
+ fname = pdc_get_keyword(font->opt.fontstyle, pdf_helvetica_keylist);
+ else if (!strcmp(fontname, "Times-Roman"))
+ fname = pdc_get_keyword(font->opt.fontstyle, pdf_times_keylist);
+ }
+
+ if (checktimes)
+ {
+ if (!strcmp(fontname, "Times"))
+ fname = pdc_get_keyword(font->opt.fontstyle, pdf_times_keylist);
+ }
+
+ return fname;
+}
+
+static pdc_bool
+pdf_get_metrics_core(PDF *p, pdf_font *font, const char *fontname,
+ pdc_encoding enc, pdc_bool checktimes)
+{
+ const char *fname = NULL;
+ const fnt_font_metric *ftm;
+
+ fname = pdf_get_fontname_core(font, fontname, checktimes);
+ if (fname != NULL)
+ {
+ fontname = fname;
+ font->opt.fontstyle = fnt_Normal;
+ }
+
+ ftm = fnt_get_core_metric(fontname);
+ if (ftm != NULL)
+ {
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tLoading metrics data for core font \"%s\":\n", fontname);
+
+ /* Fill up the font struct */
+ fnt_fill_font_metric(p->pdc, &font->ft,
+ pdc_false,
+ ftm);
+ font->ft.enc = enc;
+
+ /* all new glyph names of AGL 2.0 are missing */
+ font->missingglyphs = 0xFFFFFFFF;
+
+ /* Process metrics data */
+ if (pdf_process_metrics_data(p, font, fontname))
+ {
+ if (pdf_make_fontflag(p, font))
+ {
+ if (!font->opt.monospace)
+ return pdc_true;
+ else
+ pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace",
+ 0, 0, 0);
+ }
+ }
+
+ return pdc_false;
+ }
+
+ return pdc_undef;
+}
+
+void
+pdf_font_set_missvalues(PDF *p, pdf_font *font)
+{
+ pdf_font_options *fo = &font->opt;
+ fnt_font_metric *ftm = &font->ft.m;
+
+ (void) p;
+
+ if (ftm->descender > 0)
+ ftm->descender = -(ftm->descender);
+
+ if (fo->mask & (1L << fo_ascender))
+ {
+ font->metricflags |= font_ascender;
+ ftm->ascender = fo->ascender;
+ }
+ else if (ftm->ascender <= 0)
+ {
+ font->metricflags |= font_ascender;
+ ftm->ascender = 720;
+ }
+
+ if (fo->mask & (1L << fo_descender))
+ {
+ font->metricflags |= font_descender;
+ ftm->descender = fo->descender;
+ }
+ else if (ftm->descender == FNT_MISSING_FONTVAL)
+ {
+ font->metricflags |= font_descender;
+ ftm->descender = (int) PDC_ROUND(-0.25 * ftm->ascender);
+ }
+
+ if (fo->mask & (1L << fo_capheight))
+ {
+ font->metricflags |= font_capheight;
+ ftm->capHeight = fo->capheight;
+ }
+ else if (ftm->capHeight <= 0)
+ {
+ font->metricflags |= font_capheight;
+ ftm->capHeight = (int) PDC_ROUND(0.93 * ftm->ascender);
+ }
+
+ if (fo->mask & (1L << fo_xheight))
+ {
+ font->metricflags |= font_xheight;
+ ftm->xHeight = fo->xheight;
+ }
+ else if (ftm->xHeight <= 0)
+ {
+ font->metricflags |= font_xheight;
+ ftm->xHeight = (int) PDC_ROUND(0.66 * ftm->ascender);
+ }
+
+ if (fo->mask & (1L << fo_linegap))
+ {
+ font->metricflags |= font_linegap;
+ font->ft.linegap = fo->linegap;
+ }
+ else if (font->ft.linegap == FNT_MISSING_FONTVAL)
+ {
+ font->metricflags |= font_linegap;
+ font->ft.linegap = (int) PDC_ROUND(0.23 * ftm->ascender);
+ }
+
+ if (ftm->llx == FNT_MISSING_FONTVAL)
+ ftm->llx = -50;
+ if (ftm->lly == FNT_MISSING_FONTVAL)
+ ftm->lly = ftm->descender;
+ if (ftm->urx == FNT_MISSING_FONTVAL)
+ ftm->urx = 1000;
+ if (ftm->ury == FNT_MISSING_FONTVAL)
+ ftm->ury = ftm->ascender;
+
+ /* try to fix broken entries */
+ if (ftm->lly > ftm->ury)
+ ftm->ury = ftm->lly + ftm->ascender;
+ if (ftm->llx > ftm->urx)
+ ftm->urx = ftm->llx + 1000;
+}
+
+pdc_bool
+pdf_font_get_is_faked(pdf_font *font, pdf_font_values flag)
+{
+ return (font->metricflags & flag) ? pdc_true : pdc_false;
+}
+
+double
+pdf_font_get_metric_value(int value)
+{
+ return (double) value / 1000.0;
+}
+
+
+/* --------------------------- font processing ---------------------------- */
+
+pdc_bool
+pdf_make_fontflag(PDF *p, pdf_font *font)
+{
+ int errcode = 0;
+
+ if (font->ft.m.type != fnt_Type3)
+ {
+ if (font->ft.m.isFixedPitch)
+ font->ft.m.flags |= FNT_FIXEDWIDTH;
+
+ if (font->ft.issymbfont == pdc_false ||
+ font->ft.enc == pdc_winansi ||
+ font->ft.enc == pdc_macroman ||
+ font->ft.enc == pdc_ebcdic ||
+ font->ft.enc == pdc_ebcdic_37 ||
+ font->ft.enc == pdc_ebcdic_winansi)
+ font->ft.m.flags |= FNT_ADOBESTANDARD;
+ else
+ font->ft.m.flags |= FNT_SYMBOL;
+
+ if (font->ft.m.italicAngle < 0 ||
+ font->opt.fontstyle == fnt_Italic ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ font->ft.m.flags |= FNT_ITALIC;
+ if (font->ft.m.italicAngle == 0 &&
+ font->ft.m.flags & FNT_ITALIC)
+ font->ft.m.italicAngle = FNT_DEF_ITALICANGLE;
+
+ /* heuristic to identify (small) caps fonts */
+ if (font->ft.name &&
+ (strstr(font->ft.name, "Caps") ||
+ !strcmp(font->ft.name + strlen(font->ft.name) - 2, "SC")))
+ font->ft.m.flags |= FNT_SMALLCAPS;
+
+ if (font->opt.fontstyle == fnt_Bold ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ font->ft.weight = FNT_FW_BOLD;
+
+ if (strstr(font->ft.name, "Bold") ||
+ font->ft.weight >= FNT_FW_BOLD)
+ font->ft.m.flags |= FNT_FORCEBOLD;
+
+ /* determine values for FontWeight to StemV */
+ if (font->ft.m.StdVW == 0)
+ font->ft.m.StdVW = fnt_weight2stemv(font->ft.weight);
+ else if (font->ft.weight == 0)
+ font->ft.weight = fnt_stemv2weight(font->ft.m.StdVW);
+ }
+
+ fnt_font_logg_protocol(p->pdc, &font->ft);
+
+ switch(font->ft.m.type)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ case fnt_Type3:
+ if (font->opt.fontstyle == fnt_Bold ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ {
+ font->metricflags |= font_bold;
+ }
+
+ if (font->opt.fontstyle == fnt_Italic ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ {
+ font->metricflags |= font_italic;
+ }
+
+ break;
+
+ default:
+ if (font->opt.embedding)
+ {
+ if (font->opt.fontstyle == fnt_Bold ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ {
+ font->metricflags |= font_bold;
+ }
+
+ if (font->opt.fontstyle == fnt_Italic ||
+ font->opt.fontstyle == fnt_BoldItalic)
+ {
+ font->metricflags |= font_italic;
+ }
+ }
+ break;
+ }
+
+
+ return errcode ? pdc_false : pdc_true;
+}
+
+int
+pdf_get_code_or_glyphid(PDF *p, pdf_font *font, pdc_encodingvector *ev,
+ pdc_ushort uv)
+{
+ if (ev != NULL)
+ {
+ int code = pdc_get_encoding_bytecode(p->pdc, ev, uv);
+
+ if (code >= 0)
+ {
+ if (fnt_get_glyphid(code, &font->ft) <= 0)
+ code = 0;
+ }
+ return code;
+ }
+
+ return fnt_get_glyphid((int) uv, &font->ft);
+}
+
+void
+pdf_set_replchar(PDF *p, pdf_font *font)
+{
+ pdc_encoding enc = font->ft.enc;
+
+ switch (enc)
+ {
+ case pdc_glyphid:
+ case pdc_cid:
+ return;
+
+ case pdc_builtin:
+ font->replacementcode = 0;
+ return;
+
+ case pdc_unicode:
+ default:
+ {
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ pdc_ushort uv = 0;
+ int cg = 0;
+ uv = PDC_UNICODE_NBSP;
+ cg = pdf_get_code_or_glyphid(p, font, ev, uv);
+ if (cg <= 0)
+ {
+ uv = PDC_UNICODE_SPACE;
+ cg = pdf_get_code_or_glyphid(p, font, ev, uv);
+ if (cg <= 0)
+ {
+ uv = 0;
+ cg = 0;
+ }
+ }
+
+ font->replacementchar = (int) uv;
+ font->replacementcode = cg;
+ }
+ return;
+ }
+}
+
+void
+pdf_font_issemantic(PDF *p, pdf_font *font)
+{
+ pdc_encoding enc = font->ft.enc;
+ pdc_ushort spacechar = 0;
+
+ /* Flag: encoding with ASCII space for wordspacing */
+ if (enc >= 0)
+ {
+ pdc_encodingvector *ev = pdc_get_encoding_vector(p->pdc, enc);
+ int i;
+
+ ev->flags |= PDC_ENC_USED;
+ i = pdc_get_encoding_bytecode(p->pdc, ev, PDC_UNICODE_SPACE);
+ if (i > -1)
+ {
+ spacechar = (pdc_ushort) i;
+ if (spacechar == PDC_UNICODE_SPACE)
+ font->asciispace = pdc_true;
+ }
+ }
+
+ /* Flag: encoding is Unicode interpretable */
+ if ((enc >= 0) ||
+ (enc == pdc_cid && font->codesize == 2) ||
+ (enc == pdc_unicode))
+ font->issemantic = pdc_true;
+
+ /* determine code of space character */
+ switch(enc)
+ {
+ case pdc_cid:
+ if (font->codesize == 2)
+ font->ft.spacechar = PDC_UNICODE_SPACE;
+ break;
+
+ case pdc_unicode:
+ font->ft.spacechar = PDC_UNICODE_SPACE;
+ break;
+
+ case pdc_glyphid:
+ font->ft.spacechar =
+ (pdc_ushort) MAX(fnt_get_glyphid(PDC_UNICODE_SPACE, &font->ft), 0);
+ break;
+
+ default:
+ font->ft.spacechar = spacechar;
+ break;
+ }
+}
+
+/* definitions of font options */
+static const pdc_defopt pdf_load_font_options[] =
+{
+ PDF_FONT_OPTIONS2
+ PDF_FONT_OPTIONS3
+ PDF_ERRORPOLICY_OPTION
+ PDC_OPT_TERMINATE
+};
+
+void
+pdf_init_font_options(PDF *p, pdf_font_options *fo)
+{
+ static const char fn[] = "pdf_init_font_options";
+
+ if (fo == NULL)
+ {
+ p->currfo = (pdf_font_options *) pdc_malloc(p->pdc,
+ sizeof(pdf_font_options), fn);
+
+
+ fo = p->currfo;
+ }
+ else
+ {
+ }
+
+
+ fo->embedding = pdc_false; /* default true if CID custom font */
+ fo->encoding = NULL;
+ fo->flags = 0;
+ fo->fontname = NULL;
+ fo->fontstyle = fnt_Normal;
+ fo->fontwarning = p->debug[(int) 'F'];
+ fo->fontwarning = pdf_get_errorpolicy(p, NULL, fo->fontwarning);
+ fo->mask = 0;
+ fo->monospace = 0;
+ fo->ascender = 0;
+ fo->descender = 0;
+ fo->capheight = 0;
+ fo->xheight = 0;
+ fo->linegap = 0;
+ fo->auxiliary = pdc_false;
+
+}
+
+void
+pdf_cleanup_font_curroptions(PDF *p)
+{
+ if (p->currfo)
+ {
+ pdc_free(p->pdc, p->currfo);
+ p->currfo = NULL;
+ }
+}
+
+void
+pdf_cleanup_font_options(PDF *p, pdf_font_options *fo)
+{
+ if (fo->fontname != NULL)
+ {
+ pdc_free(p->pdc, fo->fontname);
+ fo->fontname = NULL;
+ }
+
+ if (fo->encoding != NULL)
+ {
+ pdc_free(p->pdc, fo->encoding);
+ fo->encoding = NULL;
+ }
+}
+
+void
+pdf_parse_font_options(PDF *p, const char *optlist)
+{
+ pdc_resopt *resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_load_font_options, NULL, pdc_true);
+
+ pdf_get_font_options(p, p->currfo, resopts);
+ pdc_cleanup_optionlist(p->pdc, resopts);
+}
+
+void
+pdf_get_font_options(PDF *p, pdf_font_options *fo, pdc_resopt *resopts)
+{
+ int inum;
+
+ (void) p;
+
+ if (fo->flags & is_block ||
+ fo->flags & is_textline ||
+ fo->flags & is_textflow)
+ {
+ if (pdc_get_optvalues("fontname", resopts, NULL, NULL))
+ {
+ fo->fontname = (char *)pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ fo->mask |= (1L << fo_fontname);
+ }
+
+ if (pdc_get_optvalues("encoding", resopts, NULL, NULL))
+ {
+ fo->encoding = (char *)pdc_save_lastopt(resopts, PDC_OPT_SAVE1ELEM);
+ fo->mask |= (1L << fo_encoding);
+ }
+ }
+
+ if (pdc_get_optvalues("fontwarning", resopts, &fo->fontwarning, NULL))
+ fo->mask |= (1L << fo_fontwarning);
+ fo->fontwarning = pdf_get_errorpolicy(p, resopts, fo->fontwarning);
+
+ if (pdc_get_optvalues("embedding", resopts, &fo->embedding, NULL))
+ fo->mask |= (1L << fo_embedding);
+
+
+ if (pdc_get_optvalues("fontstyle", resopts, &inum, NULL))
+ {
+ fo->fontstyle = (fnt_fontstyle) inum;
+ fo->mask |= (1L << fo_fontstyle);
+ }
+
+ if (pdc_get_optvalues("monospace", resopts, &fo->monospace, NULL))
+ fo->mask |= (1L << fo_monospace);
+
+ if (pdc_get_optvalues("ascender", resopts, &fo->ascender, NULL))
+ fo->mask |= (1L << fo_ascender);
+
+ if (pdc_get_optvalues("descender", resopts, &fo->descender, NULL))
+ fo->mask |= (1L << fo_descender);
+
+ if (pdc_get_optvalues("capheight", resopts, &fo->capheight, NULL))
+ fo->mask |= (1L << fo_capheight);
+
+ if (pdc_get_optvalues("xheight", resopts, &fo->xheight, NULL))
+ fo->mask |= (1L << fo_xheight);
+
+ if (pdc_get_optvalues("linegap", resopts, &fo->linegap, NULL))
+ fo->mask |= (1L << fo_linegap);
+
+}
+
+int
+pdf__load_font(PDF *p, const char *fontname, int inlen,
+ const char *encoding, const char *optlist)
+{
+ int slot;
+ pdf_font_options fo;
+
+ if (encoding == NULL || *encoding == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "encoding", 0, 0, 0);
+
+ if (fontname == NULL)
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
+
+ /* initialize */
+ pdf_init_font_options(p, &fo);
+
+ /* Converting fontname */
+ fo.fontname = (char *) pdf_convert_name(p, fontname, inlen,
+ PDC_CONV_WITHBOM);
+ if (fo.fontname == NULL || *fo.fontname == '\0')
+ pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
+
+ /* encoding */
+ fo.encoding = (char *) pdc_strdup(p->pdc, encoding);
+
+ /* parsing option list */
+ if (optlist && strlen(optlist))
+ {
+ pdc_resopt *resopts;
+ pdc_clientdata data;
+
+ pdf_set_clientdata(p, &data);
+ resopts = pdc_parse_optionlist(p->pdc, optlist,
+ pdf_load_font_options, &data, pdc_true);
+ if (!resopts)
+ {
+ pdf_cleanup_font_options(p, &fo);
+ return -1;
+ }
+
+ pdf_get_font_options(p, &fo, resopts);
+ pdc_cleanup_optionlist(p->pdc, resopts);
+ }
+
+ slot = pdf_load_font_internal(p, &fo);
+ return slot;
+}
+
+static void
+pdf_check_font_identical(PDF *p, pdf_font *font, int *slot)
+{
+ pdf_font *oldfont = &p->fonts[*slot];
+ const char *optname = NULL;
+
+ if (!oldfont->opt.embedding && font->opt.embedding)
+ {
+ optname = "embedding";
+ if (p->errorpolicy == errpol_legacy)
+ {
+ pdc_warning(p->pdc, PDF_E_FONT_NOTFULFILL, optname, optname,
+ 0, 0);
+ }
+ else
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_NOTFULFILL, optname, optname,
+ 0, 0);
+ *slot = -1;
+ }
+ }
+
+}
+
+pdc_bool
+pdf_check_font_embedding(PDF *p, pdf_font *font, const char *fontname)
+{
+ (void) p;
+ (void) font;
+ (void) fontname;
+
+
+
+ return pdc_true;
+}
+
+int
+pdf_load_font_internal(PDF *p, pdf_font_options *fo)
+{
+ pdc_bool logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_font);
+ const char *fontname;
+ const char *encoding;
+ const char *encoding_aux;
+ pdc_encoding enc = pdc_invalidenc;
+ pdf_font tmpfont, *font;
+ const char *filename = NULL;
+ const char *extension = NULL;
+ const char *outfilename = NULL;
+ char *fontname_p = NULL;
+ char testfilename[PDF_MAX_FONTNAME + 5];
+ char *sf, *mmparam, mastername[PDF_MAX_FONTNAME + 1];
+ char ittc;
+ size_t len;
+ pdc_bool retval = pdc_false;
+ int slot = -1, i;
+
+ /* host or UTF-8 encoded font name without BOM */
+ fontname_p = pdc_utf8_to_hostbytes(p->pdc, pdc_false, fo->fontname);
+ if (fontname_p == NULL)
+ {
+ fontname = pdc_utf8strprint(p->pdc, fo->fontname);
+ }
+ else
+ {
+ fontname = pdc_utf8strprint(p->pdc, fontname_p);
+ pdc_free(p->pdc, fontname_p);
+ }
+ fontname_p = NULL;
+
+ /* font encoding */
+ encoding = fo->encoding;
+ encoding_aux = encoding;
+
+ /* initialize font struct */
+ font = &tmpfont;
+ pdf_init_font(p, font, fo);
+
+ /* error message prefix */
+ pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX, fontname, encoding, 0, 0);
+
+
+
+
+ /* API font name */
+ font->apiname = pdc_strdup(p->pdc, fontname);
+
+ /* UTF-8 font name with BOM */
+ font->ft.utf8name = pdc_strdup(p->pdc, fo->fontname);
+
+ pdc_logg_cond(p->pdc, 1, trc_font, "\tFont UTF-8 name: \"%s\"\n",
+ font->ft.utf8name);
+
+ /* specified encoding name */
+ font->encapiname = pdc_strdup(p->pdc, encoding);
+
+ /* search for a registered encoding */
+ enc = pdc_find_encoding(p->pdc, encoding);
+ if (enc == pdc_invalidenc || enc == pdc_unicode)
+ {
+ /* search for a predefined CMap and registered fonts */
+ if (!pdf_handle_cidfont(p, fontname, encoding, enc, font, &slot, &enc))
+ goto PDF_PREMATURE_EXIT;
+
+ if (enc == pdc_invalidenc)
+ {
+ /* search for a new encoding */
+ enc = pdc_insert_encoding(p->pdc, encoding, &font->codepage,
+ font->verbose);
+ if (enc == pdc_invalidenc)
+ goto PDF_PREMATURE_EXIT;
+ }
+ else if (enc == pdc_cid)
+ {
+ if (slot == -1)
+ goto PDF_NEWFONT_EXIT;
+ else
+ goto PDF_PREMATURE_EXIT;
+ }
+ else if (enc == pdc_glyphid)
+ {
+ encoding_aux = "glyphid";
+ }
+ else if (enc == pdc_unicode)
+ {
+ encoding_aux = "unicode";
+ }
+ }
+
+ if (pdc_strcmp(font->encapiname, encoding))
+ {
+ pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX2,
+ fontname, font->encapiname, encoding, 0);
+ }
+ encoding = encoding_aux;
+
+ encoding = pdc_get_user_encoding(p->pdc, enc);
+ pdc_logg_cond(p->pdc, 1, trc_encoding, "\tFont encoding: \"%s\"\n",
+ encoding);
+
+ if (enc == pdc_unicode || enc == pdc_glyphid)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ /*
+ * Look whether font is already in the cache.
+ * Look first for the auxiliary font (obj_id == -1).
+ * If a font with same encoding and same relevant options is found,
+ * return its handle.
+ * If a Type 3 font with the same name but different encoding
+ * is found, make a copy in a new slot and attach the requested encoding.
+ */
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tFont will be searched in the PDFlib font cache\n");
+ for (slot = 0; slot < p->fonts_number; slot++)
+ {
+ if (p->fonts[slot].obj_id == PDC_BAD_ID &&
+ p->fonts[slot].ft.m.type != fnt_Type3)
+ {
+ if (font->opt.auxiliary)
+ goto PDF_PREMATURE_EXIT;
+ }
+ else if (!font->opt.auxiliary &&
+ !pdc_strcmp(p->fonts[slot].apiname, fontname) &&
+ p->fonts[slot].opt.fontstyle == font->opt.fontstyle)
+ {
+ if (p->fonts[slot].ft.m.type == fnt_Type3)
+ {
+ if (logg2)
+ pdc_logg(p->pdc, "\t\tType3 font [%d] found\n", slot);
+
+ if (enc < pdc_winansi && enc != pdc_unicode)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0);
+
+ slot = -1;
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ if (p->fonts[slot].ft.enc != enc)
+ {
+ if (!pdf_handle_t3font(p, fontname, enc, font, &slot))
+ {
+ slot = -1;
+ goto PDF_PREMATURE_EXIT;
+ }
+ if (slot > -1)
+ font = &p->fonts[slot];
+ goto PDF_NEWFONT_EXIT;
+ }
+
+ goto PDF_PREMATURE_EXIT;
+ }
+ else if (p->fonts[slot].opt.monospace == font->opt.monospace
+ )
+ {
+ if (p->fonts[slot].ft.enc == enc &&
+ p->fonts[slot].codepage == font->codepage)
+ {
+ if (logg2)
+ pdc_logg(p->pdc,
+ "\t\tfont [%d] with same encoding found\n",
+ slot);
+
+ pdf_check_font_identical(p, font, &slot);
+ goto PDF_PREMATURE_EXIT;
+ }
+ else
+ {
+ char *adaptname;
+ int kc;
+
+ /* Comparing apiname of encoding */
+ if (!pdc_stricmp(font->encapiname,
+ p->fonts[slot].encapiname) &&
+ !pdc_stricmp(font->ft.cmapname,
+ p->fonts[slot].ft.cmapname))
+ {
+ if (logg2)
+ pdc_logg(p->pdc,
+ "\t\tfont [%d] with same encoding "
+ "apiname '%s' found\n", slot, encoding);
+
+ pdf_check_font_identical(p, font, &slot);
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ /* Name of adapted to font encoding */
+ adaptname =
+ pdf_get_encoding_adaptname(p, enc, font, fontname);
+ kc = strcmp(adaptname, pdf_get_encoding_name(p,
+ p->fonts[slot].ft.enc, &p->fonts[slot]));
+ if (!kc)
+ {
+ if (logg2)
+ pdc_logg(p->pdc,
+ "\t\tfont [%d] with same internal "
+ "encoding name '%s' found\n",
+ slot, adaptname);
+ pdc_free_tmp(p->pdc, adaptname);
+
+ pdf_check_font_identical(p, font, &slot);
+ goto PDF_PREMATURE_EXIT;
+ }
+ pdc_free_tmp(p->pdc, adaptname);
+ }
+ }
+ }
+ else if (!font->opt.auxiliary &&
+ p->fonts[slot].ft.m.type == fnt_Type1 &&
+ p->fonts[slot].ft.isstdfont && p->fonts[slot].ft.enc == enc)
+ {
+ /* different core font specifications */
+ const char *fname = pdf_get_fontname_core(font, fontname, pdc_true);
+
+ if ((fname != NULL && !strcmp(fname, p->fonts[slot].ft.name) &&
+ p->fonts[slot].opt.fontstyle == fnt_Normal) ||
+ (!strcmp(fontname, p->fonts[slot].ft.name) &&
+ p->fonts[slot].opt.fontstyle == font->opt.fontstyle))
+ {
+ if (logg2)
+ pdc_logg(p->pdc,
+ "\t\tfont [%d] with same font style '%s' found\n",
+ slot, pdc_get_keyword(font->opt.fontstyle,
+ pdf_fontstyle_pdfkeylist));
+
+ pdf_check_font_identical(p, font, &slot);
+ goto PDF_PREMATURE_EXIT;
+ }
+ }
+ }
+
+ slot = -1;
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tFont not found in the PDFlib font cache\n");
+
+ /* embedding check */
+ if (!pdf_check_font_embedding(p, font, fontname))
+ {
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ /* Multiple Master handling:
+ * - strip MM parameters to build the master name
+ * - the master name is used to find the metrics
+ * - the instance name (client-supplied font name) is used in all places
+ * - although the master name is used for finding the metrics, the
+ * instance name is stored in the font struct.
+ */
+
+ len = strlen(fontname);
+ if (len > PDF_MAX_FONTNAME)
+ {
+ pdc_set_errmsg(p->pdc, FNT_E_FONT_NAMETOOLONG,
+ pdc_errprintf(p->pdc, "%d", PDF_MAX_FONTNAME), 0, 0, 0);
+ goto PDF_PREMATURE_EXIT;
+ }
+ strcpy(mastername, fontname);
+
+ /* A Multiple Master font was requested */
+ if ((mmparam = strstr(mastername, "MM_")) != NULL)
+ {
+ if (font->opt.embedding)
+ {
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDMM, 0, 0, 0, 0);
+ goto PDF_PREMATURE_EXIT;
+ }
+ mmparam[2] = '\0'; /* strip the parameter from the master name */
+ }
+
+ /* Font for vertical writing mode */
+ fontname_p = mastername;
+ if (mastername[0] == '@')
+ {
+ font->ft.vertical = pdc_true;
+ fontname_p = &mastername[1];
+ }
+
+ /* protocol */
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tPDFlib font name: \"%s\"\n", fontname_p);
+
+ /* Font file search hierarchy
+ * - Check "FontOutline" resource entry and check TrueType font
+ * - Check "FontAFM" resource entry
+ * - Check "FontPFM" resource entry
+ * - Check "HostFont" resource entry
+ * - Check available in-core metrics
+ * - Check host font
+ */
+ retval = pdc_false;
+ while (1)
+ {
+#ifdef PDF_TRUETYPE_SUPPORTED
+ /* Check specified TrueType file */
+ filename = pdc_find_resource(p->pdc, "FontOutline", fontname_p);
+ if (!filename)
+ {
+ /* check for TTC font names with index */
+ ittc = PDF_TTC_SEPARATOR;
+ sf = strrchr(fontname_p, ittc);
+
+ if (sf != NULL)
+ {
+ *sf = 0;
+ filename = pdc_find_resource(p->pdc, "FontOutline", fontname_p);
+ *sf = ittc;
+ }
+ }
+ if (filename)
+ {
+ outfilename = filename;
+ retval = fnt_check_tt_font(p->pdc, filename, fontname_p, &font->ft,
+ pdc_false);
+ if (retval == pdc_true)
+ {
+ retval = pdf_get_metrics_tt(p, font, fontname_p, enc, filename);
+ break;
+ }
+ else if (retval == pdc_undef &&
+ pdc_get_errnum(p->pdc) == PDC_E_IO_RDOPEN_NF)
+ {
+ /* file must be exist */
+ retval = pdc_false;
+ }
+ if (retval == pdc_false)
+ break;
+ }
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ /* Check specified AFM file */
+ filename = pdc_find_resource(p->pdc, "FontAFM", fontname_p);
+ if (filename)
+ {
+ retval = pdf_get_metrics_afm(p, font, fontname_p, enc, filename,
+ pdc_true);
+ break;
+ }
+
+ /* Check specified PFM file */
+ filename = pdc_find_resource(p->pdc, "FontPFM", fontname_p);
+ if (filename)
+ {
+ retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, filename,
+ pdc_true);
+ break;
+ }
+
+
+
+ /* Check available in-core metrics */
+ retval = pdf_get_metrics_core(p, font, fontname_p, enc, pdc_false);
+ if (retval != pdc_undef)
+ break;
+ retval = pdc_false;
+
+
+ /* Check available in-core metrics */
+ retval = pdf_get_metrics_core(p, font, fontname_p, enc, pdc_true);
+ if (retval != pdc_undef)
+ break;
+ retval = pdc_false;
+
+ /* Searching for a metric file */
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tSearching for font metrics data file:\n");
+
+ filename = testfilename;
+ for (i = 0; i < 100; i++)
+ {
+ extension = pdf_extension_names[i].word;
+ if (!extension)
+ break;
+
+ strcpy(testfilename, fontname_p);
+ sf = strrchr(testfilename, PDF_TTC_SEPARATOR);
+ if (sf != NULL)
+ *sf = 0;
+ strcat(testfilename, extension);
+
+ switch (pdf_extension_names[i].code)
+ {
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case font_ttot:
+ retval = fnt_check_tt_font(p->pdc, filename, fontname_p,
+ &font->ft, pdc_false);
+ if (retval == pdc_true)
+ retval = pdf_get_metrics_tt(p, font, fontname_p, enc,
+ filename);
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ case font_afm:
+ retval = pdf_get_metrics_afm(p, font, fontname_p, enc,
+ filename, pdc_false);
+ break;
+
+ case font_pfm:
+ retval = pdf_get_metrics_pfm(p, font, fontname_p, enc,
+ filename, pdc_false);
+ break;
+
+ default:
+ break;
+ }
+
+ /* file found or error */
+ if (retval != pdc_undef)
+ {
+ if (retval == pdc_true)
+ if (pdf_extension_names[i].code == font_ttot)
+ outfilename = filename;
+ break;
+ }
+ }
+
+ if (retval == pdc_undef)
+ {
+ retval = pdc_false;
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tMetric data file for font \"%s\" not available\n",
+ fontname_p);
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_NOMETRICS, 0, 0, 0, 0);
+ }
+
+ break;
+ }
+
+ /* metrics data search finished */
+
+ if (retval == pdc_false)
+ {
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ /* store instance name instead of master name in the font structure */
+ if (mmparam)
+ {
+ pdc_free(p->pdc, font->ft.name);
+ font->ft.name = pdc_strdup(p->pdc, fontname);
+ pdc_free(p->pdc, font->ft.m.name);
+ font->ft.m.name = pdc_strdup(p->pdc, fontname);
+ }
+
+ /* If embedding was requested, check font file (or raise an exception) */
+ if (font->opt.embedding)
+ {
+ if (font->ft.img == NULL)
+ {
+ retval = pdc_undef;
+
+ if (outfilename)
+ {
+ /* Font outline file specified */
+ if (font->ft.m.type == fnt_Type1 ||
+ font->ft.m.type == fnt_MMType1)
+ {
+ retval = pdf_t1open_fontfile(p, font, outfilename, NULL,
+ pdc_true);
+ }
+ else
+ {
+ retval = fnt_check_tt_font(p->pdc, outfilename, NULL,
+ &font->ft, pdc_true);
+ }
+ }
+ else
+ {
+ /* Searching font outline file */
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tSearching for font outline data file:\n");
+
+ outfilename = testfilename;
+ for (i = 0; i < 100; i++)
+ {
+ extension = pdf_extension_names[i].word;
+ if (!extension)
+ break;
+
+ strcpy(testfilename, fontname_p);
+ strcat(testfilename, extension);
+
+ if (font->ft.m.type == fnt_Type1 ||
+ font->ft.m.type == fnt_MMType1)
+ {
+ if (pdf_extension_names[i].code == font_pfab)
+ {
+ retval = pdf_t1open_fontfile(p, font, outfilename,
+ NULL, pdc_false);
+ }
+ }
+ else if (pdf_extension_names[i].code == font_ttot)
+ {
+ retval = fnt_check_tt_font(p->pdc, outfilename,
+ NULL, &font->ft, pdc_false);
+ }
+
+ /* file found or error */
+ if (retval != pdc_undef)
+ break;
+ }
+
+ if (retval == pdc_undef)
+ {
+ retval = pdc_false;
+ pdc_set_errmsg(p->pdc, PDF_E_FONT_NOOUTLINE, 0, 0, 0, 0);
+ }
+ }
+
+ if (retval == pdc_false)
+ {
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tOutline data file for font \"%s\" not found\n",
+ fontname_p);
+ }
+ else
+ {
+ if (!font->ft.img)
+ font->filename = font->ft.filename;
+
+ pdc_logg_cond(p->pdc, 1, trc_font,
+ "\tFont outline data file \"%s\" available\n",
+ font->filename ?
+ font->filename : font->ft.imgname);
+ }
+ }
+ }
+ else if (font->ft.img)
+ {
+ if (!font->ft.imgname)
+ pdc_free(p->pdc, font->ft.img);
+ else
+ {
+ pdc_unlock_pvf(p->pdc, font->ft.imgname);
+ pdc_free(p->pdc, font->ft.imgname);
+ font->ft.imgname = NULL;
+ }
+ font->ft.img = NULL;
+ font->ft.filelen = 0;
+ }
+
+ if (retval && font->opt.monospace && font->opt.embedding)
+ {
+ pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0);
+ retval = pdc_false;
+ }
+
+ if (retval == pdc_false)
+ {
+ goto PDF_PREMATURE_EXIT;
+ }
+
+ PDF_NEWFONT_EXIT:
+
+ pdf_cleanup_font_options(p, fo);
+
+ encoding = pdc_get_user_encoding(p->pdc, font->ft.enc);
+ if (pdc_strcmp(font->encapiname, encoding))
+ pdc_logg_cond(p->pdc, 1, trc_encoding,
+ "\tDetermined font encoding: \"%s\"\n", encoding);
+
+ /* set missing font metrics values */
+ pdf_font_set_missvalues(p, font);
+
+ /* font is semantic (Unicode compatible) */
+ pdf_font_issemantic(p, font);
+
+ /* set replacement character and code */
+ pdf_set_replchar(p, font);
+
+ /* font object ID */
+ if (!font->opt.auxiliary)
+ font->obj_id = pdc_alloc_id(p->out);
+
+ /* Now everything is fine, insert font */
+ if (slot == -1)
+ slot = pdf_insert_font(p, font);
+
+
+ pdc_pop_errmsg(p->pdc);
+
+ return slot;
+
+
+ PDF_PREMATURE_EXIT:
+
+ pdf_cleanup_font_options(p, fo);
+ pdf_cleanup_font(p, font);
+
+ if (slot == -1)
+ {
+ if (font->verbose)
+ pdc_error(p->pdc, -1, 0, 0, 0, 0);
+ }
+
+ pdc_pop_errmsg(p->pdc);
+
+ return slot;
+}
+
+
+/* --------------------------- font writing ---------------------------- */
+
+static char *
+pdf_code2fontglyphname(pdf_font *font, pdc_encodingvector *ev, int code)
+{
+ char *glyphname;
+
+ glyphname = ev->chars[code];
+ pdc_get_alter_glyphname(ev->codes[code], font->missingglyphs,
+ &glyphname);
+
+ return glyphname ? glyphname : (char *) pdc_get_notdef_glyphname();
+}
+
+void
+pdf_transform_fontwidths(PDF *p, pdf_font *font, pdc_encodingvector *evto,
+ pdc_encodingvector *evfrom)
+{
+ int widths[256];
+ pdc_ushort code2gid[256];
+ int i, j;
+
+ for (i = 0; i < 256; i++)
+ {
+ widths[i] = font->ft.m.defwidth;
+ code2gid[i] = 0;
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ j = (int) pdc_transform_bytecode(p->pdc, evto, evfrom, (pdc_byte)i);
+ widths[j] = font->ft.m.widths[i];
+ if (font->ft.code2gid != NULL)
+ code2gid[j] = font->ft.code2gid[i];
+ }
+
+ widths[0] = font->ft.m.defwidth;
+ memcpy(font->ft.m.widths, widths, 256 * sizeof(int));
+ if (font->ft.code2gid != NULL)
+ memcpy(font->ft.code2gid, code2gid, 256 * sizeof(pdc_ushort));
+}
+
+
+
+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)
+{
+ (void) cidset_id;
+ (void) nusedgids;
+
+ /*
+ * Font descriptor object
+ */
+ pdc_begin_obj(p->out, fontdescriptor_id); /* font descriptor obj */
+ pdc_begin_dict(p->out); /* font descriptor dict */
+
+ pdc_puts(p->out, "/Type/FontDescriptor\n");
+ pdc_printf(p->out, "/Flags %ld\n", font->ft.m.flags);
+
+
+ pdc_printf(p->out, "/Ascent %d\n", font->ft.m.ascender);
+ pdc_printf(p->out, "/CapHeight %d\n", font->ft.m.capHeight);
+ pdc_printf(p->out, "/Descent %d\n", font->ft.m.descender);
+ pdc_printf(p->out, "/FontBBox[%d %d %d %d]\n",
+ (int) font->ft.m.llx, (int) font->ft.m.lly,
+ (int) font->ft.m.urx, (int) font->ft.m.ury);
+
+ pdc_printf(p->out, "/FontName");
+ pdf_put_pdfname(p, font->ft.m.name);
+ pdc_puts(p->out, "\n");
+
+ pdc_printf(p->out, "/ItalicAngle %d\n", (int) (font->ft.m.italicAngle));
+ pdc_printf(p->out, "/StemV %d\n", font->ft.m.StdVW);
+
+ if (font->ft.m.StdHW > 0)
+ pdc_printf(p->out, "/StemH %d\n", font->ft.m.StdHW);
+
+ if (font->ft.m.xHeight > 0)
+ pdc_printf(p->out, "/XHeight %d\n", font->ft.m.xHeight);
+
+ if (missingwidth > 0)
+ pdc_printf(p->out, "/MissingWidth %d\n", missingwidth);
+
+ if (fontfile_id != PDC_BAD_ID)
+ {
+ switch(font->ft.m.type)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ pdc_objref(p->out, "/FontFile", fontfile_id);
+ break;
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ pdc_objref(p->out, "/FontFile2", fontfile_id);
+ break;
+
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ pdc_objref(p->out, "/FontFile3", fontfile_id);
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ default:
+ break;
+ }
+ }
+
+
+ pdc_end_dict(p->out); /* font descriptor dict */
+ pdc_end_obj(p->out); /* font descriptor obj */
+}
+
+static void
+pdf_put_font(PDF *p, pdf_font *font)
+{
+ const char *fontname = font->ft.name;
+ fnt_fonttype fonttype = font->ft.m.type;
+ pdc_id fontdescriptor_id = PDC_BAD_ID;
+ pdc_id fontfile_id = PDC_BAD_ID;
+ pdc_id encoding_id = PDC_BAD_ID;
+ pdc_id cidset_id = PDC_BAD_ID;
+ pdc_id length_id = PDC_BAD_ID;
+ pdc_id descendant_id = PDC_BAD_ID;
+ pdc_encoding enc = font->ft.enc;
+ const char *encoding;
+ pdc_encoding_info *encinfo = NULL;
+ pdc_bool comp_font = pdc_false;
+ pdc_bool acro_fontstyle = pdc_false;
+ pdc_scalar a = 1.0;
+ PDF_data_source src;
+ int nusedgids = 0;
+
+ /* save font struct members */
+ pdc_encodingvector *ev = NULL;
+ pdc_encoding font_encoding = font->ft.enc;
+ int font_numcodes = font->ft.numcodes;
+ int font_codesize = font->codesize;
+
+ int missingwidth = 0;
+ int i;
+
+ encoding = pdc_get_user_encoding(p->pdc, enc);
+ if (!pdc_strcmp(font->encapiname, encoding))
+ {
+ pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX,
+ font->apiname, font->encapiname, 0, 0);
+ }
+ else
+ {
+ pdc_push_errmsg(p->pdc, PDF_E_FONT_PREFIX2,
+ font->apiname, font->encapiname, encoding, 0);
+ }
+
+
+ /* ID for embedded font */
+ if (font->opt.embedding)
+ {
+ switch(fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ fontfile_id = pdc_alloc_id(p->out);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Font dictionary
+ */
+ pdc_begin_obj(p->out, font->obj_id); /* font obj */
+ pdc_begin_dict(p->out); /* font dict */
+ pdc_puts(p->out, "/Type/Font\n");
+
+ /* /Subtype */
+ pdc_printf(p->out, "/Subtype/%s\n",
+ pdc_get_keyword(fonttype, pdf_fonttype_pdfkeylist));
+ comp_font = fonttype == fnt_CIDFontType0 || fonttype == fnt_CIDFontType2;
+
+ /* Acrobat font style */
+ acro_fontstyle = font->opt.fontstyle != fnt_Normal &&
+ !(font->metricflags & (font_bold | font_italic));
+
+ /* /Name */
+ if (fonttype == fnt_Type3 || font->used_in_formfield)
+ {
+ /*
+ * The name is optional, but if we include it it will show up
+ * in Acrobat's font info box. However, if the same font name
+ * is used with different encodings Acrobat 4 will not be
+ * able to distinguish both. For this reason we add the
+ * encoding name to make the font name unique.
+ */
+
+ const char *name = fontname;
+
+ if (font->used_in_formfield)
+ name = pdf_get_pdf_fontname(font);
+
+ pdc_puts(p->out, "/Name");
+ pdf_put_pdfname(p, name);
+ pdc_puts(p->out, "\n");
+ }
+
+ /* /BaseFont */
+ switch (fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ case fnt_TrueType:
+ case fnt_Type1C:
+ case fnt_CIDFontType2:
+ case fnt_CIDFontType0:
+ {
+ pdc_puts(p->out, "/BaseFont");
+ pdf_put_pdfname(p, fontname);
+ if (font->outcmapname)
+ pdc_printf(p->out, "-%s", font->outcmapname);
+ if (acro_fontstyle && !comp_font)
+ pdc_printf(p->out, ",%s", pdc_get_keyword(font->opt.fontstyle,
+ pdf_fontstyle_pdfkeylist));
+ pdc_puts(p->out, "\n");
+ }
+ break;
+
+ /* /FontBBox, /FontMatrix, /CharProcs /Resources */
+ case fnt_Type3:
+ if (font->t3font->charprocs_id == PDC_BAD_ID)
+ pdc_error(p->pdc, PDF_E_T3_OUTLINESMISSING, fontname, 0, 0, 0);
+
+ pdc_printf(p->out, "/FontBBox[%f %f %f %f]\n",
+ font->ft.bbox.llx, font->ft.bbox.lly,
+ font->ft.bbox.urx, font->ft.bbox.ury);
+
+ pdc_printf(p->out, "/FontMatrix[%f %f %f %f %f %f]\n",
+ font->ft.matrix.a, font->ft.matrix.b,
+ font->ft.matrix.c, font->ft.matrix.d,
+ font->ft.matrix.e, font->ft.matrix.f);
+ pdc_objref(p->out, "/CharProcs", font->t3font->charprocs_id);
+ pdc_objref(p->out, "/Resources", font->t3font->res_id);
+
+ /* We must apply a correctional factor since Type 3 fonts not
+ * necessarily use 1000 units per em. We apply the correction
+ * here, and store the 1000-based width values in the font in
+ * order to speed up PDF_stringwidth().
+ */
+ a = 1000 * font->ft.matrix.a;
+ break;
+
+ default:
+ break;
+ }
+
+ /* changing 8-bit font encoding to builtin */
+ if (enc >= 0 && font->symenc != pdc_invalidenc)
+ {
+ ev = NULL;
+ enc = pdc_builtin;
+ font->ft.enc = enc;
+ }
+
+ /* changing 8-bit font encoding to winansi */
+ if (font->towinansi != pdc_invalidenc)
+ {
+ pdc_encodingvector *evfrom;
+
+ ev = pdc_get_encoding_vector(p->pdc, font->towinansi);
+ evfrom = pdc_get_encoding_vector(p->pdc, enc);
+ pdf_transform_fontwidths(p, font, ev, evfrom);
+
+ enc = font->towinansi;
+ font->ft.enc = enc;
+ }
+
+ /* /FontDescriptor, /FirstChar, /LastChar, /Widths */
+ switch (fonttype)
+ {
+ case fnt_Type1:
+ /* disabled, because of PDF 1.7 reference
+ if (font->ft.isstdfont == pdc_true) break;
+ */
+ case fnt_MMType1:
+ case fnt_TrueType:
+ case fnt_Type1C:
+ case fnt_Type3:
+ {
+ int firstchar = 0;
+ int lastchar = 255;
+ int defwidth = 0;
+
+ if (fonttype != fnt_Type3
+ )
+ {
+ fontdescriptor_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id);
+ }
+
+
+ /* determine missing width.
+ * Only for embedded fonts because of a bug in Acrobat,
+ * which arises if the font is not installed at host.
+ */
+ if (font->opt.embedding)
+ {
+ if (fonttype != fnt_Type3)
+ defwidth = font->ft.m.widths[0];
+
+ {
+ for (i = 1; i < 255; i++)
+ {
+ if (font->ft.m.widths[i] != defwidth)
+ break;
+ }
+ if (i > 1)
+ firstchar = i;
+ for (i = 255; i > 0; i--)
+ {
+ if (i == firstchar || font->ft.m.widths[i] != defwidth)
+ break;
+ }
+ lastchar = i;
+ }
+
+ if (firstchar > 0 || lastchar < 255)
+ missingwidth = (int) (defwidth / a + 0.5);
+ }
+
+ pdc_printf(p->out, "/FirstChar %d\n", firstchar);
+ pdc_printf(p->out, "/LastChar %d\n", lastchar);
+
+ pdc_puts(p->out, "/Widths");
+ pdc_begin_array(p->out);
+ for (i = firstchar; i <= lastchar; i++)
+ {
+ pdc_printf(p->out, "%d",
+ (int) (font->ft.m.widths[i] / a + .5));
+ if (i < 255)
+ pdc_printf(p->out, "%s", ((i + 1) % 16) ? " " : "\n");
+ }
+ pdc_end_array(p->out);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* /Encoding */
+ switch (fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ case fnt_TrueType:
+ case fnt_Type1C:
+ if (!font->used_in_formfield)
+ {
+ if (enc == pdc_winansi)
+ {
+ pdc_printf(p->out, "/Encoding/WinAnsiEncoding\n");
+ break;
+ }
+ if (enc == pdc_macroman && font->hasnomac == pdc_false)
+ {
+ pdc_printf(p->out, "/Encoding/MacRomanEncoding\n");
+ break;
+ }
+ }
+ case fnt_Type3:
+ if (enc >= 0)
+ {
+ encinfo = pdc_get_encoding_info(p->pdc, enc);
+ if (encinfo->id == PDC_BAD_ID)
+ encinfo->id = pdc_alloc_id(p->out);
+ encoding_id = encinfo->id;
+ }
+
+ if (encoding_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Encoding", encoding_id);
+
+ if (encinfo != NULL)
+ {
+ if (!encinfo->stored)
+ encinfo->stored = pdc_true;
+ else
+ encoding_id = PDC_BAD_ID;
+ }
+
+ break;
+
+ case fnt_CIDFontType2:
+ case fnt_CIDFontType0:
+ if (font->outcmapname)
+ {
+ pdc_printf(p->out, "/Encoding/%s\n", font->outcmapname);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* /ToUnicode . Only reasonable if nusedgids != 1
+ * (== 1: only notdef character in a font subset)
+ */
+
+
+ /* /DescendantFonts */
+ if (comp_font == pdc_true)
+ {
+ descendant_id = pdc_alloc_id(p->out);
+ pdc_puts(p->out, "/DescendantFonts");
+ pdc_begin_array(p->out);
+ pdc_objref(p->out, "", descendant_id);
+ pdc_end_array(p->out);
+ }
+
+ pdc_end_dict(p->out); /* font dict */
+ pdc_end_obj(p->out); /* font obj */
+
+ /*
+ * Encoding dictionary
+ */
+ if (encoding_id != PDC_BAD_ID)
+ {
+ char *glyphname;
+
+ pdc_begin_obj(p->out, encoding_id); /* encoding obj */
+ pdc_begin_dict(p->out); /* encoding dict */
+
+ pdc_puts(p->out, "/Type/Encoding\n");
+
+ {
+ pdc_encodingvector *evb = NULL;
+
+ pdc_set_encoding_glyphnames(p->pdc, enc);
+ ev = pdc_get_encoding_vector(p->pdc, enc);
+
+ /* See Implementation Note 46. The restrictions described there
+ * are also valid for Acrobat versions up to now.
+ */
+ if (fonttype != fnt_Type3 && !font->used_in_formfield)
+ {
+ if (!strncmp(ev->apiname, PDC_ENC_MODWINANSI,
+ strlen(PDC_ENC_MODWINANSI)) ||
+ !strncmp(ev->apiname, PDC_ENC_ISO8859,
+ strlen(PDC_ENC_ISO8859)) ||
+ !strncmp(ev->apiname, PDC_ENC_CP125,
+ strlen(PDC_ENC_CP125)))
+ {
+ pdc_puts(p->out, "/BaseEncoding/WinAnsiEncoding\n");
+ evb = pdc_get_encoding_vector(p->pdc, pdc_winansi);
+ }
+ else if (!strncmp(ev->apiname, PDC_ENC_MODMACROMAN,
+ strlen(PDC_ENC_MODMACROMAN)))
+ {
+ pdc_puts(p->out, "/BaseEncoding/MacRomanEncoding\n");
+ evb = pdc_get_encoding_vector(p->pdc, pdc_macroman);
+ }
+ else
+ {
+ /* /BaseEncoding/StandardEncoding */
+ evb = pdc_get_encoding_vector(p->pdc, pdc_stdenc);
+ }
+ }
+
+ if (evb != NULL)
+ {
+ int iv = -1;
+ for (i = 0; i < font->ft.numcodes; i++)
+ {
+ glyphname = pdf_code2fontglyphname(font, ev, i);
+
+ /* enforce first three names because of bug in Acrobat 6 */
+ if (i < 3 ||
+ (glyphname && !evb->chars[i]) ||
+ (!glyphname && evb->chars[i]) ||
+ (glyphname && evb->chars[i] &&
+ strcmp(glyphname, evb->chars[i])))
+ {
+ if (iv == -1)
+ pdc_puts(p->out, "/Differences[0");
+ if (i > iv + 1)
+ pdc_printf(p->out, "%d", i);
+ pdf_put_pdfname(p, glyphname);
+ pdc_puts(p->out, "\n");
+ iv = i;
+ }
+ }
+ if (iv > -1)
+ pdc_end_array(p->out);
+ }
+ else
+ {
+ pdc_puts(p->out, "/Differences[0");
+ for (i = 0; i < font->ft.numcodes; i++)
+ {
+ glyphname = pdf_code2fontglyphname(font, ev, i);
+ pdf_put_pdfname(p, glyphname);
+ pdc_puts(p->out, "\n");
+ }
+ pdc_end_array(p->out);
+ }
+ }
+
+ pdc_end_dict(p->out); /* encoding dict */
+ pdc_end_obj(p->out); /* encoding obj */
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+ }
+
+
+ /*
+ * CID fonts dictionary
+ */
+ if (descendant_id != PDC_BAD_ID)
+ {
+ pdc_begin_obj(p->out, descendant_id); /* CID font obj */
+ pdc_begin_dict(p->out); /* CID font dict */
+ pdc_puts(p->out, "/Type/Font\n");
+
+ /* /Subtype */
+ if (fonttype == fnt_CIDFontType0)
+ pdc_puts(p->out, "/Subtype/CIDFontType0\n");
+ if (fonttype == fnt_CIDFontType2)
+ pdc_puts(p->out, "/Subtype/CIDFontType2\n");
+
+ /* /BaseFont */
+ pdc_puts(p->out, "/BaseFont");
+ pdf_put_pdfname(p, fontname);
+ if (acro_fontstyle)
+ pdc_printf(p->out, ",%s",
+ pdc_get_keyword(font->opt.fontstyle, pdf_fontstyle_pdfkeylist));
+ pdc_puts(p->out, "\n");
+
+ /* /CIDSystemInfo */
+ pdc_puts(p->out, "/CIDSystemInfo<</Registry");
+ pdf_put_hypertext(p, "Adobe");
+ pdc_puts(p->out, "/Ordering");
+ pdf_put_hypertext(p, fnt_get_ordering_cid(font->ft.m.charcoll));
+ pdc_printf(p->out, "/Supplement %d>>\n", MAX(font->supplement, 0));
+
+ /* /FontDescriptor */
+ fontdescriptor_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id);
+
+
+
+ /* /DW /W */
+#ifdef PDF_CJKFONTWIDTHS_SUPPORTED
+ if (font->ft.isstdfont)
+ pdf_put_cidglyph_widths(p, font);
+#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */
+
+
+ pdc_end_dict(p->out); /* CID font dict */
+ pdc_end_obj(p->out); /* CID font obj */
+
+ }
+
+
+ /*
+ * FontDescriptor dictionary
+ */
+ if (fontdescriptor_id != PDC_BAD_ID)
+ pdf_write_fontdescriptor(p, font, missingwidth, fontdescriptor_id,
+ cidset_id, fontfile_id, nusedgids);
+
+
+
+ /*
+ * Font embedding
+ */
+ if (fontfile_id != PDC_BAD_ID)
+ {
+ pdc_id length1_id = PDC_BAD_ID;
+ pdc_id length2_id = PDC_BAD_ID;
+ pdc_id length3_id = PDC_BAD_ID;
+ pdc_bool compress = pdc_false;
+
+ /* Prepare embedding */
+ switch(fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ {
+ pdf_make_t1src(p, font, &src);
+ length1_id = pdc_alloc_id(p->out);
+ length2_id = pdc_alloc_id(p->out);
+ length3_id = pdc_alloc_id(p->out);
+ }
+ break;
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ {
+ length1_id = pdc_alloc_id(p->out);
+ }
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ case fnt_OpenType:
+ {
+ src.private_data = (void *) font->filename;
+ if (font->filename)
+ {
+ /* Read the font from file */
+ src.init = pdf_data_source_file_init;
+ src.fill = pdf_data_source_file_fill;
+ src.terminate = pdf_data_source_file_terminate;
+ switch(fonttype)
+ {
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_OpenType:
+ src.offset = (long) 0;
+ src.length = (long) 0;
+ break;
+
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ src.offset = font->cff_offset;
+ src.length = (long) font->cff_length;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* Read the font from memory */
+ src.init = NULL;
+ src.fill = pdf_data_source_buf_fill;
+ src.terminate = NULL;
+ switch(fonttype)
+ {
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_OpenType:
+ src.buffer_start = font->ft.img;
+ src.buffer_length = font->ft.filelen;
+ break;
+
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ src.buffer_start = font->ft.img + font->cff_offset;
+ src.buffer_length = font->cff_length;
+ break;
+
+ default:
+ break;
+ }
+ src.bytes_available = 0;
+ src.next_byte = NULL;
+ }
+ }
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ default:
+ break;
+ }
+
+ /* Embedded font stream dictionary */
+ pdc_begin_obj(p->out, fontfile_id); /* Embedded font stream obj */
+ pdc_begin_dict(p->out); /* Embedded font stream dict */
+
+ /* /Length, /Filter */
+ length_id = pdc_alloc_id(p->out);
+ pdc_objref(p->out, "/Length", length_id);
+ switch(fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ break;
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_Type1C:
+ case fnt_CIDFontType0:
+ case fnt_OpenType:
+ if (font->ft.filelen != 0L)
+ {
+ compress = pdc_true;
+ if (pdc_get_compresslevel(p->out))
+ pdc_puts(p->out, "/Filter/FlateDecode\n");
+ }
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ default:
+ break;
+ }
+
+ /* /Length1, /Length2, Length3 */
+ if (length1_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Length1", length1_id);
+ if (length2_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Length2", length2_id);
+ if (length3_id != PDC_BAD_ID)
+ pdc_objref(p->out, "/Length3", length3_id);
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ /* /Subtype */
+ if(fonttype == fnt_Type1C)
+ pdc_puts(p->out, "/Subtype/Type1C\n");
+ if (fonttype == fnt_CIDFontType0)
+ pdc_puts(p->out, "/Subtype/CIDFontType0C\n");
+ if (fonttype == fnt_OpenType)
+ pdc_puts(p->out, "/Subtype/OpenType\n");
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+
+ pdc_end_dict(p->out); /* Embedded font stream dict */
+
+ /* Stream */
+ pdf_copy_stream(p, &src, compress);
+
+ pdc_end_obj(p->out); /* Embedded font stream obj */
+
+ pdc_put_pdfstreamlength(p->out, length_id);
+
+ /* Length objects */
+ switch(fonttype)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+ pdf_put_length_objs(p, &src, length1_id, length2_id, length3_id);
+ break;
+
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ if (compress)
+ {
+ pdc_begin_obj(p->out, length1_id); /* Length1 obj */
+ pdc_printf(p->out, "%ld\n", (long) font->ft.filelen);
+ pdc_end_obj(p->out); /* Length1 obj */
+ }
+ else
+ {
+ /* same as /Length */
+ pdc_put_pdfstreamlength(p->out, length1_id);
+ }
+ break;
+#endif /* PDF_TRUETYPE_SUPPORTED */
+
+ default:
+ break;
+ }
+ }
+
+ if (p->flush & pdc_flush_content)
+ pdc_flush_stream(p->out);
+
+ /* restore font struct members */
+ font->ft.enc = font_encoding;
+ font->ft.numcodes = font_numcodes;
+ font->codesize = font_codesize;
+
+ pdc_pop_errmsg(p->pdc);
+}
+
+void
+pdf_write_doc_fonts(PDF *p)
+{
+ int slot;
+ pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_font);
+
+ /* output pending font objects */
+ for (slot = 0; slot < p->fonts_number; slot++)
+ {
+ pdf_font *font = &p->fonts[slot];
+
+ switch(p->fonts[slot].ft.m.type)
+ {
+ case fnt_Type1:
+ case fnt_MMType1:
+#ifdef PDF_TRUETYPE_SUPPORTED
+ case fnt_TrueType:
+ case fnt_CIDFontType2:
+ case fnt_Type1C:
+#endif /* PDF_TRUETYPE_SUPPORTED */
+ case fnt_CIDFontType0:
+ case fnt_Type3:
+ if (font->obj_id != PDC_BAD_ID)
+ {
+ if (logg1)
+ {
+ pdc_logg(p->pdc,
+ "\tProcessing font %d: \"%s\" "
+ "with encoding \"%s\" and PDF object id %ld",
+ slot, font->ft.name,
+ pdf_get_encoding_name(p, font->ft.enc, font),
+ font->obj_id);
+ }
+
+ if (font->ft.enc == pdc_invalidenc ||
+ font->used_in_current_doc == pdc_false)
+ {
+ if (logg1)
+ pdc_logg(p->pdc, " - but not used\n", font->obj_id);
+
+ /*
+ * This font has been defined, but never used in the
+ * document. Ignore it. However, the font's object id
+ * has already been allocated, so we mark the object
+ * as free in order to avoid a complaint of the object
+ * machinery.
+ */
+ pdc_mark_free(p->out, font->obj_id);
+ }
+ else
+ {
+ if (logg1)
+ pdc_logg(p->pdc, "\n");
+
+ pdf_put_font(p, font);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void
+pdf_write_page_fonts(PDF *p)
+{
+ int i, total = 0;
+ int bias = p->curr_ppt->fn_bias;
+
+ /* This doesn't really belong here, but all modules which write
+ * font resources also need this, so we include it here.
+ * Note that keeping track of ProcSets is considered obsolete
+ * starting with PDF 1.4, so we always include the full set which
+ * is written as a constant object at the beginning of the file.
+ */
+
+ pdc_objref(p->out, "/ProcSet", p->procset_id);
+
+ for (i = 0; i < p->fonts_number; i++)
+ if (p->fonts[i].used_on_current_page == pdc_true)
+ total++;
+
+ if (total > 0 || bias)
+ {
+ pdc_puts(p->out, "/Font");
+ pdc_begin_dict(p->out); /* font resource dict */
+ }
+
+ if (total > 0)
+ {
+ for (i = 0; i < p->fonts_number; i++)
+ {
+ if (p->fonts[i].used_on_current_page == pdc_true) {
+ p->fonts[i].used_on_current_page = pdc_false; /* reset */
+ pdc_printf(p->out, "/F%d", bias + i);
+ pdc_objref(p->out, "", p->fonts[i].obj_id);
+ }
+ }
+
+ if (!bias)
+ pdc_end_dict(p->out); /* font resource dict */
+ }
+}
+
+void
+pdf_get_page_fonts(PDF *p, pdf_reslist *rl)
+{
+ int i;
+
+ for (i = 0; i < p->fonts_number; i++)
+ {
+ if (p->fonts[i].used_on_current_page)
+ {
+ p->fonts[i].used_on_current_page = pdc_false; /* reset */
+ pdf_add_reslist(p, rl, i);
+ }
+ }
+}
+
+void
+pdf_mark_page_font(PDF *p, int ft)
+{
+ p->fonts[ft].used_on_current_page = pdc_true;
+}
+
+
+