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
		
			
				
	
	
		
			411 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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;
 | 
						|
}
 |