guy 3bf951f42c Patch level : 10.0
Files correlati     : pdflib
Ricompilazione Demo : [ ]
Commento            :
Aggiornata pdflib.dll alla versione 7.0.4


git-svn-id: svn://10.65.10.50/trunk@18580 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-03-23 08:55:58 +00:00

411 lines
12 KiB
C
Executable File

/*---------------------------------------------------------------------------*
| 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_pfm.c,v 1.4 2009-03-23 08:55:35 guy Exp $
*
* PDFlib routines for fast reading of PFM font metrics files
*
*/
#include "p_intern.h"
#include "p_font.h"
/* read data types from the PFM */
#define PFM_BYTE(offset) pfm[offset]
#define PFM_WORD(offset) PDC_GET_WORD(&pfm[offset])
#define PFM_SHORT(offset) PDC_GET_SHORT(&pfm[offset])
#define PFM_DWORD(offset) PDC_GET_DWORD3(&pfm[offset])
/* Offsets in the buffer containing the various PFM structures */
#define header_base 0
#define header_dfVersion (PFM_WORD(header_base + 0))
#define header_dfSize (PFM_DWORD(header_base + 2))
#define header_dfAscent (PFM_WORD(header_base + 74))
#define header_dfItalic (PFM_BYTE(header_base + 80))
#define header_dfWeight (PFM_WORD(header_base + 83))
#define header_dfCharSet (PFM_BYTE(header_base + 85))
#define header_dfPitchAndFamily (PFM_BYTE(header_base + 90))
#define header_dfMaxWidth (PFM_WORD(header_base + 93))
#define header_dfFirstChar (PFM_BYTE(header_base + 95))
#define header_dfLastChar (PFM_BYTE(header_base + 96))
#define header_dfDefaultChar (PFM_BYTE(header_base + 97))
#define ext_base 117
#define ext_dfExtentTable (PFM_DWORD(ext_base + 6))
#define ext_dfKernPairs (PFM_DWORD(ext_base + 14))
#define ext_dfKernTrack (PFM_DWORD(ext_base + 18))
#define ext_dfDriverInfo (PFM_DWORD(ext_base + 22))
#define etm_base 147
#define etmCapHeight (PFM_SHORT(etm_base + 14))
#define etmXHeight (PFM_SHORT(etm_base + 16))
#define etmLowerCaseAscent (PFM_SHORT(etm_base + 18))
#define etmLowerCaseDescent (PFM_SHORT(etm_base + 20))
#define etmSlant (PFM_SHORT(etm_base + 22))
#define etmUnderlineOffset (PFM_SHORT(etm_base + 32))
#define etmUnderlineWidth (PFM_SHORT(etm_base + 34))
#define dfDevice 199
/* Windows font descriptor flags */
#define PDF_FIXED_PITCH 0x01 /* Fixed width font; rarely used flag */
#define PDF_DONTCARE 0x00 /* Don't care or don't know. */
#define PDF_ROMAN 0x10 /* Variable stroke width, serifed */
#define PDF_SWISS 0x20 /* Variable stroke width, sans-serifed */
#define PDF_MODERN 0x30 /* fixed pitch */
#define PDF_SCRIPT 0x40 /* Cursive, etc. */
#define PDF_DECORATIVE 0x50 /* Old English, etc. */
/* Windows character set flags */
#define PFM_ANSI_CHARSET 0
#define PFM_SYMBOL_CHARSET 2
#define PFM_GREEK_CHARSET 161
#define PFM_TURKISH_CHARSET 162
#define PFM_VIETNAMESE_CHARSET 163
#define PFM_HEBREW_CHARSET 177
#define PFM_ARABIC_CHARSET 178
#define PFM_BALTIC_CHARSET 186
#define PFM_RUSSIAN_CHARSET 204
#define PFM_THAI_CHARSET 222
#define PFM_EASTEUROPE_CHARSET 238
static const pdc_keyconn pdf_charset_keylist[] =
{
{"winansi", PFM_ANSI_CHARSET },
{"", PFM_SYMBOL_CHARSET },
{"cp1253", PFM_GREEK_CHARSET },
{"cp1254", PFM_TURKISH_CHARSET },
{"cp1258", PFM_VIETNAMESE_CHARSET},
{"cp1255", PFM_HEBREW_CHARSET },
{"cp1256", PFM_ARABIC_CHARSET },
{"cp1257", PFM_BALTIC_CHARSET },
{"cp1251", PFM_RUSSIAN_CHARSET },
{"cp874", PFM_THAI_CHARSET },
{"cp1250", PFM_EASTEUROPE_CHARSET},
{NULL, 0},
};
#define PDF_STRING_PostScript \
((const char*) "\120\157\163\164\123\143\162\151\160\164")
/*
* Kerning pairs
*/
typedef struct kern_
{
pdc_byte first; /* First character */
pdc_byte second; /* Second character */
pdc_byte kern[2]; /* Kern distance */
}
KERN;
pdc_bool
pdf_check_pfm_encoding(PDF *p, pdf_font *font, pdc_encoding enc)
{
const char *encname =
pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
pdf_get_encoding_name(p, enc, font));
const char *intencname = NULL;
pdc_encoding intenc = pdc_invalidenc;
pdc_bool issymbfont = pdc_undef;
pdc_logg_cond(p->pdc, 2, trc_font,
"\tFont internal charset (dfCharSet): %d\n", font->ft.enc);
/* Font encoding */
intencname = pdc_get_keyword(font->ft.enc, pdf_charset_keylist);
if (intencname == NULL)
{
pdc_set_errmsg(p->pdc, PDF_E_T1_BADCHARSET,
pdc_errprintf(p->pdc, "%d", font->ft.enc), 0, 0, 0);
return pdc_false;
}
if (strlen(intencname))
{
int codepage = 0;
pdc_logg_cond(p->pdc, 2, trc_font,
"\tFont internal encoding \"%s\" found\n", intencname);
intenc = pdc_find_encoding(p->pdc, intencname);
if (intenc == pdc_invalidenc)
intenc = pdc_insert_encoding(p->pdc, intencname, &codepage,
pdc_true);
font->ft.issymbfont = pdc_false;
}
else
{
pdc_logg_cond(p->pdc, 2, trc_font, "\tSymbol font\n");
font->ft.issymbfont = pdc_true;
intenc = pdc_builtin;
/* auto */
if (!strcmp(font->encapiname, "auto"))
{
issymbfont = pdc_true;
enc = pdc_builtin;
}
}
/* builtin */
if (enc == pdc_builtin)
issymbfont = pdc_true;
/* unicode */
if (enc == pdc_unicode)
{
font->unibyte = pdc_true;
issymbfont = pdc_false;
enc = intenc;
}
/* encoding is subset of 8-bit encoding */
if (enc >= pdc_winansi && intenc >= pdc_winansi)
{
if (pdc_is_encoding_subset(p->pdc, pdc_get_encoding_vector(p->pdc, enc),
pdc_get_encoding_vector(p->pdc, intenc)))
{
if (enc != pdc_winansi && intenc == pdc_winansi &&
strcmp(encname, "iso8859-1"))
{
font->towinansi = intenc;
}
else
{
enc = intenc;
}
issymbfont = pdc_false;
}
}
/* illegal encoding */
if (issymbfont == pdc_undef || font->ft.issymbfont == pdc_undef)
{
pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 0, 0, 0, 0);
return pdc_false;
}
font->ft.enc = enc;
if (issymbfont && !font->ft.issymbfont)
{
pdc_warning(p->pdc, PDF_E_FONT_FORCEENC,
pdf_get_encoding_name(p, intenc, NULL),
0, 0, 0);
font->ft.enc = intenc;
}
if (!issymbfont && font->ft.issymbfont)
{
pdc_warning(p->pdc, PDF_E_FONT_FORCEENC,
pdf_get_encoding_name(p, pdc_builtin, NULL),
0, 0, 0);
font->ft.enc = pdc_builtin;
font->towinansi = pdc_invalidenc;
}
if (font->towinansi != pdc_invalidenc)
pdf_transform_fontwidths(p, font,
pdc_get_encoding_vector(p->pdc, font->ft.enc),
pdc_get_encoding_vector(p->pdc, font->towinansi));
return pdc_true;
}
/*
* Currently we do not populate the following fields correctly:
* - serif flag
*/
static pdc_bool
pdf_parse_pfm(PDF *p, pdc_file *fp, pdf_font *font)
{
static const char fn[] = "pdf_parse_pfm";
fnt_font_metric *ftm = &font->ft.m;
size_t length;
pdc_byte *pfm;
pdc_bool ismem;
int i, dfFirstChar, dfLastChar, default_width;
unsigned long dfExtentTable;
/* read whole file and close it */
pfm = (pdc_byte *) pdc_freadall(fp, &length, &ismem);
pdc_fclose(fp);
/* check whether this is really a valid PostScript PFM file */
if (pfm == NULL ||
(header_dfVersion != 0x100 && header_dfVersion != 0x200) ||
dfDevice > length ||
strncmp((const char *) pfm + dfDevice, PDF_STRING_PostScript, 10) ||
ext_dfDriverInfo > length)
{
if (!ismem)
pdc_free(p->pdc, pfm);
return pdc_false;
}
/* fetch relevant data from the PFM */
ftm->type = fnt_Type1;
font->ft.name = pdc_strdup(p->pdc, (const char *)pfm + ext_dfDriverInfo);
ftm->name = pdc_strdup(p->pdc, font->ft.name);
pdc_logg_cond(p->pdc, 1, trc_font,
"\tPostScript font name: \"%s\"\n", ftm->name);
switch (header_dfPitchAndFamily & 0xF0)
{
case PDF_ROMAN:
ftm->flags |= FNT_SERIF;
break;
case PDF_MODERN:
/* Has to be ignored, contrary to MS's specs */
break;
case PDF_SCRIPT:
ftm->flags |= FNT_SCRIPT;
break;
case PDF_DECORATIVE:
/* the dfCharSet flag lies in this case... */
header_dfCharSet = PFM_SYMBOL_CHARSET;
break;
case PDF_SWISS:
case PDF_DONTCARE:
default:
break;
}
/* temporarily */
font->ft.enc = (pdc_encoding) header_dfCharSet;
dfFirstChar = header_dfFirstChar;
dfLastChar = header_dfLastChar;
dfExtentTable = ext_dfExtentTable;
/*
* Some rare PFMs do not contain any ExtentTable if the fixed pitch flag
* is set. Use the dfMaxWidth entry for all glyphs in this case.
* If the user forced the font to be monospaced we use this value instead.
*/
if ((!(header_dfPitchAndFamily & PDF_FIXED_PITCH) && dfExtentTable == 0) ||
font->opt.monospace)
{
ftm->isFixedPitch = pdc_true;
default_width = font->opt.monospace ? font->opt.monospace :
(int) header_dfMaxWidth;
}
else
{
/* default values -- don't take the width of the default character */
default_width = FNT_DEFAULT_WIDTH;
}
font->ft.numcodes = 256;
ftm->numwidths = font->ft.numcodes;
ftm->widths = (int *) pdc_calloc(p->pdc, ftm->numwidths * sizeof(int), fn);
for (i = 0; i < font->ft.numcodes; i++)
ftm->widths[i] = default_width;
if (!ftm->isFixedPitch)
{
if (ext_dfExtentTable == 0 ||
ext_dfExtentTable + 2 * (header_dfLastChar-header_dfFirstChar) + 1 >
length)
{
if (!ismem)
pdc_free(p->pdc, pfm);
return pdc_false;
}
for (i = dfFirstChar; i <= dfLastChar; i++)
ftm->widths[i] =
(int) PFM_WORD(dfExtentTable + 2 * (i - dfFirstChar));
/*
* Check whether the font is actually opt.monospaced
* (the fixed pitch flag is not necessarily set)
*/
default_width = ftm->widths[dfFirstChar];
for (i = dfFirstChar+1; i <= dfLastChar; i++)
if (default_width != ftm->widths[i])
break;
if (i == dfLastChar + 1)
ftm->isFixedPitch = pdc_true;
}
font->ft.weight = fnt_check_weight(header_dfWeight);
ftm->defwidth = default_width;
ftm->italicAngle = (header_dfItalic ? etmSlant/(10.0) : 0.0);
ftm->capHeight = etmCapHeight;
ftm->xHeight = etmXHeight;
ftm->descender = -etmLowerCaseDescent;
ftm->ascender = (int) header_dfAscent;
ftm->underlinePosition = -etmUnderlineOffset;
ftm->underlineThickness = etmUnderlineWidth;
ftm->urx = header_dfMaxWidth;
if (!ismem)
pdc_free(p->pdc, pfm);
return pdc_true;
}
pdc_bool
pdf_get_metrics_pfm(
PDF *p,
pdf_font *font,
const char *fontname,
pdc_encoding enc,
const char *filename,
pdc_bool requested)
{
static const char fn[] = "pdf_get_metrics_pfm";
char fullname[PDC_FILENAMELEN];
pdc_file *pfmfile;
(void) fontname;
/* open PFM file */
pfmfile = pdc_fsearch_fopen(p->pdc, filename, fullname, "PFM ",
PDC_FILE_BINARY);
if (pfmfile == NULL)
return pdc_check_fopen_errmsg(p->pdc, requested);
pdc_logg_cond(p->pdc, 1, trc_font,
"\tLoading PFM metric fontfile \"%s\":\n", fullname);
/* Read PFM metrics */
if (!pdf_parse_pfm(p, pfmfile, font))
{
pdc_set_errmsg(p->pdc, PDF_E_FONT_CORRUPT, "PFM", fullname, 0, 0);
return pdc_false;
}
/* save full filename */
font->metricfilename = pdc_strdup_ext(p->pdc, fullname, 0, fn);
/* Check encoding */
if (!pdf_check_pfm_encoding(p, font, enc))
return pdc_false;
if (!pdf_make_fontflag(p, font))
return pdc_false;
return pdc_true;
}