/*---------------------------------------------------------------------------* | 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.2 2009/10/20 18:12:26 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[PDC_GEN_BUFSIZE]; pdc->uniqueno++; pdc_sprintf(pdc, pdc_false, 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}, {"0", FNT_FW_DONTCARE}, {"100", FNT_FW_THIN}, {"200", FNT_FW_EXTRALIGHT}, {"300", FNT_FW_LIGHT}, {"400", FNT_FW_NORMAL}, {"500", FNT_FW_MEDIUM}, {"600", FNT_FW_SEMIBOLD}, {"700", FNT_FW_BOLD}, {"800", FNT_FW_EXTRABOLD}, {"900", 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); } }