brugno 8e01c8dd9a Patch level :
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :Primo commit del modulo


git-svn-id: svn://10.65.10.50/trunk@13958 c028cbd2-c16b-5b4b-a496-9718f37d4682
2006-05-04 16:36:51 +00:00

1900 lines
54 KiB
C
Executable File

/*---------------------------------------------------------------------------*
| PDFlib - A library for generating PDF on the fly |
+---------------------------------------------------------------------------+
| Copyright (c) 1997-2005 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 2006-05-04 16:36:51 brugno 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_truetype.h"
#define PDF_TTC_SEPARATOR ':'
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}
};
const char *
pdf_get_font_char_option(PDF *p, pdf_font_optflags fflags)
{
pdf_text_options *to = p->curr_ppt->currto;
pdc_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->name;
case fo_encoding:
return pdf_get_encoding_name(p, currfont->encoding, currfont);
case fo_fontstyle:
return pdc_get_keyword(currfont->style, 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;
pdc_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->monospace;
default:
return 0;
}
}
void
pdf_cleanup_font(PDF *p, pdc_font *font)
{
if (font->imgname)
pdf_unlock_pvf(p, font->imgname);
pdc_cleanup_font_struct(p->pdc, font);
}
void
pdf_cleanup_fonts(PDF *p)
{
int slot;
if (p->fonts)
{
for (slot = 0; slot < p->fonts_number; slot++)
pdf_cleanup_font(p, &p->fonts[slot]);
if (p->fonts)
pdc_free(p->pdc, p->fonts);
p->fonts = NULL;
}
}
void
pdf_init_fonts(PDF *p)
{
static const char fn[] = "pdf_init_fonts";
p->fonts_number = 0;
p->fonts_capacity = FONTS_CHUNKSIZE;
p->fonts = (pdc_font *) pdc_calloc(p->pdc,
sizeof(pdc_font) * p->fonts_capacity, fn);
p->t3font = (pdc_t3font *) NULL;
pdf_init_encoding_ids(p);
}
void
pdf_grow_fonts(PDF *p)
{
static const char fn[] = "pdf_grow_fonts";
p->fonts = (pdc_font *) pdc_realloc(p->pdc, p->fonts,
sizeof(pdc_font) * 2 * p->fonts_capacity, fn);
p->fonts_capacity *= 2;
}
int
pdf_init_newfont(PDF *p)
{
pdc_font *font;
int slot;
/* slot for font struct */
slot = p->fonts_number;
if (slot >= p->fonts_capacity)
pdf_grow_fonts(p);
/* initialize font struct */
font = &p->fonts[slot];
pdc_init_font_struct(p->pdc, font);
return slot;
}
static pdc_bool
pdf_get_metrics_core(PDF *p, pdc_font *font, const char *fontname,
pdc_encoding enc)
{
const pdc_core_metric *metric;
metric = pdc_get_core_metric(fontname);
if (metric != NULL)
{
pdc_trace_protocol(p->pdc, 1, trc_font,
"\tLoading metric data for core font \"%s\":\n", fontname);
/* Fill up the font struct */
pdc_fill_font_metric(p->pdc, font, metric);
font->encoding = enc;
/* Process metric data */
if (pdf_process_metrics_data(p, font, fontname))
{
if (!pdf_make_fontflag(p, font))
return pdc_false;
if (font->monospace)
{
pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0);
if (font->verbose == pdc_true)
{
pdf_cleanup_font(p, font);
pdc_error(p->pdc, -1, 0, 0, 0, 0);
}
return pdc_false;
}
return pdc_true;
}
}
return pdc_undef;
}
void
pdf_font_set_missvalues(PDF *p, pdc_font *font)
{
(void) p;
if (font->descender > 0)
font->descender = -(font->descender);
if (font->ascender <= 0)
{
font->metricflags |= font_ascender;
font->ascender = 720;
}
if (font->descender == PDC_MISSING_FONTVAL)
{
font->metricflags |= font_descender;
font->descender = (int) PDC_ROUND(-0.25 * font->ascender);
}
if (font->capHeight <= 0)
{
font->metricflags |= font_capheight;
font->capHeight = (int) PDC_ROUND(0.93 * font->ascender);
}
if (font->xHeight <= 0)
{
font->metricflags |= font_xheight;
font->xHeight = (int) PDC_ROUND(0.66 * font->ascender);
}
}
pdc_bool
pdf_font_get_is_faked(pdc_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;
}
pdc_bool
pdf_make_fontflag(PDF *p, pdc_font *font)
{
(void) p;
if (font->type != pdc_Type3)
{
if (font->isFixedPitch)
font->flags |= FIXEDWIDTH;
if (font->isstdlatin == pdc_true ||
font->encoding == pdc_winansi ||
font->encoding == pdc_macroman ||
font->encoding == pdc_ebcdic ||
font->encoding == pdc_ebcdic_37)
font->flags |= ADOBESTANDARD;
else
font->flags |= SYMBOL;
if (font->italicAngle < 0 ||
font->style == pdc_Italic || font->style == pdc_BoldItalic)
font->flags |= ITALIC;
if (font->italicAngle == 0 && font->flags & ITALIC)
font->italicAngle = PDC_DEF_ITALICANGLE;
/* heuristic to identify (small) caps fonts */
if (font->name &&
(strstr(font->name, "Caps") ||
!strcmp(font->name + strlen(font->name) - 2, "SC")))
font->flags |= SMALLCAPS;
if (font->style == pdc_Bold || font->style == pdc_BoldItalic)
font->StdVW = PDF_STEMV_BOLD;
if (strstr(font->name, "Bold") || font->StdVW > PDF_STEMV_SEMIBOLD)
font->flags |= FORCEBOLD;
}
if (font->style != pdc_Normal &&
(font->embedding || font->type == pdc_Type1 ||
font->type == pdc_MMType1 || font->type == pdc_Type3))
{
pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDSTYLE, 0, 0, 0, 0);
if (font->verbose == pdc_true)
{
pdf_cleanup_font(p, font);
pdc_error(p->pdc, -1, 0, 0, 0, 0);
}
return pdc_false;
}
pdc_font_trace_protocol(p->pdc, font);
return pdc_true;
}
void
pdf_font_issemantic(PDF *p, pdc_font *font)
{
pdc_encoding enc = font->encoding;
pdc_ushort spacechar = 0;
/* Flag: encoding is Unicode interpretable */
if (enc >= 0 || enc == pdc_unicode ||
(enc == pdc_cid && font->codeSize == 2))
font->issemantic = pdc_true ;
/* Flag: encoding with ASCII space for wordspacing */
if (enc >= 0)
{
int i = pdc_get_encoding_bytecode(p->pdc,
pdf_get_encoding_vector(p, enc),
PDC_UNICODE_SPACE);
if (i > -1)
{
spacechar = (pdc_ushort) i;
if (spacechar == PDC_UNICODE_SPACE)
font->asciispace = pdc_true;
}
}
/* determine code of space character */
font->spacechar = 0;
switch(enc)
{
case pdc_cid:
if (font->codeSize == 2)
font->spacechar = PDC_UNICODE_SPACE;
break;
case pdc_unicode:
font->spacechar = PDC_UNICODE_SPACE;
break;
case pdc_glyphid:
font->spacechar = font->code2GID[PDC_UNICODE_SPACE];
break;
default:
font->spacechar = spacechar;
break;
}
}
/* definitions of font options */
static const pdc_defopt pdf_load_font_options[] =
{
PDF_FONT_OPTIONS2
PDF_FONT_OPTIONS3
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;
fo->encoding = NULL;
fo->flags = 0;
fo->fontname = NULL;
fo->fontstyle = pdc_Normal;
fo->fontwarning = p->debug[(int) 'F'];
fo->kerning = pdc_false;
fo->mask = 0;
fo->monospace = 0;
fo->auxiliary = pdc_false;
}
void
pdf_cleanup_font_options(PDF *p)
{
if (p->currfo)
{
pdc_free(p->pdc, p->currfo);
p->currfo = 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, p->debug[(int) 'F']);
if (resopts)
{
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_textflow)
{
fo->fontname = pdf_get_opt_utf8name(p, "fontname", resopts);
if (fo->fontname)
{
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);
if (pdc_get_optvalues("embedding", resopts, &fo->embedding, NULL))
fo->mask |= (1L << fo_embedding);
if (pdc_get_optvalues("fontstyle", resopts, &inum, NULL))
{
fo->fontstyle = (pdc_fontstyle) inum;
fo->mask |= (1L << fo_fontstyle);
}
if (pdc_get_optvalues("monospace", resopts, &fo->monospace, NULL))
fo->mask |= (1L << fo_monospace);
}
int
pdf__load_font(PDF *p, const char *fontname, int inlen,
const char *encoding, const char *optlist)
{
int slot;
char *fname;
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);
/* Converting fontname */
fname = pdf_convert_name(p, fontname, inlen, pdc_true);
if (fname == NULL || *fname == '\0')
pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);
/* initialize */
pdf_init_font_options(p, &fo);
fo.fontname = (char *) fname;
fo.encoding = (char *) encoding;
/* parsing option list */
if (optlist && strlen(optlist))
{
pdc_resopt *resopts = pdc_parse_optionlist(p->pdc, optlist,
pdf_load_font_options, NULL, p->debug[(int) 'F']);
if (!resopts)
return -1;
pdf_get_font_options(p, &fo, resopts);
pdc_cleanup_optionlist(p->pdc, resopts);
}
slot = pdf_load_font_internal(p, &fo);
pdc_free(p->pdc, fname);
return slot;
}
int
pdf_load_font_internal(PDF *p, pdf_font_options *fo)
{
static const char fn[] = "pdf_load_font_internal";
const char *fontname;
const char *encoding;
pdc_encoding enc = pdc_invalidenc, enc_old;
pdc_bool verbose;
pdc_bool kret;
int slot = -1;
size_t len;
int i;
int retval;
pdc_font *font;
const char *extension = NULL;
const char *outfilename = NULL;
char *fontname_p = NULL;
char *filename = NULL, testfilename[PDF_MAX_FONTNAME + 5];
char *sf, *mmparam, mastername[PDF_MAX_FONTNAME + 1];
char ittc;
/* UTF-8 font name without BOM */
fontname = pdc_utf8strprint(p->pdc, fo->fontname);
/* font encoding */
encoding = fo->encoding;
/* slot for new font struct */
slot = pdf_init_newfont(p);
font = &p->fonts[slot];
/* copy options */
font->embedding = fo->embedding;
font->style = fo->fontstyle;
font->verbose = fo->fontwarning;
font->verbose_open = fo->fontwarning;
font->kerning = fo->kerning;
font->monospace = fo->monospace;
verbose = font->verbose;
slot = -1;
kret = pdc_false;
/* search for a registered encoding */
enc = pdf_find_encoding(p, encoding);
if (enc == pdc_invalidenc)
{
/* search for a predefined CMap and registered fonts */
enc = pdf_handle_cidfont(p, fontname, encoding, &slot);
if (enc == pdc_invalidenc)
{
/* search for a new encoding */
enc = pdf_insert_encoding(p, encoding, &font->codepage,
font->verbose);
if (enc == pdc_invalidenc)
kret = pdc_true;
}
else if (enc == pdc_cid && slot != -1)
{
kret = pdc_true;
if (slot < 0)
{
slot = -1;
pdf_cleanup_font(p, font);
if (verbose)
pdc_error(p->pdc, -1, 0, 0, 0, 0);
}
}
}
pdc_trace_protocol(p->pdc, 1, trc_encoding, "\tFont encoding: \"%s\"\n",
pdf_get_user_encoding(p, enc));
enc_old = enc;
if (kret)
return slot;
if (enc == pdc_unicode || enc == pdc_glyphid)
{
pdf_cleanup_font(p, font);
pdc_error(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0);
}
/*
* 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 descriptor.
* 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.
*/
for (slot = 0; slot < p->fonts_number; slot++)
{
if (p->fonts[slot].obj_id == PDC_BAD_ID)
{
if (fo->auxiliary)
return slot;
}
else if (!fo->auxiliary &&
!strcmp(p->fonts[slot].apiname, fontname) &&
p->fonts[slot].style == font->style)
{
if (p->fonts[slot].type == pdc_Type3)
{
if (enc < 0 )
{
pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC,
p->fonts[slot].name,
pdf_get_encoding_name(p, enc, font), 0, 0);
pdf_cleanup_font(p, font);
if (verbose == pdc_true)
pdc_error(p->pdc, -1, 0, 0, 0, 0);
return -1;
}
if (p->fonts[slot].encoding != enc)
slot = pdf_handle_t3font(p, fontname, enc, slot);
return slot;
}
else if (p->fonts[slot].monospace == font->monospace)
{
if (p->fonts[slot].encoding == enc &&
p->fonts[slot].codepage == font->codepage)
{
return slot;
}
else
{
char *encname, *adaptname;
int kc;
/* Comparing apiname of encoding */
if (!strcmp(encoding, p->fonts[slot].encapiname))
return slot;
/* Name of adapted to font encoding */
encname = (char *) pdf_get_encoding_name(p, enc, font);
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);
kc = strcmp(adaptname, pdf_get_encoding_name(p,
p->fonts[slot].encoding, &p->fonts[slot]));
pdc_free_tmp(p->pdc, adaptname);
if (!kc)
return slot;
}
}
}
}
/* 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, PDC_E_ILLARG_TOOLONG, "fontname",
pdc_errprintf(p->pdc, "%d", PDF_MAX_FONTNAME), 0, 0);
pdf_cleanup_font(p, font);
if (verbose)
pdc_error(p->pdc, -1, 0, 0, 0, 0);
return -1;
}
strcpy(mastername, fontname);
/* A Multiple Master font was requested */
if ((mmparam = strstr(mastername, "MM_")) != NULL)
{
if (font->embedding)
{
pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDMM, fontname, 0, 0, 0);
pdf_cleanup_font(p, font);
if (verbose)
pdc_error(p->pdc, -1, 0, 0, 0, 0);
return -1;
}
mmparam[2] = '\0'; /* strip the parameter from the master name */
}
/* Font with vertical writing mode */
fontname_p = mastername;
if (mastername[0] == '@')
{
font->vertical = pdc_true;
fontname_p = &mastername[1];
}
/* protocol */
pdc_trace_protocol(p->pdc, 1, trc_font,
"\n\tPDFlib fontname: \"%s\"\n", fontname_p);
/* API font name */
font->apiname = pdc_strdup(p->pdc, fontname);
/* UTF-8 font name with BOM */
font->utf8name = pdc_strdup(p->pdc, fo->fontname);
/* specified encoding name */
font->encapiname = pdc_strdup(p->pdc, encoding);
/* 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 = pdf_find_resource(p, "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 = pdf_find_resource(p, "FontOutline", fontname_p);
*sf = ittc;
}
}
if (filename)
{
outfilename = filename;
retval = pdf_check_tt_font(p, filename, fontname_p, font);
if (retval == pdc_undef)
{
retval = pdc_false;
break;
}
if (retval == pdc_true)
{
retval = pdf_get_metrics_tt(p, font, fontname_p, enc, filename);
break;
}
}
#endif /* PDF_TRUETYPE_SUPPORTED */
/* Check specified AFM file */
filename = pdf_find_resource(p, "FontAFM", fontname_p);
if (filename)
{
retval = pdf_get_metrics_afm(p, font, fontname_p, enc, filename);
if (retval == pdc_undef)
retval = pdc_false;
break;
}
/* Check specified PFM file */
filename = pdf_find_resource(p, "FontPFM", fontname_p);
if (filename)
{
retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, filename);
if (retval == pdc_undef)
retval = pdc_false;
break;
}
/* Check available in-core metrics */
retval = pdf_get_metrics_core(p, font, fontname_p, enc);
if (retval != pdc_undef)
break;
retval = pdc_false;
/* tSearching for a metric file */
pdc_trace_protocol(p->pdc, 1, trc_font,
"\tSearching for font metric data file:\n");
font->verbose_open = pdc_false;
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)
{
case font_ttot:
retval = pdf_check_tt_font(p, filename, fontname_p, font);
if (retval == pdc_true)
retval = pdf_get_metrics_tt(p, font, fontname_p, enc,
filename);
break;
case font_afm:
retval = pdf_get_metrics_afm(p, font, fontname_p, enc,
filename);
break;
case font_pfm:
retval = pdf_get_metrics_pfm(p, font, fontname_p, enc,
filename);
break;
default:
break;
}
if (retval != pdc_undef)
{
if (pdf_extension_names[i].code == font_ttot)
outfilename = filename;
break;
}
}
if (retval == pdc_undef)
{
pdc_set_errmsg(p->pdc, PDF_E_FONT_NOMETRICS, fontname, 0, 0, 0);
pdc_trace_protocol(p->pdc, 1, trc_font,
"\tMetric data file for font \"%s\" not found\n", fontname);
if (verbose)
{
pdf_cleanup_font(p, font);
pdc_error(p->pdc, -1, 0, 0, 0, 0);
}
retval = pdc_false;
}
break;
}
if (retval == pdc_false)
{
pdf_cleanup_font(p, font);
return -1;
}
/* store instance name instead of master name in the font structure */
if (mmparam)
{
pdc_free(p->pdc, font->name);
font->name = pdc_strdup(p->pdc, fontname);
}
/* If embedding was requested, check font file (or raise an exception) */
font->verbose_open = font->verbose;
if (font->embedding)
{
if (font->img == NULL)
{
char fullname[PDC_FILENAMELEN];
pdc_file *fp = NULL;
retval = pdc_false;
if (outfilename)
{
/* Font outline file specified */
if (font->type == pdc_Type1 || font->type == pdc_MMType1)
{
retval = pdf_t1open_fontfile(p, font, outfilename, NULL);
}
else
{
fp = pdf_fopen_name(p, outfilename, fullname, "font ", 0);
if (fp != NULL)
retval = pdc_true;
}
}
else
{
/* Searching font outline file */
pdc_trace_protocol(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->type == pdc_Type1 || font->type == pdc_MMType1)
{
if (pdf_extension_names[i].code == font_pfab)
{
retval = pdf_t1open_fontfile(p, font, outfilename,
NULL);
}
}
else if (pdf_extension_names[i].code == font_ttot)
{
fp = pdf_fopen_name(p, outfilename, fullname, NULL, 0);
if (fp != NULL)
retval = pdc_true;
}
if (retval == pdc_true)
break;
}
if (retval == pdc_false)
{
pdc_set_errmsg(p->pdc, PDF_E_FONT_NOOUTLINE, fontname,
0, 0, 0);
}
}
if (retval == pdc_true && fp != NULL)
{
if (pdc_file_isvirtual(fp) == pdc_true)
{
font->imgname = pdc_strdup(p->pdc, outfilename);
pdf_lock_pvf(p, font->imgname);
}
else
font->fontfilename = pdc_strdup(p->pdc, fullname);
pdc_fclose(fp);
}
if (retval == pdc_false)
{
pdc_trace_protocol(p->pdc, 1, trc_font,
"\tOutline data file for font \"%s\" not found\n",
fontname);
if (verbose)
{
pdf_cleanup_font(p, font);
pdc_error(p->pdc, -1, 0, 0, 0, 0);
}
}
else
pdc_trace_protocol(p->pdc, 1, trc_font,
"\tFont outline data file \"%s\" available\n",
font->fontfilename ? font->fontfilename : font->imgname);
}
}
else if (font->img)
{
if (!font->imgname)
pdc_free(p->pdc, font->img);
else
{
pdf_unlock_pvf(p, font->imgname);
pdc_free(p->pdc, font->imgname);
font->imgname = NULL;
}
font->img = NULL;
font->filelen = 0;
}
if (retval && font->monospace && font->embedding)
{
pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0);
if (font->verbose == pdc_true)
{
pdf_cleanup_font(p, font);
pdc_error(p->pdc, -1, 0, 0, 0, 0);
}
retval = pdc_false;
}
if (retval == pdc_false)
{
pdf_cleanup_font(p, font);
return -1;
}
if (font->encoding != enc_old)
pdc_trace_protocol(p->pdc, 1, trc_encoding,
"\tDetermined font encoding: \"%s\"\n",
pdf_get_user_encoding(p, font->encoding));
/* Now everything is fine; fill the remaining font cache entries */
p->fonts_number++;
font->verbose_open = pdc_true;
if (enc >= 0)
p->encodings[enc].ev->flags |= PDC_ENC_USED;
pdf_font_issemantic(p, font);
if (!fo->auxiliary)
font->obj_id = pdc_alloc_id(p->out);
return slot;
}
int
pdf__get_glyphid(PDF *p, int font, int code)
{
int gid = 0;
if (font < 0 || font >= p->fonts_number)
pdc_error(p->pdc, PDC_E_ILLARG_INT,
"font", pdc_errprintf(p->pdc, "%d", font), 0, 0);
if (code < 0 || code >= p->fonts[font].numOfCodes)
pdc_error(p->pdc, PDC_E_ILLARG_INT,
"code", pdc_errprintf(p->pdc, "%d", code), 0, 0);
if (p->fonts[font].code2GID)
gid = p->fonts[font].code2GID[code];
else
pdc_error(p->pdc, PDF_E_FONT_NOGLYPHID, p->fonts[font].apiname, 0, 0,0);
return gid;
}
const char *
pdf_get_pdf_fontname(pdc_font *font)
{
const char *name;
name = pdc_get_abb_std_fontname(font->name);
if (!name)
{
name = pdf_get_abb_cjk_fontname(font->name);
}
if (!name)
{
switch (font->type)
{
case pdc_TrueType:
case pdc_Type1C:
case pdc_CIDFontType2:
case pdc_CIDFontType0:
name = font->ttname;
break;
default:
name = font->name;
break;
}
}
return (const char *) name;
}
const char *
pdf_get_encoding_name(PDF *p, pdc_encoding enc, pdc_font *font)
{
const char *apiname = pdc_get_fixed_encoding_name(enc);
if (!apiname[0] && enc >= 0)
apiname = (const char *) p->encodings[enc].ev->apiname;
else if (enc == pdc_cid && font != NULL && font->cmapname != NULL)
apiname = pdc_errprintf(p->pdc, "%.*s",
PDC_ET_MAXSTRLEN, font->cmapname);
return apiname;
}
void
pdf_transform_fontwidths(PDF *p, pdc_font *font, pdc_encodingvector *evto,
pdc_encodingvector *evfrom)
{
int widths[256];
int i, j;
for (i = 0; i < 256; i++)
widths[i] = font->defWidth;
for (i = 0; i < 256; i++)
{
j = (int) pdc_transform_bytecode(p->pdc, evto, evfrom, (pdc_byte)i);
widths[j] = font->widths[i];
}
widths[0] = font->defWidth;
memcpy(font->widths, widths, 256 * sizeof(int));
}
static void
pdf_write_fontdescriptor(
PDF *p,
pdc_font *font,
int missingwidth,
pdc_id fontdescriptor_id,
pdc_id fontfile_id)
{
/*
* 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, "/Ascent %d\n", font->ascender);
pdc_printf(p->out, "/CapHeight %d\n", font->capHeight);
pdc_printf(p->out, "/Descent %d\n", font->descender);
pdc_printf(p->out, "/Flags %ld\n", font->flags);
pdc_printf(p->out, "/FontBBox[%d %d %d %d]\n",
(int) font->llx, (int) font->lly, (int) font->urx, (int) font->ury);
pdc_printf(p->out, "/FontName");
pdf_put_pdfname(p, font->name);
pdc_puts(p->out, "\n");
pdc_printf(p->out, "/ItalicAngle %d\n", (int) (font->italicAngle));
pdc_printf(p->out, "/StemV %d\n", font->StdVW);
if (font->StdHW > 0)
pdc_printf(p->out, "/StemH %d\n", font->StdHW);
if (font->xHeight > 0)
pdc_printf(p->out, "/XHeight %d\n", font->xHeight);
if (missingwidth > 0)
pdc_printf(p->out, "/MissingWidth %d\n", missingwidth);
if (fontfile_id != PDC_BAD_ID)
{
switch(font->type)
{
case pdc_Type1:
case pdc_MMType1:
pdc_objref(p->out, "/FontFile", fontfile_id);
break;
#ifdef PDF_TRUETYPE_SUPPORTED
case pdc_TrueType:
case pdc_CIDFontType2:
pdc_objref(p->out, "/FontFile2", fontfile_id);
break;
case pdc_Type1C:
case pdc_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, pdc_font *font)
{
const char *fontname = font->name;
pdc_id fontdescriptor_id = PDC_BAD_ID;
pdc_id fontfile_id = PDC_BAD_ID;
pdc_id encoding_id = PDC_BAD_ID;
pdc_id descendant_id = PDC_BAD_ID;
pdc_encoding enc = font->encoding;
pdc_bool standard_font = pdc_false;
pdc_bool comp_font = pdc_false;
pdc_scalar a = 1.0;
PDF_data_source src;
/* save font struct members */
pdc_encoding font_encoding = font->encoding;
int font_numOfCodes = font->numOfCodes;
int font_codeSize = font->codeSize;
int missingwidth = 0;
int i;
/* ID for embedded font */
if (font->embedding)
{
switch(font->type)
{
case pdc_Type1:
case pdc_MMType1:
case pdc_TrueType:
case pdc_CIDFontType2:
case pdc_Type1C:
case pdc_CIDFontType0:
fontfile_id = pdc_alloc_id(p->out);
break;
default:
break;
}
}
else if (font->type == pdc_Type1)
{
/* check whether we have one of the 14 standard fonts */
standard_font = pdc_is_standard_font(fontname);
}
/*
* 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 */
switch (font->type)
{
case pdc_Type1:
pdc_puts(p->out, "/Subtype/Type1\n");
break;
case pdc_MMType1:
pdc_puts(p->out, "/Subtype/MMType1\n");
break;
case pdc_TrueType:
pdc_puts(p->out, "/Subtype/TrueType\n");
fontname = font->ttname;
break;
case pdc_Type1C:
fontname = font->ttname;
pdc_puts(p->out, "/Subtype/Type1\n");
break;
case pdc_CIDFontType2:
case pdc_CIDFontType0:
fontname = font->ttname;
pdc_puts(p->out, "/Subtype/Type0\n");
comp_font = pdc_true;
break;
case pdc_Type3:
pdc_puts(p->out, "/Subtype/Type3\n");
break;
default:
break;
}
/* /Name */
if (font->type == pdc_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 (font->type)
{
case pdc_Type1:
case pdc_MMType1:
case pdc_TrueType:
case pdc_Type1C:
case pdc_CIDFontType2:
case pdc_CIDFontType0:
{
pdc_puts(p->out, "/BaseFont");
pdf_put_pdfname(p, fontname);
if (font->cmapname)
pdc_printf(p->out, "-%s", font->cmapname);
if (font->style != pdc_Normal && !comp_font)
pdc_printf(p->out, ",%s",
pdc_get_keyword(font->style, pdf_fontstyle_pdfkeylist));
pdc_puts(p->out, "\n");
}
break;
/* /FontBBox, /FontMatrix, /CharProcs /Resources */
case pdc_Type3:
pdc_printf(p->out, "/FontBBox[%f %f %f %f]\n",
font->t3font->bbox.llx, font->t3font->bbox.lly,
font->t3font->bbox.urx, font->t3font->bbox.ury);
pdc_printf(p->out, "/FontMatrix[%f %f %f %f %f %f]\n",
font->t3font->matrix.a, font->t3font->matrix.b,
font->t3font->matrix.c, font->t3font->matrix.d,
font->t3font->matrix.e, font->t3font->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->t3font->matrix.a;
break;
default:
break;
}
/* changing 8-bit font encoding to winansi */
if (font->towinansi != pdc_invalidenc)
{
pdf_transform_fontwidths(p, font,
pdf_get_encoding_vector(p, font->towinansi),
pdf_get_encoding_vector(p, enc));
enc = font->towinansi;
font->encoding = enc;
}
/* /FontDescriptor, /FirstChar, /LastChar, /Widths */
switch (font->type)
{
case pdc_Type1:
if (standard_font == pdc_true) break;
case pdc_MMType1:
case pdc_TrueType:
case pdc_Type1C:
{
fontdescriptor_id = pdc_alloc_id(p->out);
pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id);
}
case pdc_Type3:
{
int firstchar = 0;
int lastchar = 255;
int defwidth = 0;
/* 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->embedding)
{
if (font->type != pdc_Type3)
defwidth = font->widths[0];
for (i = 1; i < 255; i++)
{
if (font->widths[i] != defwidth)
break;
}
if (i > 1)
firstchar = i;
for (i = 255; i > 0; i--)
{
if (i == firstchar || font->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->widths[i] / a + 0.5));
if (i < 255)
pdc_printf(p->out, "%s", ((i + 1) % 16) ? " " : "\n");
}
pdc_end_array(p->out);
}
break;
default:
break;
}
/* /Encoding */
switch (font->type)
{
case pdc_Type1:
case pdc_MMType1:
case pdc_TrueType:
case pdc_Type1C:
if (enc == pdc_winansi && !font->used_in_formfield)
{
pdc_printf(p->out, "/Encoding/WinAnsiEncoding\n");
break;
}
if (enc == pdc_macroman && font->hasnomac == pdc_false &&
!font->used_in_formfield)
{
pdc_printf(p->out, "/Encoding/MacRomanEncoding\n");
break;
}
case pdc_Type3:
if (enc >= 0)
{
if (p->encodings[enc].id == PDC_BAD_ID)
p->encodings[enc].id = pdc_alloc_id(p->out);
encoding_id = p->encodings[enc].id;
}
if (encoding_id != PDC_BAD_ID)
pdc_objref(p->out, "/Encoding", encoding_id);
break;
case pdc_CIDFontType2:
case pdc_CIDFontType0:
if (font->cmapname)
pdc_printf(p->out, "/Encoding/%s\n", font->cmapname);
break;
default:
break;
}
/* /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 *charname;
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 *ev = pdf_get_encoding_vector(p, enc);
pdc_encodingvector *evb = NULL;
pdf_set_encoding_glyphnames(p, enc);
/* See Implementation Note 46. The restrictions described there
* are also valid for Acrobat versions up to now.
*/
if (font->type != pdc_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 = pdf_get_encoding_vector(p, pdc_winansi);
}
else if (!strncmp(ev->apiname, PDC_ENC_MODMACROMAN,
strlen(PDC_ENC_MODMACROMAN)))
{
pdc_puts(p->out, "/BaseEncoding/MacRomanEncoding\n");
evb = pdf_get_encoding_vector(p, pdc_macroman);
}
else
{
/* /BaseEncoding/StandardEncoding */
evb = pdf_get_encoding_vector(p, pdc_stdenc);
}
}
if (evb != NULL)
{
int iv = -1;
for (i = 0; i < font->numOfCodes; i++)
{
charname = ev->chars[i];
pdc_get_alter_glyphname(ev->codes[i], font->missingglyphs,
&charname);
/* enforce first three names because of bug in Acrobat 6 */
if (i < 3 ||
(charname && !evb->chars[i]) ||
(!charname && evb->chars[i]) ||
(charname && evb->chars[i] &&
strcmp(charname, 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, charname);
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->numOfCodes; i++)
{
charname = ev->chars[i];
pdc_get_alter_glyphname(ev->codes[i], font->missingglyphs,
&charname);
pdf_put_pdfname(p, charname);
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 & pdf_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 (font->type == pdc_CIDFontType0)
pdc_puts(p->out, "/Subtype/CIDFontType0\n");
if (font->type == pdc_CIDFontType2)
pdc_puts(p->out, "/Subtype/CIDFontType2\n");
/* /BaseFont */
pdc_puts(p->out, "/BaseFont");
pdf_put_pdfname(p, fontname);
if (font->style != pdc_Normal)
pdc_printf(p->out, ",%s",
pdc_get_keyword(font->style, 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, pdf_get_ordering_cid(p, font));
pdc_printf(p->out, "/Supplement %d>>\n",
pdf_get_supplement_cid(p, font));
/* /FontDescriptor */
fontdescriptor_id = pdc_alloc_id(p->out);
pdc_objref(p->out, "/FontDescriptor", fontdescriptor_id);
/* /DW /W */
#ifdef PDF_CJKFONTWIDTHS_SUPPORTED
if (font->standardcjk)
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,
fontfile_id);
/*
* Font embedding
*/
if (fontfile_id != PDC_BAD_ID)
{
pdc_id length_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(font->type)
{
case pdc_Type1:
case pdc_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 pdc_TrueType:
case pdc_CIDFontType2:
{
length1_id = pdc_alloc_id(p->out);
}
case pdc_Type1C:
case pdc_CIDFontType0:
{
src.private_data = (void *) font->fontfilename;
if (font->fontfilename)
{
/* 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(font->type)
{
case pdc_TrueType:
case pdc_CIDFontType2:
src.offset = (long) 0;
src.length = (long) 0;
break;
case pdc_Type1C:
case pdc_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(font->type)
{
case pdc_TrueType:
case pdc_CIDFontType2:
src.buffer_start = font->img;
src.buffer_length = font->filelen;
break;
case pdc_Type1C:
case pdc_CIDFontType0:
src.buffer_start = font->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(font->type)
{
case pdc_Type1:
case pdc_MMType1:
break;
#ifdef PDF_TRUETYPE_SUPPORTED
case pdc_TrueType:
case pdc_CIDFontType2:
case pdc_Type1C:
case pdc_CIDFontType0:
if (font->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(font->type == pdc_Type1C)
pdc_puts(p->out, "/Subtype/Type1C\n");
if (font->type == pdc_CIDFontType0)
pdc_puts(p->out, "/Subtype/CIDFontType0C\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(font->type)
{
case pdc_Type1:
case pdc_MMType1:
pdf_put_length_objs(p, &src, length1_id, length2_id, length3_id);
break;
#ifdef PDF_TRUETYPE_SUPPORTED
case pdc_TrueType:
case pdc_CIDFontType2:
if (compress)
{
pdc_begin_obj(p->out, length1_id); /* Length1 obj */
pdc_printf(p->out, "%ld\n", (long) font->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 & pdf_flush_content)
pdc_flush_stream(p->out);
/* restore font struct members */
font->encoding = font_encoding;
font->numOfCodes = font_numOfCodes;
font->codeSize = font_codeSize;
}
void
pdf_write_doc_fonts(PDF *p)
{
int slot;
/* output pending font objects */
for (slot = 0; slot < p->fonts_number; slot++)
{
pdc_font *font = &p->fonts[slot];
switch(font->type)
{
case pdc_Type1:
case pdc_MMType1:
#ifdef PDF_TRUETYPE_SUPPORTED
case pdc_TrueType:
case pdc_CIDFontType2:
case pdc_Type1C:
#endif /* PDF_TRUETYPE_SUPPORTED */
case pdc_CIDFontType0:
case pdc_Type3:
if (font->obj_id != PDC_BAD_ID)
{
if (font->encoding == pdc_invalidenc ||
font->used_in_current_doc == pdc_false)
{
/*
* 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 (pdc_trace_protocol_is_enabled(p->pdc, 1, trc_font))
{
pdc_trace(p->pdc, "\tProcessing font %d: ", slot);
pdc_trace(p->pdc, "\"%s\" with encoding \"%s\"\n",
font->name,
pdf_get_encoding_name(p, font->encoding, font));
}
pdf_put_font(p, font);
}
}
break;
default:
break;
}
}
}
void
pdf_write_page_fonts(PDF *p)
{
int i, total = 0;
/* 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)
{
pdc_puts(p->out, "/Font");
pdc_begin_dict(p->out); /* font resource dict */
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", i);
pdc_objref(p->out, "", p->fonts[i].obj_id);
}
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 n)
{
p->fonts[n].used_on_current_page = pdc_true;
}