diff options
Diffstat (limited to 'src/pdflib/font/ft_font.c')
-rw-r--r-- | src/pdflib/font/ft_font.c | 532 |
1 files changed, 532 insertions, 0 deletions
diff --git a/src/pdflib/font/ft_font.c b/src/pdflib/font/ft_font.c new file mode 100644 index 0000000..53a39a9 --- /dev/null +++ b/src/pdflib/font/ft_font.c @@ -0,0 +1,532 @@ +/*---------------------------------------------------------------------------* + | 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: ft_font.c,v 1.1 2008/10/17 06:10:43 scuri Exp $ + * + * FONT basic font functions + * + */ + +#define FT_FONT_C + +#include "ft_font.h" + + +static pdc_error_info fnt_errors[] = +{ +#define fnt_genInfo 1 +#include "ft_generr.h" +}; + +#define N_FNT_ERRORS (sizeof fnt_errors / sizeof (pdc_error_info)) + +void +fnt_register_errtab(pdc_core *pdc) +{ + pdc_register_errtab(pdc, PDC_ET_FONT, fnt_errors, N_FNT_ERRORS); +} + +static void +fnt_init_font_metric(fnt_font_metric *metric) +{ + metric->name = NULL; + metric->flags = 0L; + metric->type = fnt_unknownType; + metric->charcoll = (int) cc_none; + + /* + * Fill in some reasonable default values in global font info in + * case they're missing from the metrics data. + */ + metric->italicAngle = 0; + metric->isFixedPitch = pdc_false; + metric->llx = FNT_MISSING_FONTVAL; + metric->lly = FNT_MISSING_FONTVAL; + metric->urx = FNT_MISSING_FONTVAL; + metric->ury = FNT_MISSING_FONTVAL; + metric->underlinePosition = -100; + metric->underlineThickness = FNT_DEFAULT_UNDERLINEWIDTH; + metric->ascender = FNT_MISSING_FONTVAL; + metric->descender = FNT_MISSING_FONTVAL; + metric->capHeight = FNT_MISSING_FONTVAL; + metric->xHeight = FNT_MISSING_FONTVAL; + metric->StdHW = 0; + metric->StdVW = 0; + + metric->defwidth = FNT_DEFAULT_WIDTH; + metric->numwidths = 0; + metric->widths = NULL; + metric->numinters = 0; + metric->ciw = NULL; + metric->numglwidths = 0; + metric->glw = NULL; + +} + +void +fnt_init_font(fnt_font *font) +{ + fnt_init_font_metric(&font->m); + + font->name = NULL; + font->utf8name = NULL; + font->filename = NULL; + font->isstdfont = pdc_false; + font->ishostfont = pdc_false; + font->issymbfont = pdc_true; + font->hasdescr = pdc_false; + font->vertical = pdc_false; + font->spacechar = 0; + font->spacewidth = 0; + font->linegap = FNT_MISSING_FONTVAL; + font->weight = 0; + font->vertical = pdc_false; + pdc_identity_matrix(&font->matrix); + font->bbox.llx = 0; + font->bbox.lly = 0; + font->bbox.urx = 0; + font->bbox.ury = 0; + font->fsscale = 1.0; + font->enc = pdc_invalidenc; + font->numglyphs = 0; + font->numcodes = 0; + font->gid2code = NULL; + font->code2gid = NULL; + font->embedded = pdc_false; + font->cmapname = NULL; + font->imgname = NULL; + font->filelen = 0; + font->img = NULL; +} + +static void +fnt_cleanup_font_metric(pdc_core *pdc, fnt_font_metric *metric) +{ + if (metric->name != NULL) + { + pdc_free(pdc, metric->name); + metric->name = NULL; + } + + if (metric->widths != NULL) + { + pdc_free(pdc, metric->widths); + metric->widths = NULL; + } + + if (metric->ciw != NULL) + { + pdc_free(pdc, metric->ciw); + metric->ciw = NULL; + } + + if (metric->glw != NULL) + { + pdc_free(pdc, metric->glw); + metric->glw = NULL; + } + + +} + +void +fnt_cleanup_fontimg(pdc_core *pdc, fnt_font *font) +{ + if (font->img != NULL && font->imgname == NULL) + { + pdc_free(pdc, font->img); + font->img = NULL; + } + + if (font->imgname != NULL) + { + pdc_free(pdc, font->imgname); + font->imgname = NULL; + } +} + +void +fnt_cleanup_font(pdc_core *pdc, fnt_font *font) +{ + int i = 0; + + (void) i; + + fnt_cleanup_font_metric(pdc, &font->m); + + if (font->name != NULL) + { + pdc_free(pdc, font->name); + font->name = NULL; + } + + if (font->utf8name != NULL) + { + pdc_free(pdc, font->utf8name); + font->utf8name = NULL; + } + + if (font->filename != NULL) + { + pdc_free(pdc, font->filename); + font->filename = NULL; + } + + /* delete font specific encoding vector */ + if (font->enc >= pdc_firstvarenc) + { + pdc_encodingvector *ev = pdc_get_encoding_vector(pdc, font->enc); + + if (ev != NULL && ev->flags & PDC_ENC_FONT) + pdc_remove_encoding_vector(pdc, (int) font->enc); + } + + if (font->gid2code != NULL) + { + pdc_free(pdc, font->gid2code); + font->gid2code = NULL; + } + + if (font->code2gid != NULL) + { + pdc_free(pdc, font->code2gid); + font->code2gid = NULL; + } + + + + if (font->cmapname != NULL) + { + pdc_free(pdc, font->cmapname); + font->cmapname = NULL; + } + + + fnt_cleanup_fontimg(pdc, font); +} + +/* + * we assume: + * code!=0 --> gid=0 --> gid=-1 or code=0 <--> gid=0 + * + */ +int +fnt_get_glyphid(int code, fnt_font *font) +{ + if (code >= 0 && code < font->numcodes) + { + if (font->code2gid != NULL) + { + int gid = font->code2gid[code]; + + if (gid) + return gid; + } + else + { + /* this is temporary. for Type1 fonts there is no information + * about glyphs at present. we assume identity code = glyph id. + */ + return code; + } + } + + if (!code) + return 0; + + return -1; +} + +/* + * we assume: + * gid!=0 --> code=0 --> code=-1 or gid=0 <--> code=0 + * + */ +int +fnt_get_code(int gid, fnt_font *font) +{ + if (gid >= 0 && gid < font->numglyphs) + { + if (font->gid2code != NULL) + { + int code = font->gid2code[gid]; + + if (code) + return code; + } + } + + if (!gid) + return 0; + + return -1; +} + +int +fnt_get_glyphwidth(int code, fnt_font *font) +{ + int i; + + if (font->m.widths != NULL) + { + if (code < font->m.numwidths) + return font->m.widths[code]; + } + else if (font->m.ciw != NULL) + { + fnt_interwidth *wd = font->m.ciw; + int lo = 0; + int hi = font->m.numinters - 1; + + while (lo < hi) + { + i = (lo + hi) / 2; + + if (code >= wd[i].startcode && code < wd[i+1].startcode) + return (int) wd[i].width; + + if (code < wd[i].startcode) + hi = i; + else + lo = i + 1; + } + } + else if (font->m.glw != NULL) + { + for (i = 0; i < font->m.numglwidths; i++) + { + if (font->m.glw[i].unicode == (pdc_ushort) code) + { + return font->m.glw[i].width; + } + } + } + + return FNT_MISSING_WIDTH; +} + +void +fnt_font_logg_widths(pdc_core *pdc, fnt_font *font) +{ + if (font != NULL && + pdc_logg_is_enabled(pdc, 2, trc_font)) + { + int code, width; + + for (code = 0; code < PDC_NUM_UNIVAL; code++) + { + width = fnt_get_glyphwidth(code, font); + if (width == FNT_MISSING_WIDTH) + break; + pdc_logg(pdc, + "\t\tWidth[%d]: %d\n", code, width); + } + } +} + +static const pdc_keyconn pdf_fonttype_pdfkeylist[] = +{ + {"Type0", fnt_Type0}, + {"Type1", fnt_Type1}, + {"MMType1", fnt_MMType1}, + {"TrueType", fnt_TrueType}, + {"CIDFontType2", fnt_CIDFontType2}, + {"Type1C", fnt_Type1C}, + {"CIDFontType0", fnt_CIDFontType0}, + {"CIDFontType0C", fnt_CIDFontType0C}, + {"OpenType", fnt_OpenType}, + {"OpenType", fnt_OpenTypeC}, + {"Type3", fnt_Type3}, + {"(unknown)", fnt_unknownType}, + {NULL, 0} +}; + +int +fnt_get_pdf_fonttype_code(const char *typenam) +{ + int type = pdc_get_keycode(typenam, pdf_fonttype_pdfkeylist); + return (type != PDC_KEY_NOTFOUND) ? type : fnt_unknownType; +} + +const char * +fnt_get_pdf_fonttype_name(int typecode) +{ + const char *name = pdc_get_keyword(typecode, pdf_fonttype_pdfkeylist); + return name ? name : ""; +} + +static const pdc_keyconn pdf_fonttype_descrkeylist[] = +{ + /* Acrobat 7 names for comparison */ + {"Composite", fnt_Type0}, /* - */ + {"Type 1", fnt_Type1}, /* Type 1 */ + {"Multiple Master", fnt_MMType1}, /* MM */ + {"TrueType", fnt_TrueType}, /* TrueType */ + {"TrueType (CID)", fnt_CIDFontType2}, /* TrueType (CID) */ + {"Type 1 CFF", fnt_Type1C}, /* Type 1 */ + {"Type 1 (CID)", fnt_CIDFontType0}, /* Type 1 (CID) */ + {"Type 1 CFF (CID)",fnt_CIDFontType0C}, /* Type 1 (CID) */ + {"OpenType", fnt_OpenType}, /* OpenType */ + {"OpenType", fnt_OpenTypeC}, + {"Type 3", fnt_Type3}, /* Type 3 */ + {"(unknown)", fnt_unknownType}, + {NULL, 0} +}; + +const char * +fnt_get_pdf_fonttype_desc(int typecode) +{ + const char *name = pdc_get_keyword(typecode, pdf_fonttype_descrkeylist); + return name ? name : ""; +} + +pdc_encodingvector * +fnt_create_font_ev(pdc_core *pdc, fnt_font *font) +{ + pdc_encodingvector *ev = NULL; + char encname[128]; + + pdc->uniqueno++; + sprintf(encname, "encoding_%s_%d", font->name, pdc->uniqueno); + ev = pdc_new_encoding(pdc, encname); + pdc_insert_encoding_vector(pdc, ev); + font->enc = pdc_find_encoding(pdc, encname); + ev->flags |= PDC_ENC_FONT; + + return ev; +} + +int +fnt_check_weight(int weight) +{ + if (weight == PDC_KEY_NOTFOUND) + weight = FNT_FW_NORMAL; + + if (weight > 1000) + weight = 1000; + + if (weight <= 10) + weight *= 100; + else + weight = 100 * (weight / 100); + + return weight; +} + +static const pdc_keyconn fnt_fontweight_keylist[] = +{ + {"none", FNT_FW_DONTCARE}, + {"thin", FNT_FW_THIN}, + {"extralight", FNT_FW_EXTRALIGHT}, + {"ultralight", FNT_FW_ULTRALIGHT}, + {"light", FNT_FW_LIGHT}, + {"normal", FNT_FW_NORMAL}, + {"regular", FNT_FW_REGULAR}, + {"", FNT_FW_REGULAR}, + {"medium", FNT_FW_MEDIUM}, + {"semibold", FNT_FW_SEMIBOLD}, + {"semi", FNT_FW_SEMIBOLD}, + {"demibold", FNT_FW_DEMIBOLD}, + {"bold", FNT_FW_BOLD}, + {"extrabold", FNT_FW_EXTRABOLD}, + {"extra", FNT_FW_EXTRABOLD}, + {"ultrabold", FNT_FW_ULTRABOLD}, + {"heavy", FNT_FW_HEAVY}, + {"black", FNT_FW_BLACK}, + {NULL, 0} +}; + +int +fnt_weightname2weight(const char *weightname) +{ + return pdc_get_keycode_ci(weightname, fnt_fontweight_keylist); +} + +const char * +fnt_weight2weightname(int weight) +{ + return pdc_get_keyword(weight, fnt_fontweight_keylist); +} + +int +fnt_macfontstyle2weight(int macfontstyle) +{ + return (macfontstyle & (1<<0)) ? FNT_FW_BOLD : FNT_FW_NORMAL; +} + +#define FNT_STEMV_WEIGHT 65.0 + +int +fnt_weight2stemv(int weight) +{ + double w = weight / FNT_STEMV_WEIGHT; + return (int) (FNT_STEMV_MIN + w * w + 0.5); +} + +int +fnt_stemv2weight(int stemv) +{ + double w; + int weight = 0; + + w = (double) (stemv - FNT_STEMV_MIN); + if (w > 0) + weight = (int) (FNT_STEMV_WEIGHT * sqrt(w) + 0.5); + + return weight; +} + +void +fnt_font_logg_protocol(pdc_core *pdc, fnt_font *font) +{ + if (font != NULL && + pdc_logg_is_enabled(pdc, 2, trc_font)) + { + const char *wname = fnt_weight2weightname(font->weight); + char dwname[16]; + + dwname[0] = 0; + if (wname && *wname) + sprintf(dwname, " (%s)", wname); + + pdc_logg(pdc, + "\n" + "\t\tFont type: %s\n" + "\t\tFlags: %d\n" + "\t\tFontBBox: %g,%g %g,%g\n" + "\t\titalicAngle: %g\n" + "\t\tisFixedPitch: %d\n" + "\t\tunderlinePosition: %d\n" + "\t\tunderlineThickness: %d\n" + "\t\tcapHeight: %d\n" + "\t\txHeight: %d\n" + "\t\tascender: %d\n" + "\t\tdescender: %d\n" + "\t\tlinegap: %d\n" + "\t\tweight: %d%s\n" + "\t\tStdVW: %d\n" + "\t\tStdHW: %d\n" + "\t\tdefWidth: %d\n", + fnt_get_pdf_fonttype_name(font->m.type), + font->m.flags, + font->m.llx, font->m.lly, font->m.urx, font->m.ury, + font->m.italicAngle, font->m.isFixedPitch, + font->m.underlinePosition, font->m.underlineThickness, + font->m.capHeight, font->m.xHeight, font->m.ascender, + font->m.descender, font->linegap, font->weight, + dwname, + font->m.StdVW, font->m.StdHW, + font->m.defwidth); + } +} + + |