/* * Create an Identity-* CMap (for both 1 and 2-byte encodings) */ fz_error pdf_newidentitycmap(pdf_cmap **cmapp, int wmode, int bytes) { fz_error error; pdf_cmap *cmap; error = pdf_newcmap(&cmap); if (error) return fz_rethrow(error, "cannot create cmap"); sprintf(cmap->cmapname, "Identity-%c", wmode ? 'V' : 'H'); error = pdf_addcodespace(cmap, 0x0000, 0xffff, bytes); if (error) { pdf_dropcmap(cmap); return fz_rethrow(error, "cannot add code space"); } error = pdf_maprangetorange(cmap, 0x0000, 0xffff, 0); if (error) { pdf_dropcmap(cmap); return fz_rethrow(error, "cannot map <0000> to <ffff>"); } error = pdf_sortcmap(cmap); if (error) { pdf_dropcmap(cmap); return fz_rethrow(error, "cannot sort cmap"); } pdf_setwmode(cmap, wmode); *cmapp = cmap; return fz_okay; }
static void ftdropfont(fz_font *font) { pdf_font *pfont = (pdf_font*)font; if (pfont->encoding) pdf_dropcmap(pfont->encoding); if (pfont->tottfcmap) pdf_dropcmap(pfont->tottfcmap); if (pfont->tounicode) pdf_dropcmap(pfont->tounicode); fz_free(pfont->cidtogid); fz_free(pfont->cidtoucs); if (pfont->ftface) FT_Done_Face((FT_Face)pfont->ftface); if (pfont->fontdata) fz_dropbuffer(pfont->fontdata); }
static void t3dropfont(fz_font *font) { int i; pdf_font *pfont = (pdf_font*)font; if (pfont->encoding) pdf_dropcmap(pfont->encoding); for (i = 0; i < 256; i++) if (pfont->charprocs[i]) fz_droptree(pfont->charprocs[i]); }
void pdf_dropfont(pdf_fontdesc *fontdesc) { if (fontdesc && --fontdesc->refs == 0) { if (fontdesc->font) fz_dropfont(fontdesc->font); if (fontdesc->encoding) pdf_dropcmap(fontdesc->encoding); if (fontdesc->tottfcmap) pdf_dropcmap(fontdesc->tottfcmap); if (fontdesc->tounicode) pdf_dropcmap(fontdesc->tounicode); fz_free(fontdesc->cidtogid); fz_free(fontdesc->cidtoucs); fz_free(fontdesc->hmtx); fz_free(fontdesc->vmtx); fz_free(fontdesc); } }
static void dropitem(pdf_itemkind kind, void *val) { switch (kind) { case PDF_KCOLORSPACE: fz_dropcolorspace(val); break; case PDF_KFUNCTION: pdf_dropfunction(val); break; case PDF_KXOBJECT: pdf_dropxobject(val); break; case PDF_KIMAGE: fz_dropimage(val); break; case PDF_KPATTERN: pdf_droppattern(val); break; case PDF_KSHADE: fz_dropshade(val); break; case PDF_KCMAP: pdf_dropcmap(val); break; case PDF_KFONT: pdf_dropfont(val); break; } }
fz_error pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm) { fz_error error = fz_okay; pdf_cmap *cmap; int cid; int ucsbuf[8]; int ucslen; int i; if (pdf_isstream(xref, fz_tonum(cmapstm), fz_togen(cmapstm))) { pdf_logfont("tounicode embedded cmap\n"); error = pdf_loadembeddedcmap(&cmap, xref, cmapstm); if (error) return fz_rethrow(error, "cannot load embedded cmap (%d %d R)", fz_tonum(cmapstm), fz_togen(cmapstm)); font->tounicode = pdf_newcmap(); for (i = 0; i < (strings ? 256 : 65536); i++) { cid = pdf_lookupcmap(font->encoding, i); if (cid >= 0) { ucslen = pdf_lookupcmapfull(cmap, i, ucsbuf); if (ucslen == 1) pdf_maprangetorange(font->tounicode, cid, cid, ucsbuf[0]); if (ucslen > 1) pdf_maponetomany(font->tounicode, cid, ucsbuf, ucslen); } } pdf_sortcmap(font->tounicode); pdf_dropcmap(cmap); } else if (collection) { pdf_logfont("tounicode cid collection (%s)\n", collection); error = fz_okay; if (!strcmp(collection, "Adobe-CNS1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan2-UCS2"); /* where's this? */ else if (!strcmp(collection, "Adobe-Korea1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Korea1-UCS2"); if (error) return fz_rethrow(error, "cannot load tounicode system cmap %s-UCS2", collection); } if (strings) { pdf_logfont("tounicode strings\n"); /* TODO one-to-many mappings */ font->ncidtoucs = 256; font->cidtoucs = fz_calloc(256, sizeof(unsigned short)); for (i = 0; i < 256; i++) { if (strings[i]) font->cidtoucs[i] = pdf_lookupagl(strings[i]); else font->cidtoucs[i] = '?'; } } if (!font->tounicode && !font->cidtoucs) { pdf_logfont("tounicode could not be loaded\n"); /* TODO: synthesize a ToUnicode if it's a freetype font with * cmap and/or post tables or if it has glyph names. */ } return fz_okay; }
/* * Load CMap stream in PDF file */ fz_error pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmref) { fz_error error = fz_okay; fz_obj *stmobj; fz_stream *file = nil; pdf_cmap *cmap = nil; pdf_cmap *usecmap; fz_obj *wmode; fz_obj *obj; if ((*cmapp = pdf_finditem(xref->store, PDF_KCMAP, stmref))) { pdf_keepcmap(*cmapp); return fz_okay; } pdf_logfont("load embedded cmap (%d %d R) {\n", fz_tonum(stmref), fz_togen(stmref)); stmobj = fz_resolveindirect(stmref); error = pdf_openstream(&file, xref, fz_tonum(stmref), fz_togen(stmref)); if (error) { error = fz_rethrow(error, "cannot open cmap stream"); goto cleanup; } error = pdf_parsecmap(&cmap, file); if (error) { error = fz_rethrow(error, "cannot parse cmap stream"); goto cleanup; } fz_dropstream(file); wmode = fz_dictgets(stmobj, "WMode"); if (fz_isint(wmode)) { pdf_logfont("wmode %d\n", wmode); pdf_setwmode(cmap, fz_toint(wmode)); } obj = fz_dictgets(stmobj, "UseCMap"); if (fz_isname(obj)) { pdf_logfont("usecmap /%s\n", fz_toname(obj)); error = pdf_loadsystemcmap(&usecmap, fz_toname(obj)); if (error) { error = fz_rethrow(error, "cannot load system usecmap '%s'", fz_toname(obj)); goto cleanup; } pdf_setusecmap(cmap, usecmap); pdf_dropcmap(usecmap); } else if (fz_isindirect(obj)) { pdf_logfont("usecmap (%d %d R)\n", fz_tonum(obj), fz_togen(obj)); error = pdf_loadembeddedcmap(&usecmap, xref, obj); if (error) { error = fz_rethrow(error, "cannot load embedded usecmap"); goto cleanup; } pdf_setusecmap(cmap, usecmap); pdf_dropcmap(usecmap); } pdf_logfont("}\n"); error = pdf_storeitem(xref->store, PDF_KCMAP, stmref, cmap); if (error) { error = fz_rethrow(error, "cannot store cmap resource"); goto cleanup; } *cmapp = cmap; return fz_okay; cleanup: if (file) fz_dropstream(file); if (cmap) pdf_dropcmap(cmap); return error; /* already rethrown */ }
fz_error pdf_parsecmap(pdf_cmap **cmapp, fz_stream *file) { fz_error error; pdf_cmap *cmap; char key[64]; char buf[256]; pdf_token_e tok; int len; cmap = pdf_newcmap(); strcpy(key, ".notdef"); while (1) { error = lexcmap(&tok, file, buf, sizeof buf, &len); if (error) { /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=642 */ fz_warn("syntaxerror in cmap"); tok = PDF_TEOF; } if (tok == PDF_TEOF) break; else if (tok == PDF_TNAME) { if (!strcmp(buf, "CMapName")) { error = parsecmapname(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap after /CMapName"); goto cleanup; } } else if (!strcmp(buf, "WMode")) { error = parsewmode(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap after /WMode"); goto cleanup; } } else strlcpy(key, buf, sizeof key); } else if (tok == TUSECMAP) { strlcpy(cmap->usecmapname, key, sizeof(cmap->usecmapname)); } else if (tok == TBEGINCODESPACERANGE) { error = parsecodespacerange(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap codespacerange"); goto cleanup; } } else if (tok == TBEGINBFCHAR) { error = parsebfchar(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap bfchar"); goto cleanup; } } else if (tok == TBEGINCIDCHAR) { error = parsecidchar(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap cidchar"); goto cleanup; } } else if (tok == TBEGINBFRANGE) { error = parsebfrange(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap bfrange"); goto cleanup; } } else if (tok == TBEGINCIDRANGE) { error = parsecidrange(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap cidrange"); goto cleanup; } } /* ignore everything else */ } pdf_sortcmap(cmap); *cmapp = cmap; return fz_okay; cleanup: pdf_dropcmap(cmap); return error; /* already rethrown */ }