pdc_bool pdf_get_metrics_tt(PDF *p, pdf_font *font, const char *fontname, pdc_encoding enc, const char *filename) { pdc_bool logg1 = pdc_logg_is_enabled(p->pdc, 1, trc_font); pdc_bool logg2 = pdc_logg_is_enabled(p->pdc, 2, trc_font); int filesize = 0; double kbfilesize = 0; int foundglyphs, flags = 0; tt_file *ttf; pdc_bool retval; pdc_encoding enc_req; pdc_encodingvector *ev = NULL; pdc_bool isotf; int errcode = 0; (void) logg2; /* * Initialisation */ ttf = fnt_new_tt(p->pdc, &font->ft); ttf->filename = filename; ttf->fontname = fontname; ttf->verbose = font->verbose; ttf->incore = pdc_true; ttf->monospace = font->opt.monospace; filesize = font->ft.filelen; kbfilesize = filesize / 1024.0; /* * Read font file */ retval = fnt_read_tt(ttf); if (retval == pdc_false) goto PDF_TRUETYPE_ERROR2; /* * Font type */ if (ttf->tab_CFF_) { isotf = pdc_true; font->ft.m.type = fnt_Type1C; font->cff_offset = (long) ttf->tab_CFF_->offset; font->cff_length = ttf->tab_CFF_->length; } else { isotf = pdc_false; font->ft.m.type = fnt_TrueType; TT_IOCHECK(ttf, tt_tag2idx(ttf, fnt_str_glyf) != -1); TT_IOCHECK(ttf, tt_tag2idx(ttf, fnt_str_loca) != -1); } /* Number of Glyphs */ if (ttf->numGlyphs <= 1) { errcode = FNT_E_TT_NOGLYFDESC; goto PDF_TRUETYPE_ERROR1; } /* * Encoding */ if (isotf) { /* OpenType font with CFF table */ if (ttf->charcoll != cc_none) { /* CID font */ if (font->ft.m.charcoll != cc_none) { if (!ttf->regisadobe) { errcode = PDF_E_CJK_UNSUPP_REGISTRY; goto PDF_TRUETYPE_ERROR1; } if (font->ft.m.charcoll != ttf->charcoll) { errcode = PDF_E_CJK_UNSUPP_CHARCOLL; goto PDF_TRUETYPE_ERROR1; } if (font->outcmapname != NULL) enc = pdc_cid; if (logg1) pdc_logg(p->pdc, "\tCID font ordering: \"%s\"\n", fnt_get_ordering_cid(ttf->charcoll)); } else if (enc == pdc_unicode || enc == pdc_glyphid) { font->ft.m.charcoll = ttf->charcoll; font->supplement = ttf->supplement; } else { errcode = PDF_E_FONT_ONLY_CMAP; goto PDF_TRUETYPE_ERROR1; } } else if (font->ft.m.charcoll != cc_none) { /* SID font */ errcode = PDF_E_FONT_UNSUPP_CMAP; goto PDF_TRUETYPE_ERROR1; } } else { if (font->ft.m.charcoll != cc_none) { int i; pdc_bool iscjk = pdc_false; for (i = 0; i < PDC_NUMCHARCOLL; i++) { if (ttf->tab_OS_2->charcolls[i]) iscjk = pdc_true; if (ttf->tab_OS_2->charcolls[i] == font->ft.m.charcoll) break; } if (i == PDC_NUMCHARCOLL) { if (iscjk) { /* CJK font */ errcode = PDF_E_CJK_UNSUPP_CHARCOLL; goto PDF_TRUETYPE_ERROR1; } else { /* no CJK font */ errcode = PDF_E_FONT_UNSUPP_CMAP; goto PDF_TRUETYPE_ERROR1; } } else { if (font->outcmapname != NULL) { ttf->charcoll = font->ft.m.charcoll; enc = pdc_cid; } } } } /* encoding vector */ enc_req = fnt_get_tt_encoding_key(ttf, enc); if (enc_req == pdc_invalidenc) { errcode = FNT_E_TT_BADCMAP; goto PDF_TRUETYPE_ERROR1; } else if (enc_req != enc) { if (strcmp(font->encapiname, "auto")) { pdc_warning(p->pdc, PDF_E_FONT_FORCEENC, pdf_get_encoding_name(p, enc_req, NULL), 0, 0, 0); } enc = enc_req; } if (enc >= 0) ev = pdc_get_encoding_vector(p->pdc, enc); font->ft.enc = enc; font->ft.issymbfont = ttf->issymbol; font->hasnomac = !ttf->tab_cmap || !ttf->tab_cmap->mac; /* builtin encoding */ if (enc == pdc_builtin) { if (font->ft.issymbfont == pdc_false) { errcode = PDF_E_FONT_BADENC; goto PDF_TRUETYPE_ERROR1; } else { /* encoding vector for builtin */ ev = pdf_create_font_encoding(p, enc, font, fontname, pdc_true); font->symenc = font->ft.enc; } } { /* optimizing PDF output */ if (enc == pdc_ebcdic || enc == pdc_ebcdic_37 || enc == pdc_ebcdic_winansi) font->towinansi = pdc_winansi; } /* /FontName in FontDescriptor */ font->ft.m.name = pdc_strdup(p->pdc, ttf->tab_name->englishname4); /* /BaseFont name */ font->ft.name = pdc_strdup(p->pdc, ttf->tab_name->englishname6); #define PDF_RESTRICTED_TT_EMBEDDING 0x02 /* check embedding flags */ if ((font->opt.embedding) && ttf->tab_OS_2 && ttf->tab_OS_2->fsType == PDF_RESTRICTED_TT_EMBEDDING) { errcode = FNT_E_TT_EMBED; goto PDF_TRUETYPE_ERROR1; } if (logg1) { pdc_logg(p->pdc, "\tFull font name: \"%s\"\n" "\tPostScript font name: \"%s\"\n" "\tFont embedding: %s\n" "\tVertical font: %s\n", font->ft.name, font->ft.m.name, PDC_BOOLSTR(font->opt.embedding), PDC_BOOLSTR(font->ft.vertical)); if (ttf->tab_name->producer != NULL) pdc_logg(p->pdc, "\tFont producer: \"%s\"\n", ttf->tab_name->producer); pdc_logg(p->pdc, "\tNumber of Glyphs: %d\n", ttf->numGlyphs); } /* Save font values */ fnt_set_tt_fontvalues(ttf); /* Flags for creating font arrays */ flags = TT_FONT_code2gid | TT_FONT_m_widths; /* Create font mapping and width arrays */ foundglyphs = fnt_set_tt_fontarrays(ttf, flags); /***********************************/ if (font->symenc != pdc_invalidenc) font->ft.enc = pdc_builtin; /***********************************/ if (!foundglyphs) { errcode = PDF_E_FONT_BADENC; goto PDF_TRUETYPE_ERROR1; } fnt_delete_tt(ttf); if (!pdf_make_fontflag(p, font)) return pdc_false; return pdc_true; PDF_TRUETYPE_ERROR1: pdc_set_errmsg(p->pdc, errcode, 0, 0, 0, 0); PDF_TRUETYPE_ERROR2: fnt_delete_tt(ttf); return pdc_false; }
/* ** Returns CMap slot and for standard CJK fonts: fontandle. ** ** pdc_invalidenc: predefined CMap not found ** pdc_cid or pdc_unicode: predefined CMap found ** ** *o_slot: ** >= 0: standard font found ** < 0: |error code| */ pdc_bool pdf_handle_cidfont(PDF *p, const char *fontname, const char *encoding, pdc_encoding enc, pdf_font *font, int *o_slot, pdc_encoding *newenc) { const char *encapiname = encoding; fnt_cmap_info cmapinfo; const fnt_font_metric *fontmetric; pdc_bool isidentity = pdc_false; pdc_bool isstdfont = pdc_false; pdc_bool iscjkcp = pdc_false; int charcoll, slot; (void) enc; (void) iscjkcp; (void) encapiname; *o_slot = -1; *newenc = pdc_invalidenc; /* * Look whether font is already in the cache. * If font with same name and encoding is found, * returns its slot number. */ for (slot = 0; slot < p->fonts_number; slot++) { if (p->fonts[slot].ft.enc == pdc_cid && p->fonts[slot].opt.fontstyle == font->opt.fontstyle && p->fonts[slot].opt.embedding == font->opt.embedding && !strcmp(p->fonts[slot].apiname, fontname) && !strcmp(p->fonts[slot].ft.cmapname, encoding)) { *o_slot = slot; *newenc = pdc_cid; return pdc_true; } } /* Check the requested CMap */ charcoll = fnt_get_predefined_cmap_info(encoding, &cmapinfo); if (charcoll == (int) cc_none) return pdc_true; pdc_logg_cond(p->pdc, 1, trc_font, "\tPredefined CMap \"%s\" found\n", encoding); /* Check whether this CMap is supported in the desired PDF version */ if (cmapinfo.compatibility > p->compatibility) { pdc_set_errmsg(p->pdc, PDF_E_DOC_PDFVERSION, encoding, pdc_get_pdfversion(p->pdc, p->compatibility), 0, 0); return pdc_false; } /* For Unicode capable language wrappers only UCS2/UTF16 CMaps allowed */ if (cmapinfo.codesize == 0 && p->pdc->unicaplang) { pdc_set_errmsg(p->pdc, PDF_E_FONT_NEEDUCS2, 0, 0, 0, 0); return pdc_false; } /* Check whether the font name is among the known Acrobat CJK fonts */ charcoll = fnt_get_preinstalled_cidfont(fontname, &fontmetric); isidentity = cmapinfo.charcoll == (int) cc_identity; if (isidentity) cmapinfo.charcoll = abs(charcoll); /* known Acrobat CID font */ if (charcoll != (int) cc_none) { pdc_logg_cond(p->pdc, 1, trc_font, "\tStandard CJK font \"%s\" found\n", fontname); /* Selected CMap and known standard font don't match */ if ((cmapinfo.charcoll != abs(charcoll) || (charcoll == (int) cc_japanese && cmapinfo.codesize == -2))) { pdc_set_errmsg(p->pdc, PDF_E_CJK_UNSUPP_CHARCOLL, 0, 0, 0, 0); return pdc_false; } isstdfont = pdc_true; /* Embedding not possible */ if (font->opt.embedding) { pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDCMAP, 0, 0, 0, 0); return pdc_false; } } #ifdef WIN32 else if (iscjkcp && !p->pdc->ptfrun) { return pdc_true; } #endif /* embedding check */ if (!pdf_check_font_embedding(p, font, fontname)) return pdc_false; /* supplement number, number of codes = (maximal) number of CIDs */ font->supplement = fnt_get_supplement(&cmapinfo, p->compatibility); if (isidentity) font->supplement = -1; font->ft.numcodes = fnt_get_maxcid(cmapinfo.charcoll, font->supplement) + 1; { font->passthrough = pdc_true; font->codesize = 0; } /* CMap and default settings */ font->ft.vertical = cmapinfo.vertical; font->ft.cmapname = pdc_strdup(p->pdc, encoding); if (font->outcmapname == NULL) font->outcmapname = pdc_strdup(p->pdc, encoding); font->ft.enc = pdc_cid; font->iscidfont = pdc_true; /* Fill up the font struct */ fnt_fill_font_metric(p->pdc, &font->ft, pdc_false, fontmetric); /* CID widths not available */ font->widthsmissing = pdc_true; pdc_logg_cond(p->pdc, 1, trc_font, "\n\t%s CJK font: \"%s\"\n\tPredefined CMap: \"%s\"\n" "\tOrdering: \"%s\"\n\tSupplement: %d\n", font->ft.isstdfont ? "Adobe Standard" : "Custom", fontname, encoding, fnt_get_ordering_cid(font->ft.m.charcoll), font->supplement); *newenc = pdc_cid; return pdc_true; }