static fz_error loadtype0(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_obj *dfonts; fz_obj *dfont; fz_obj *subtype; fz_obj *encoding; fz_obj *tounicode; dfonts = fz_dictgets(dict, "DescendantFonts"); if (!dfonts) return fz_throw("cid font is missing descendant fonts"); dfont = fz_arrayget(dfonts, 0); subtype = fz_dictgets(dfont, "Subtype"); encoding = fz_dictgets(dict, "Encoding"); tounicode = fz_dictgets(dict, "ToUnicode"); if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "CIDFontType0")) error = loadcidfont(fontdescp, xref, dfont, encoding, tounicode); else if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "CIDFontType2")) error = loadcidfont(fontdescp, xref, dfont, encoding, tounicode); else error = fz_throw("syntaxerror: unknown cid font type"); if (error) return fz_rethrow(error, "cannot load descendant font (%d %d R)", fz_tonum(dfont), fz_togen(dfont)); return fz_okay; }
static fz_error gatherpsobjs(int page, fz_obj *pageobj, fz_obj *dict) { int i; for (i = 0; i < fz_dictlen(dict); i++) { fz_obj *ref; fz_obj *xobjdict; fz_obj *type; fz_obj *subtype; int k; xobjdict = ref = fz_dictgetval(dict, i); if (!fz_isdict(xobjdict)) return fz_throw("not a xobject dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); type = fz_dictgets(xobjdict, "Subtype"); if (!fz_isname(type)) return fz_throw("not a xobject type (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (strcmp(fz_toname(type), "Form")) continue; subtype = fz_dictgets(xobjdict, "Subtype2"); if (subtype && !fz_isname(subtype)) return fz_throw("not a xobject subtype (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (strcmp(fz_toname(type), "PS") && (strcmp(fz_toname(type), "Form") || strcmp(fz_toname(subtype), "PS"))) continue; for (k = 0; k < psobjs; k++) if (fz_tonum(psobj[k]->ref) == fz_tonum(ref) && fz_togen(psobj[k]->ref) == fz_togen(ref)) break; if (k < psobjs) continue; psobjs++; psobj = fz_realloc(psobj, psobjs * sizeof (struct info *)); if (!psobj) return fz_throw("out of memory"); psobj[psobjs - 1] = fz_malloc(sizeof (struct info)); if (!psobj[psobjs - 1]) return fz_throw("out of memory"); psobj[psobjs - 1]->page = page; psobj[psobjs - 1]->pageobj = pageobj; psobj[psobjs - 1]->ref = ref; } return fz_okay; }
void pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots) { pdf_comment *comment; pdf_link *link; fz_obj *subtype; fz_obj *obj; int i; comment = nil; link = nil; pdf_logpage("load annotations {\n"); for (i = 0; i < fz_arraylen(annots); i++) { obj = fz_arrayget(annots, i); subtype = fz_dictgets(obj, "Subtype"); if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "Link")) { pdf_link *temp = pdf_loadlink(xref, obj); if (temp) { temp->next = link; link = temp; } } } pdf_logpage("}\n"); *cp = comment; *lp = link; }
static fz_obj * resolvedest(pdf_xref *xref, fz_obj *dest) { if (fz_isname(dest) || fz_isstring(dest)) { dest = pdf_lookupdest(xref, dest); return resolvedest(xref, dest); } else if (fz_isarray(dest)) { return dest; /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=275 */ } else if (fz_isdict(dest)) { dest = fz_dictgets(dest, "D"); return resolvedest(xref, dest); } else if (fz_isindirect(dest)) return dest; return nil; }
static fz_obj * resolvedest(pdf_xref *xref, fz_obj *dest) { if (fz_isname(dest) || fz_isstring(dest)) { dest = pdf_lookupdest(xref, dest); return resolvedest(xref, dest); } else if (fz_isarray(dest)) { return fz_arrayget(dest, 0); } else if (fz_isdict(dest)) { dest = fz_dictgets(dest, "D"); return resolvedest(xref, dest); } else if (fz_isindirect(dest)) return dest; return nil; }
static fz_obj * resolvedest(pdf_xref *xref, fz_obj *dest) { if (fz_isname(dest)) { dest = fz_dictget(xref->dests, dest); if (dest) pdf_resolve(&dest, xref); /* XXX */ return resolvedest(xref, dest); } else if (fz_isstring(dest)) { dest = fz_dictget(xref->dests, dest); if (dest) pdf_resolve(&dest, xref); /* XXX */ return resolvedest(xref, dest); } else if (fz_isarray(dest)) { return fz_arrayget(dest, 0); } else if (fz_isdict(dest)) { dest = fz_dictgets(dest, "D"); return resolvedest(xref, dest); } else if (fz_isindirect(dest)) return dest; return nil; }
static void writeobject(int num, int gen) { fz_error error; fz_obj *obj; fz_obj *type; error = pdf_loadobject(&obj, xref, num, gen); if (error) die(error); /* skip ObjStm and XRef objects */ if (fz_isdict(obj)) { type = fz_dictgets(obj, "Type"); if (fz_isname(type) && !strcmp(fz_toname(type), "ObjStm")) { uselist[num] = 0; fz_dropobj(obj); return; } if (fz_isname(type) && !strcmp(fz_toname(type), "XRef")) { uselist[num] = 0; fz_dropobj(obj); return; } } if (!pdf_isstream(xref, num, gen)) { fprintf(out, "%d %d obj\n", num, gen); fz_fprintobj(out, obj, !doexpand); fprintf(out, "endobj\n\n"); } else { if (doexpand && !pdf_isjpximage(obj)) expandstream(obj, num, gen); else copystream(obj, num, gen); } fz_dropobj(obj); }
fz_error pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots) { fz_error error; pdf_comment *comment; pdf_link *link; fz_obj *subtype; fz_obj *obj; int i; comment = nil; link = nil; pdf_logpage("load annotations {\n"); for (i = 0; i < fz_arraylen(annots); i++) { obj = fz_arrayget(annots, i); subtype = fz_dictgets(obj, "Subtype"); if (fz_isname(subtype) && !strcmp(fz_toname(subtype), "Link")) { pdf_link *temp = nil; error = pdf_loadlink(&temp, xref, obj); if (error) { if (link) pdf_droplink(link); return fz_rethrow(error, "cannot load annotation link"); } if (temp) { temp->next = link; link = temp; } } else { error = loadcomment(&comment, xref, obj); if (error) { if (link) pdf_droplink(link); return fz_rethrow(error, "cannot load annotation comment"); } } } pdf_logpage("}\n"); *cp = comment; *lp = link; return fz_okay; }
static int pdf_extgstateusesblending(fz_obj *dict) { fz_obj *obj; obj = fz_dictgets(dict, "BM"); if (fz_isname(obj) && strcmp(fz_toname(obj), "Normal")) return 1; return 0; }
static void addhexfilter(fz_obj *dict) { fz_obj *f, *dp, *newf, *newdp; fz_obj *ahx, *nullobj; ahx = fz_newname("ASCIIHexDecode"); nullobj = fz_newnull(); newf = newdp = nil; f = fz_dictgets(dict, "Filter"); dp = fz_dictgets(dict, "DecodeParms"); if (fz_isname(f)) { newf = fz_newarray(2); fz_arraypush(newf, ahx); fz_arraypush(newf, f); f = newf; if (fz_isdict(dp)) { newdp = fz_newarray(2); fz_arraypush(newdp, nullobj); fz_arraypush(newdp, dp); dp = newdp; } } else if (fz_isarray(f)) { fz_arrayinsert(f, ahx); if (fz_isarray(dp)) fz_arrayinsert(dp, nullobj); } else f = ahx; fz_dictputs(dict, "Filter", f); if (dp) fz_dictputs(dict, "DecodeParms", dp); fz_dropobj(ahx); fz_dropobj(nullobj); if (newf) fz_dropobj(newf); if (newdp) fz_dropobj(newdp); }
/* * Construct a filter to decode a stream, without * constraining to stream length, and without decryption. */ fz_error * pdf_buildinlinefilter(fz_filter **filterp, fz_obj *stmobj) { fz_error *error; fz_obj *filters; fz_obj *params; filters = fz_dictgetsa(stmobj, "Filter", "F"); params = fz_dictgetsa(stmobj, "DecodeParms", "DP"); if (filters) { if (fz_isname(filters)) error = buildonefilter(filterp, filters, params); else error = buildfilterchain(filterp, nil, filters, params); } else error = fz_newnullfilter(filterp, -1); if (error) return fz_rethrow(error, "cannot create inline filter chain"); return fz_okay; }
pdf_link * pdf_loadlink(pdf_xref *xref, fz_obj *dict) { fz_obj *dest; fz_obj *action; fz_obj *obj; fz_rect bbox; pdf_linkkind kind; pdf_logpage("load link {\n"); dest = nil; obj = fz_dictgets(dict, "Rect"); if (obj) { bbox = pdf_torect(obj); pdf_logpage("rect [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); } else bbox = fz_emptyrect; obj = fz_dictgets(dict, "Dest"); if (obj) { kind = PDF_LGOTO; dest = resolvedest(xref, obj); pdf_logpage("dest (%d %d R)\n", fz_tonum(dest), fz_togen(dest)); } action = fz_dictgets(dict, "A"); if (action) { obj = fz_dictgets(action, "S"); if (fz_isname(obj) && !strcmp(fz_toname(obj), "GoTo")) { kind = PDF_LGOTO; dest = resolvedest(xref, fz_dictgets(action, "D")); pdf_logpage("action goto (%d %d R)\n", fz_tonum(dest), fz_togen(dest)); } else if (fz_isname(obj) && !strcmp(fz_toname(obj), "URI")) { kind = PDF_LURI; dest = fz_dictgets(action, "URI"); pdf_logpage("action uri %s\n", fz_tostrbuf(dest)); } /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=726 */ else if (fz_isname(obj) && !strcmp(fz_toname(obj), "Launch")) { kind = PDF_LLAUNCH; dest = fz_dictgets(action, "F"); pdf_logpage("action launch (%d %d R)\n", fz_tonum(dest), fz_togen(dest)); } else { pdf_logpage("unhandled link action, ignoring link\n"); dest = nil; } } pdf_logpage("}\n"); if (dest) { return pdf_newlink(kind, bbox, dest); } return nil; }
fz_error pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict) { fz_error error; pdf_xobject *form; fz_obj *obj; if ((*formp = pdf_finditem(xref->store, PDF_KXOBJECT, dict))) { pdf_keepxobject(*formp); return fz_okay; } form = fz_malloc(sizeof(pdf_xobject)); form->refs = 1; form->resources = nil; form->contents = nil; /* Store item immediately, to avoid possible recursion if objects refer back to this one */ pdf_storeitem(xref->store, PDF_KXOBJECT, dict, form); pdf_logrsrc("load xobject (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), form); obj = fz_dictgets(dict, "BBox"); form->bbox = pdf_torect(obj); pdf_logrsrc("bbox [%g %g %g %g]\n", form->bbox.x0, form->bbox.y0, form->bbox.x1, form->bbox.y1); obj = fz_dictgets(dict, "Matrix"); if (obj) form->matrix = pdf_tomatrix(obj); else form->matrix = fz_identity(); pdf_logrsrc("matrix [%g %g %g %g %g %g]\n", form->matrix.a, form->matrix.b, form->matrix.c, form->matrix.d, form->matrix.e, form->matrix.f); form->isolated = 0; form->knockout = 0; form->transparency = 0; obj = fz_dictgets(dict, "Group"); if (obj) { fz_obj *attrs = obj; form->isolated = fz_tobool(fz_dictgets(attrs, "I")); form->knockout = fz_tobool(fz_dictgets(attrs, "K")); obj = fz_dictgets(attrs, "S"); if (fz_isname(obj) && !strcmp(fz_toname(obj), "Transparency")) form->transparency = 1; } pdf_logrsrc("isolated %d\n", form->isolated); pdf_logrsrc("knockout %d\n", form->knockout); pdf_logrsrc("transparency %d\n", form->transparency); form->resources = fz_dictgets(dict, "Resources"); if (form->resources) fz_keepobj(form->resources); error = pdf_loadstream(&form->contents, xref, fz_tonum(dict), fz_togen(dict)); if (error) { pdf_removeitem(xref->store, PDF_KXOBJECT, dict); pdf_dropxobject(form); return fz_rethrow(error, "cannot load xobject content stream (%d %d R)", fz_tonum(dict), fz_togen(dict)); } pdf_logrsrc("stream %d bytes\n", form->contents->wp - form->contents->rp); pdf_logrsrc("}\n"); *formp = form; 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_loadtype3font(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) { fz_error error; char buf[256]; char *estrings[256]; pdf_fontdesc *fontdesc; fz_obj *encoding; fz_obj *widths; fz_obj *resources; fz_obj *charprocs; fz_obj *obj; int first, last; int i, k, n; fz_rect bbox; fz_matrix matrix; obj = fz_dictgets(dict, "Name"); if (fz_isname(obj)) strlcpy(buf, fz_toname(obj), sizeof buf); else sprintf(buf, "Unnamed-T3"); fontdesc = pdf_newfontdesc(); pdf_logfont("load type3 font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("name %s\n", buf); obj = fz_dictgets(dict, "FontMatrix"); matrix = pdf_tomatrix(obj); pdf_logfont("matrix [%g %g %g %g %g %g]\n", matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f); obj = fz_dictgets(dict, "FontBBox"); bbox = pdf_torect(obj); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); bbox = fz_transformaabb(matrix, bbox); bbox.x0 = fz_floor(bbox.x0 * 1000); bbox.y0 = fz_floor(bbox.y0 * 1000); bbox.x1 = fz_ceil(bbox.x1 * 1000); bbox.y1 = fz_ceil(bbox.y1 * 1000); fontdesc->font = fz_newtype3font(buf, matrix); fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding */ for (i = 0; i < 256; i++) estrings[i] = nil; encoding = fz_dictgets(dict, "Encoding"); if (!encoding) { error = fz_throw("syntaxerror: Type3 font missing Encoding"); goto cleanup; } if (fz_isname(encoding)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } fontdesc->encoding = pdf_newidentitycmap(0, 1); error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* * Widths */ pdf_setdefaulthmtx(fontdesc, 0); first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); widths = fz_dictgets(dict, "Widths"); if (!widths) { error = fz_throw("syntaxerror: Type3 font missing Widths"); goto cleanup; } for (i = first; i <= last; i++) { float w = fz_toreal(fz_arrayget(widths, i - first)); w = fontdesc->font->t3matrix.a * w * 1000.0; fontdesc->font->t3widths[i] = w * 0.001; pdf_addhmtx(fontdesc, i, i, w); } pdf_endhmtx(fontdesc); /* * Resources */ resources = fz_dictgets(dict, "Resources"); /* Inherit page's resource dict if type3 font does not have one */ if (!resources && rdb) resources = rdb; else if (!resources && !rdb) fz_warn("no resource dictionary for type 3 font!"); /* * CharProcs */ charprocs = fz_dictgets(dict, "CharProcs"); if (!charprocs) { error = fz_throw("syntaxerror: Type3 font missing CharProcs"); goto cleanup; } for (i = 0; i < 256; i++) { if (estrings[i]) { obj = fz_dictgets(charprocs, estrings[i]); if (obj) { pdf_logfont("load charproc %s {\n", estrings[i]); error = loadcharproc(&fontdesc->font->t3procs[i], xref, resources, obj); if (error) goto cleanup; pdf_logfont("}\n"); } } } pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: fz_dropfont(fontdesc->font); fz_free(fontdesc); return fz_rethrow(error, "cannot load type3 font"); }
static fz_error loadcidfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *tounicode) { fz_error error; fz_obj *widths; fz_obj *descriptor; pdf_fontdesc *fontdesc; FT_Face face; fz_bbox bbox; int kind; char collection[256]; char *basefont; int i, k, fterr; fz_obj *obj; int dw; /* Get font name and CID collection */ basefont = fz_toname(fz_dictgets(dict, "BaseFont")); { fz_obj *cidinfo; char tmpstr[64]; int tmplen; cidinfo = fz_dictgets(dict, "CIDSystemInfo"); if (!cidinfo) return fz_throw("cid font is missing info"); obj = fz_dictgets(cidinfo, "Registry"); tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; fz_strlcpy(collection, tmpstr, sizeof collection); fz_strlcat(collection, "-", sizeof collection); obj = fz_dictgets(cidinfo, "Ordering"); tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; fz_strlcat(collection, tmpstr, sizeof collection); } /* Load font file */ fontdesc = pdf_newfontdesc(); pdf_logfont("load cid font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("basefont %s\n", basefont); pdf_logfont("collection %s\n", collection); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor) error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, collection, basefont); else error = fz_throw("syntaxerror: missing font descriptor"); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM; bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM; bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM; pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* Encoding */ error = fz_okay; if (fz_isname(encoding)) { pdf_logfont("encoding /%s\n", fz_toname(encoding)); if (!strcmp(fz_toname(encoding), "Identity-H")) fontdesc->encoding = pdf_newidentitycmap(0, 2); else if (!strcmp(fz_toname(encoding), "Identity-V")) fontdesc->encoding = pdf_newidentitycmap(1, 2); else error = pdf_loadsystemcmap(&fontdesc->encoding, fz_toname(encoding)); } else if (fz_isindirect(encoding)) { pdf_logfont("encoding %d %d R\n", fz_tonum(encoding), fz_togen(encoding)); error = pdf_loadembeddedcmap(&fontdesc->encoding, xref, encoding); } else { error = fz_throw("syntaxerror: font missing encoding"); } if (error) goto cleanup; pdf_setfontwmode(fontdesc, pdf_getwmode(fontdesc->encoding)); pdf_logfont("wmode %d\n", pdf_getwmode(fontdesc->encoding)); if (kind == TRUETYPE) { fz_obj *cidtogidmap; cidtogidmap = fz_dictgets(dict, "CIDToGIDMap"); if (fz_isindirect(cidtogidmap)) { fz_buffer *buf; pdf_logfont("cidtogidmap stream\n"); error = pdf_loadstream(&buf, xref, fz_tonum(cidtogidmap), fz_togen(cidtogidmap)); if (error) goto cleanup; fontdesc->ncidtogid = (buf->len) / 2; fontdesc->cidtogid = fz_malloc(fontdesc->ncidtogid * sizeof(unsigned short)); for (i = 0; i < fontdesc->ncidtogid; i++) fontdesc->cidtogid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1]; fz_dropbuffer(buf); } /* if truetype font is external, cidtogidmap should not be identity */ /* so we map from cid to unicode and then map that through the (3 1) */ /* unicode cmap to get a glyph id */ else if (fontdesc->font->ftsubstitute) { pdf_logfont("emulate ttf cidfont\n"); fterr = FT_Select_Charmap(face, ft_encoding_unicode); if (fterr) { error = fz_throw("fonterror: no unicode cmap when emulating CID font: %s", ft_errorstring(fterr)); goto cleanup; } if (!strcmp(collection, "Adobe-CNS1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan2-UCS2"); else if (!strcmp(collection, "Adobe-Korea1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Korea1-UCS2"); else error = fz_okay; if (error) { error = fz_rethrow(error, "cannot load system cmap %s", collection); goto cleanup; } } } error = pdf_loadtounicode(fontdesc, xref, nil, collection, tounicode); if (error) goto cleanup; /* Horizontal */ dw = 1000; obj = fz_dictgets(dict, "DW"); if (obj) dw = fz_toint(obj); pdf_setdefaulthmtx(fontdesc, dw); widths = fz_dictgets(dict, "W"); if (widths) { int c0, c1, w; for (i = 0; i < fz_arraylen(widths); ) { c0 = fz_toint(fz_arrayget(widths, i)); obj = fz_arrayget(widths, i + 1); if (fz_isarray(obj)) { for (k = 0; k < fz_arraylen(obj); k++) { w = fz_toint(fz_arrayget(obj, k)); pdf_addhmtx(fontdesc, c0 + k, c0 + k, w); } i += 2; } else { c1 = fz_toint(obj); w = fz_toint(fz_arrayget(widths, i + 2)); pdf_addhmtx(fontdesc, c0, c1, w); i += 3; } } } pdf_endhmtx(fontdesc); /* Vertical */ if (pdf_getwmode(fontdesc->encoding) == 1) { int dw2y = 880; int dw2w = -1000; obj = fz_dictgets(dict, "DW2"); if (obj) { dw2y = fz_toint(fz_arrayget(obj, 0)); dw2w = fz_toint(fz_arrayget(obj, 1)); } pdf_setdefaultvmtx(fontdesc, dw2y, dw2w); widths = fz_dictgets(dict, "W2"); if (widths) { int c0, c1, w, x, y; for (i = 0; i < fz_arraylen(widths); ) { c0 = fz_toint(fz_arrayget(widths, i)); obj = fz_arrayget(widths, i + 1); if (fz_isarray(obj)) { for (k = 0; k < fz_arraylen(obj); k += 3) { w = fz_toint(fz_arrayget(obj, k + 0)); x = fz_toint(fz_arrayget(obj, k + 1)); y = fz_toint(fz_arrayget(obj, k + 2)); pdf_addvmtx(fontdesc, c0 + k, c0 + k, x, y, w); } i += 2; } else { c1 = fz_toint(obj); w = fz_toint(fz_arrayget(widths, i + 2)); x = fz_toint(fz_arrayget(widths, i + 3)); y = fz_toint(fz_arrayget(widths, i + 4)); pdf_addvmtx(fontdesc, c0, c1, x, y, w); i += 5; } } } pdf_endvmtx(fontdesc); } pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: pdf_dropfont(fontdesc); return fz_rethrow(error, "cannot load cid font (%d %d R)", fz_tonum(dict), fz_togen(dict)); }
static fz_error fz_repairobj(fz_stream *file, char *buf, int cap, int *stmofsp, int *stmlenp, fz_obj **encrypt, fz_obj **id) { fz_error error; int tok; int stmlen; int len; int n; *stmofsp = 0; *stmlenp = -1; stmlen = 0; error = pdf_lex(&tok, file, buf, cap, &len); if (error) return fz_rethrow(error, "cannot parse object"); if (tok == PDF_TODICT) { fz_obj *dict, *obj; /* Send nil xref so we don't try to resolve references */ error = pdf_parsedict(&dict, nil, file, buf, cap); if (error) return fz_rethrow(error, "cannot parse object"); obj = fz_dictgets(dict, "Type"); if (fz_isname(obj) && !strcmp(fz_toname(obj), "XRef")) { obj = fz_dictgets(dict, "Encrypt"); if (obj) { if (*encrypt) fz_dropobj(*encrypt); *encrypt = fz_keepobj(obj); } obj = fz_dictgets(dict, "ID"); if (obj) { if (*id) fz_dropobj(*id); *id = fz_keepobj(obj); } } obj = fz_dictgets(dict, "Length"); if (fz_isint(obj)) stmlen = fz_toint(obj); fz_dropobj(dict); } while ( tok != PDF_TSTREAM && tok != PDF_TENDOBJ && tok != PDF_TERROR && tok != PDF_TEOF ) { error = pdf_lex(&tok, file, buf, cap, &len); if (error) return fz_rethrow(error, "cannot scan for endobj or stream token"); } if (tok == PDF_TSTREAM) { int c = fz_readbyte(file); if (c == '\r') { c = fz_peekbyte(file); if (c == '\n') fz_readbyte(file); } *stmofsp = fz_tell(file); if (*stmofsp < 0) return fz_throw("cannot seek in file"); if (stmlen > 0) { fz_seek(file, *stmofsp + stmlen, 0); error = pdf_lex(&tok, file, buf, cap, &len); if (error) fz_catch(error, "cannot find endstream token, falling back to scanning"); if (tok == PDF_TENDSTREAM) goto atobjend; fz_seek(file, *stmofsp, 0); } n = fz_read(file, (unsigned char *) buf, 9); if (n < 0) return fz_rethrow(n, "cannot read from file"); while (memcmp(buf, "endstream", 9) != 0) { c = fz_readbyte(file); if (c == EOF) break; memmove(buf, buf + 1, 8); buf[8] = c; } *stmlenp = fz_tell(file) - *stmofsp - 9; atobjend: error = pdf_lex(&tok, file, buf, cap, &len); if (error) return fz_rethrow(error, "cannot scan for endobj token"); if (tok != PDF_TENDOBJ) fz_warn("object missing 'endobj' token"); } return fz_okay; }
static fz_error gatherforms(int page, fz_obj *pageobj, fz_obj *dict) { int i; for (i = 0; i < fz_dictlen(dict); i++) { fz_obj *ref; fz_obj *xobjdict; fz_obj *type; fz_obj *subtype; fz_obj *group; fz_obj *reference; int k; xobjdict = ref = fz_dictgetval(dict, i); if (!fz_isdict(xobjdict)) return fz_throw("not a xobject dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); type = fz_dictgets(xobjdict, "Subtype"); if (!fz_isname(type)) return fz_throw("not a xobject type (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (strcmp(fz_toname(type), "Form")) continue; subtype = fz_dictgets(xobjdict, "Subtype2"); if (subtype && !fz_isname(subtype)) return fz_throw("not a xobject subtype (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (strcmp(fz_toname(subtype), "PS")) continue; group = fz_dictgets(xobjdict, "Group"); if (group && !fz_isdict(group)) return fz_throw("not a form xobject group dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); reference = fz_dictgets(xobjdict, "Ref"); if (reference && !fz_isdict(reference)) return fz_throw("not a form xobject reference dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); for (k = 0; k < forms; k++) if (fz_tonum(form[k]->ref) == fz_tonum(ref) && fz_togen(form[k]->ref) == fz_togen(ref)) break; if (k < forms) continue; forms++; form = fz_realloc(form, forms * sizeof (struct info *)); if (!form) return fz_throw("out of memory"); form[forms - 1] = fz_malloc(sizeof (struct info)); if (!form[forms - 1]) return fz_throw("out of memory"); form[forms - 1]->page = page; form[forms - 1]->pageobj = pageobj; form[forms - 1]->ref = ref; form[forms - 1]->u.form.group = group; form[forms - 1]->u.form.reference = reference; } return fz_okay; }
static fz_error gatherimages(int page, fz_obj *pageobj, fz_obj *dict) { int i; for (i = 0; i < fz_dictlen(dict); i++) { fz_obj *ref; fz_obj *imagedict; fz_obj *type; fz_obj *width; fz_obj *height; fz_obj *bpc = nil; fz_obj *filter = nil; fz_obj *mask; fz_obj *cs = nil; fz_obj *altcs; int k; imagedict = ref = fz_dictgetval(dict, i); if (!fz_isdict(imagedict)) return fz_throw("not an image dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); type = fz_dictgets(imagedict, "Subtype"); if (!fz_isname(type)) return fz_throw("not an image subtype (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (strcmp(fz_toname(type), "Image")) continue; filter = fz_dictgets(imagedict, "Filter"); if (filter && !fz_isname(filter) && !fz_isarray(filter)) return fz_throw("not an image filter (%d %d R)", fz_tonum(ref), fz_togen(ref)); mask = fz_dictgets(imagedict, "ImageMask"); altcs = nil; cs = fz_dictgets(imagedict, "ColorSpace"); if (fz_isarray(cs)) { fz_obj *cses = cs; cs = fz_arrayget(cses, 0); if (fz_isname(cs) && (!strcmp(fz_toname(cs), "DeviceN") || !strcmp(fz_toname(cs), "Separation"))) { altcs = fz_arrayget(cses, 2); if (fz_isarray(altcs)) altcs = fz_arrayget(altcs, 0); } } if (fz_isbool(mask) && fz_tobool(mask)) { if (cs) fz_warn("image mask (%d %d R) may not have colorspace", fz_tonum(ref), fz_togen(ref)); } if (cs && !fz_isname(cs)) return fz_throw("not an image colorspace (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (altcs && !fz_isname(altcs)) return fz_throw("not an image alternate colorspace (%d %d R)", fz_tonum(ref), fz_togen(ref)); width = fz_dictgets(imagedict, "Width"); if (!fz_isint(width)) return fz_throw("not an image width (%d %d R)", fz_tonum(ref), fz_togen(ref)); height = fz_dictgets(imagedict, "Height"); if (!fz_isint(height)) return fz_throw("not an image height (%d %d R)", fz_tonum(ref), fz_togen(ref)); bpc = fz_dictgets(imagedict, "BitsPerComponent"); if (!fz_tobool(mask) && !fz_isint(bpc)) return fz_throw("not an image bits per component (%d %d R)", fz_tonum(ref), fz_togen(ref)); if (fz_tobool(mask) && fz_isint(bpc) && fz_toint(bpc) != 1) return fz_throw("not an image mask bits per component (%d %d R)", fz_tonum(ref), fz_togen(ref)); for (k = 0; k < images; k++) if (fz_tonum(image[k]->ref) == fz_tonum(ref) && fz_togen(image[k]->ref) == fz_togen(ref)) break; if (k < images) continue; images++; image = fz_realloc(image, images * sizeof (struct info *)); if (!image) return fz_throw("out of memory"); image[images - 1] = fz_malloc(sizeof (struct info)); if (!image[images - 1]) return fz_throw("out of memory"); image[images - 1]->page = page; image[images - 1]->pageobj = pageobj; image[images - 1]->ref = ref; image[images - 1]->u.image.width = width; image[images - 1]->u.image.height = height; image[images - 1]->u.image.bpc = bpc; image[images - 1]->u.image.filter = filter; image[images - 1]->u.image.cs = cs; image[images - 1]->u.image.altcs = altcs; } return fz_okay; }
static fz_error gatherfonts(int page, fz_obj *pageobj, fz_obj *dict) { int i; for (i = 0; i < fz_dictlen(dict); i++) { fz_obj *ref; fz_obj *fontdict; fz_obj *subtype; fz_obj *basefont; fz_obj *name; int k; fontdict = ref = fz_dictgetval(dict, i); if (!fz_isdict(fontdict)) { fz_warn("not a font dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); continue; } subtype = fz_dictgets(fontdict, "Subtype"); if (!fz_isname(subtype)) fz_warn("not a font dict subtype (%d %d R)", fz_tonum(ref), fz_togen(ref)); basefont = fz_dictgets(fontdict, "BaseFont"); if (basefont) { if (!fz_isname(basefont)) return fz_throw("not a font dict basefont (%d %d R)", fz_tonum(ref), fz_togen(ref)); } else { name = fz_dictgets(fontdict, "Name"); if (name && !fz_isname(name)) return fz_throw("not a font dict name (%d %d R)", fz_tonum(ref), fz_togen(ref)); } for (k = 0; k < fonts; k++) if (fz_tonum(font[k]->ref) == fz_tonum(ref) && fz_togen(font[k]->ref) == fz_togen(ref)) break; if (k < fonts) continue; fonts++; font = fz_realloc(font, fonts * sizeof (struct info *)); if (!font) return fz_throw("out of memory"); font[fonts - 1] = fz_malloc(sizeof (struct info)); if (!font[fonts - 1]) return fz_throw("out of memory"); font[fonts - 1]->page = page; font[fonts - 1]->pageobj = pageobj; font[fonts - 1]->ref = ref; font[fonts - 1]->u.font.subtype = subtype; font[fonts - 1]->u.font.name = basefont ? basefont : name; } return fz_okay; }
static fz_error pdf_loadimageimp(fz_pixmap **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, int forcemask) { fz_stream *stm; fz_pixmap *tile; fz_obj *obj, *res; fz_error error; int w, h, bpc, n; int imagemask; int interpolate; int indexed; fz_colorspace *colorspace; fz_pixmap *mask; /* explicit mask/softmask image */ int usecolorkey; int colorkey[FZ_MAXCOLORS * 2]; float decode[FZ_MAXCOLORS * 2]; int scale; int stride; unsigned char *samples; int i, len; /* special case for JPEG2000 images */ if (pdf_isjpximage(dict)) { tile = nil; error = pdf_loadjpximage(&tile, xref, dict); if (error) return fz_rethrow(error, "cannot load jpx image"); if (forcemask) { if (tile->n != 2) { fz_droppixmap(tile); return fz_throw("softmask must be grayscale"); } mask = fz_alphafromgray(tile, 1); fz_droppixmap(tile); *imgp = mask; return fz_okay; } *imgp = tile; return fz_okay; } w = fz_toint(fz_dictgetsa(dict, "Width", "W")); h = fz_toint(fz_dictgetsa(dict, "Height", "H")); bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC")); imagemask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM")); interpolate = fz_tobool(fz_dictgetsa(dict, "Interpolate", "I")); indexed = 0; usecolorkey = 0; colorspace = nil; mask = nil; if (imagemask) bpc = 1; if (w == 0) return fz_throw("image width is zero"); if (h == 0) return fz_throw("image height is zero"); if (bpc == 0) return fz_throw("image depth is zero"); if (w > (1 << 16)) return fz_throw("image is too wide"); if (h > (1 << 16)) return fz_throw("image is too high"); obj = fz_dictgetsa(dict, "ColorSpace", "CS"); if (obj && !imagemask && !forcemask) { /* colorspace resource lookup is only done for inline images */ if (fz_isname(obj)) { res = fz_dictget(fz_dictgets(rdb, "ColorSpace"), obj); if (res) obj = res; } error = pdf_loadcolorspace(&colorspace, xref, obj); if (error) return fz_rethrow(error, "cannot load image colorspace"); if (!strcmp(colorspace->name, "Indexed")) indexed = 1; n = colorspace->n; } else { n = 1; } obj = fz_dictgetsa(dict, "Decode", "D"); if (obj) { for (i = 0; i < n * 2; i++) decode[i] = fz_toreal(fz_arrayget(obj, i)); } else { float maxval = indexed ? (1 << bpc) - 1 : 1; for (i = 0; i < n * 2; i++) decode[i] = i & 1 ? maxval : 0; } obj = fz_dictgetsa(dict, "SMask", "Mask"); if (fz_isdict(obj)) { /* Not allowed for inline images */ if (!cstm) { error = pdf_loadimageimp(&mask, xref, rdb, obj, nil, 1); if (error) { if (colorspace) fz_dropcolorspace(colorspace); return fz_rethrow(error, "cannot load image mask/softmask"); } } } else if (fz_isarray(obj)) { usecolorkey = 1; for (i = 0; i < n * 2; i++) colorkey[i] = fz_toint(fz_arrayget(obj, i)); } stride = (w * n * bpc + 7) / 8; samples = fz_calloc(h, stride); if (cstm) { stm = pdf_openinlinestream(cstm, xref, dict, stride * h); } else { error = pdf_openstream(&stm, xref, fz_tonum(dict), fz_togen(dict)); if (error) { if (colorspace) fz_dropcolorspace(colorspace); if (mask) fz_droppixmap(mask); return fz_rethrow(error, "cannot open image data stream (%d 0 R)", fz_tonum(dict)); } } len = fz_read(stm, samples, h * stride); if (len < 0) { fz_close(stm); if (colorspace) fz_dropcolorspace(colorspace); if (mask) fz_droppixmap(mask); return fz_rethrow(len, "cannot read image data"); } /* Make sure we read the EOF marker (for inline images only) */ if (cstm) { unsigned char tbuf[512]; int tlen = fz_read(stm, tbuf, sizeof tbuf); if (tlen < 0) fz_catch(tlen, "ignoring error at end of image"); if (tlen > 0) fz_warn("ignoring garbage at end of image"); } fz_close(stm); /* Pad truncated images */ if (len < stride * h) { fz_warn("padding truncated image (%d 0 R)", fz_tonum(dict)); memset(samples + len, 0, stride * h - len); } /* Invert 1-bit image masks */ if (imagemask) { /* 0=opaque and 1=transparent so we need to invert */ unsigned char *p = samples; len = h * stride; for (i = 0; i < len; i++) p[i] = ~p[i]; } pdf_logimage("size %dx%d n=%d bpc=%d imagemask=%d indexed=%d\n", w, h, n, bpc, imagemask, indexed); /* Unpack samples into pixmap */ tile = fz_newpixmap(colorspace, 0, 0, w, h); scale = 1; if (!indexed) { switch (bpc) { case 1: scale = 255; break; case 2: scale = 85; break; case 4: scale = 17; break; } } fz_unpacktile(tile, samples, n, bpc, stride, scale); if (usecolorkey) pdf_maskcolorkey(tile, n, colorkey); if (indexed) { fz_pixmap *conv; fz_decodeindexedtile(tile, decode, (1 << bpc) - 1); conv = pdf_expandindexedpixmap(tile); fz_droppixmap(tile); tile = conv; } else { fz_decodetile(tile, decode); } if (colorspace) fz_dropcolorspace(colorspace); tile->mask = mask; tile->interpolate = interpolate; fz_free(samples); *imgp = tile; return fz_okay; }
static fz_error pdf_loadcolorspaceimp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj) { if (fz_isname(obj)) { if (!strcmp(fz_toname(obj), "DeviceGray")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(obj), "DeviceRGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(obj), "DeviceCMYK")) *csp = pdf_devicecmyk; else if (!strcmp(fz_toname(obj), "G")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(obj), "RGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(obj), "CMYK")) *csp = pdf_devicecmyk; else if (!strcmp(fz_toname(obj), "Pattern")) *csp = pdf_devicepattern; else return fz_throw("unknown colorspace: %s", fz_toname(obj)); return fz_okay; } else if (fz_isarray(obj)) { fz_obj *name = fz_arrayget(obj, 0); if (fz_isname(name)) { if (!strcmp(fz_toname(name), "CalCMYK")) *csp = pdf_devicecmyk; #ifdef USECAL else if (!strcmp(fz_toname(name), "CalGray")) *csp = loadcalgray(xref, fz_arrayget(obj, 1)); else if (!strcmp(fz_toname(name), "CalRGB")) *csp = loadcalrgb(xref, fz_arrayget(obj, 1)); else if (!strcmp(fz_toname(name), "Lab")) *csp = loadlab(xref, fz_arrayget(obj, 1)); #else else if (!strcmp(fz_toname(name), "CalGray")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(name), "CalRGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(name), "Lab")) *csp = pdf_devicelab; #endif else if (!strcmp(fz_toname(name), "ICCBased")) return loadiccbased(csp, xref, fz_arrayget(obj, 1)); else if (!strcmp(fz_toname(name), "Indexed")) return loadindexed(csp, xref, obj); else if (!strcmp(fz_toname(name), "I")) return loadindexed(csp, xref, obj); else if (!strcmp(fz_toname(name), "Separation")) return loadseparation(csp, xref, obj); else if (!strcmp(fz_toname(name), "DeviceN")) return loadseparation(csp, xref, obj); /* load base colorspace instead */ else if (!strcmp(fz_toname(name), "Pattern")) { fz_error error; obj = fz_arrayget(obj, 1); if (!obj) { *csp = pdf_devicepattern; return fz_okay; } error = pdf_loadcolorspace(csp, xref, obj); if (error) return fz_rethrow(error, "cannot load pattern"); } else if (!strcmp(fz_toname(name), "DeviceGray")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(name), "DeviceRGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(name), "DeviceCMYK")) *csp = pdf_devicecmyk; else if (!strcmp(fz_toname(name), "G")) *csp = pdf_devicegray; else if (!strcmp(fz_toname(name), "RGB")) *csp = pdf_devicergb; else if (!strcmp(fz_toname(name), "CMYK")) *csp = pdf_devicecmyk; else return fz_throw("syntaxerror: unknown colorspace %s", fz_toname(name)); return fz_okay; } } return fz_throw("syntaxerror: could not parse color space"); }
static fz_error loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_obj *descriptor; fz_obj *encoding; fz_obj *widths; unsigned short *etable = nil; pdf_fontdesc *fontdesc; fz_bbox bbox; FT_Face face; FT_CharMap cmap; int kind; int symbolic; char *basefont; char *fontname; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; basefont = fz_toname(fz_dictgets(dict, "BaseFont")); fontname = cleanfontname(basefont); /* Load font file */ fontdesc = pdf_newfontdesc(); pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("basefont %s -> %s\n", basefont, fontname); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor) error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, nil, basefont); else error = pdf_loadbuiltinfont(fontdesc, fontname); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM; bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM; bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM; pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = nil; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn("freetype could not set cmap: %s", ft_errorstring(fterr)); } else fz_warn("freetype could not find any cmaps"); etable = fz_malloc(sizeof(unsigned short) * 256); for (i = 0; i < 256; i++) { estrings[i] = nil; etable[i] = 0; } encoding = fz_dictgets(dict, "Encoding"); if (encoding) { if (fz_isname(encoding)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); else if (!fontdesc->isembedded && !symbolic) pdf_loadencoding(estrings, "StandardEncoding"); /* cf. http://bugs.ghostscript.com/show_bug.cgi?id=690615 and http://code.google.com/p/sumatrapdf/issues/detail?id=687 */ /* try to extract an encoding from the font or synthesize a likely one */ /* note: FT_Get_Name_Index fails for symbolic CFF fonts, so let them be encoded by index */ else if (!fontdesc->encoding && !ftloadt1encoding(face, estrings) && !(symbolic && !strcmp(FT_Get_X11_Font_Format(face), "CFF"))) pdf_loadencoding(estrings, "StandardEncoding"); diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } } /* start with the builtin encoding */ for (i = 0; i < 256; i++) etable[i] = ftcharindex(face, i); /* encode by glyph name where we can */ if (kind == TYPE1) { pdf_logfont("encode type1/cff by strings\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) { int aglcode = pdf_lookupagl(estrings[i]); char **aglnames = pdf_lookupaglnames(aglcode); while (*aglnames) { etable[i] = FT_Get_Name_Index(face, *aglnames); if (etable[i]) break; aglnames++; } } } } } /* encode by glyph name where we can */ if (kind == TRUETYPE) { /* Unicode cmap */ if (!symbolic && face->charmap && face->charmap->platform_id == 3) { pdf_logfont("encode truetype via unicode\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { int aglcode = pdf_lookupagl(estrings[i]); if (!aglcode) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, aglcode); } } } /* MacRoman cmap */ else if (!symbolic && face->charmap && face->charmap->platform_id == 1) { pdf_logfont("encode truetype via macroman\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { k = mrecode(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, k); } } } /* Symbolic cmap */ else { pdf_logfont("encode truetype symbolic\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) etable[i] = ftcharindex(face, i); } } } } /* try to reverse the glyph names from the builtin encoding */ for (i = 0; i < 256; i++) { if (etable[i] && !estrings[i]) { if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) fz_warn("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } else { estrings[i] = (char*) pdf_winansi[i]; /* discard const */ } } } /* Prevent encoding Differences from being overwritten by reloading them */ /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=115 */ if (fz_isdict(encoding)) { fz_obj *diff, *item; diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } fontdesc->encoding = pdf_newidentitycmap(0, 1); fontdesc->ncidtogid = 256; fontdesc->cidtogid = etable; error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* Widths */ pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth); widths = fz_dictgets(dict, "Widths"); if (widths) { int first, last; first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = fz_toint(fz_arrayget(widths, i)); pdf_addhmtx(fontdesc, i + first, i + first, wid); } } else { fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn("freetype set character size: %s", ft_errorstring(fterr)); for (i = 0; i < 256; i++) { pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i)); } } pdf_endhmtx(fontdesc); pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: if (etable != fontdesc->cidtogid) fz_free(etable); pdf_dropfont(fontdesc); return fz_rethrow(error, "cannot load simple font (%d %d R)", fz_tonum(dict), fz_togen(dict)); }
static void savefont(fz_obj *dict, int num, int gen) { fz_error error; char name[1024]; char *subtype; fz_buffer *buf; fz_obj *stream = nil; fz_obj *obj; char *ext = ""; FILE *f; unsigned char *p; char *fontname = "font"; obj = fz_dictgets(dict, "FontName"); if (obj) fontname = fz_toname(obj); obj = fz_dictgets(dict, "FontFile"); if (obj) { stream = obj; ext = "pfa"; } obj = fz_dictgets(dict, "FontFile2"); if (obj) { stream = obj; ext = "ttf"; } obj = fz_dictgets(dict, "FontFile3"); if (obj) { stream = obj; obj = fz_dictgets(obj, "Subtype"); if (obj && !fz_isname(obj)) die(fz_throw("Invalid font descriptor subtype")); subtype = fz_toname(obj); if (!strcmp(subtype, "Type1C")) ext = "cff"; else if (!strcmp(subtype, "CIDFontType0C")) ext = "cid"; else die(fz_throw("Unhandled font type '%s'", subtype)); } if (!stream) { fz_warn("Unhandled font type"); return; } error = fz_newbuffer(&buf, 0); if (error) die(error); error = pdf_loadstream(&buf, xref, fz_tonum(stream), fz_togen(stream)); if (error) die(error); sprintf(name, "%s-%04d.%s", fontname, num, ext); f = fopen(name, "wb"); if (f == NULL) die(fz_throw("Error creating image file")); for (p = buf->rp; p < buf->wp; p ++) fprintf(f, "%c", *p); if (fclose(f) < 0) die(fz_throw("Error closing image file")); fz_dropbuffer(buf); }
fz_error * pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file) { fz_error *error; pdf_image *img; fz_filter *filter; fz_obj *f; fz_obj *cs; fz_obj *d; int ismask; int i; img = fz_malloc(sizeof(pdf_image)); if (!img) return fz_outofmem; pdf_logimage("load inline image %p {\n", img); img->super.loadtile = pdf_loadtile; img->super.drop = pdf_dropimage; img->super.n = 0; img->super.a = 0; img->super.refs = 0; img->indexed = nil; img->usecolorkey = 0; img->mask = nil; img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W")); img->super.h = fz_toint(fz_dictgetsa(dict, "Height", "H")); img->bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC")); ismask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM")); d = fz_dictgetsa(dict, "Decode", "D"); cs = fz_dictgetsa(dict, "ColorSpace", "CS"); pdf_logimage("size %dx%d %d\n", img->super.w, img->super.h, img->bpc); if (ismask) { pdf_logimage("is mask\n"); img->super.cs = nil; img->super.n = 0; img->super.a = 1; img->bpc = 1; } if (cs) { img->super.cs = nil; if (fz_isname(cs)) { fz_obj *csd = fz_dictgets(rdb, "ColorSpace"); if (csd) { fz_obj *cso = fz_dictget(csd, cs); img->super.cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, cso); if (img->super.cs) fz_keepcolorspace(img->super.cs); } } if (!img->super.cs) { /* XXX danger! danger! does this resolve? */ error = pdf_loadcolorspace(&img->super.cs, xref, cs); if (error) return error; } if (!strcmp(img->super.cs->name, "Indexed")) { pdf_logimage("indexed\n"); img->indexed = (pdf_indexed*)img->super.cs; img->super.cs = img->indexed->base; } pdf_logimage("colorspace %s\n", img->super.cs->name); img->super.n = img->super.cs->n; img->super.a = 0; } if (fz_isarray(d)) { pdf_logimage("decode array\n"); if (img->indexed) for (i = 0; i < 2; i++) img->decode[i] = fz_toreal(fz_arrayget(d, i)); else for (i = 0; i < (img->super.n + img->super.a) * 2; i++) img->decode[i] = fz_toreal(fz_arrayget(d, i)); } else { if (img->indexed) for (i = 0; i < 2; i++) img->decode[i] = i & 1 ? (1 << img->bpc) - 1 : 0; else for (i = 0; i < (img->super.n + img->super.a) * 2; i++) img->decode[i] = i & 1; } if (img->indexed) img->stride = (img->super.w * img->bpc + 7) / 8; else img->stride = (img->super.w * (img->super.n + img->super.a) * img->bpc + 7) / 8; /* load image data */ f = fz_dictgetsa(dict, "Filter", "F"); if (f) { fz_stream *tempfile; error = pdf_buildinlinefilter(&filter, dict); if (error) return error; error = fz_openrfilter(&tempfile, filter, file); if (error) return error; i = fz_readall(&img->samples, tempfile); if (i < 0) return fz_ioerror(tempfile); fz_dropfilter(filter); fz_dropstream(tempfile); } else { error = fz_newbuffer(&img->samples, img->super.h * img->stride); if (error) return error; i = fz_read(file, img->samples->bp, img->super.h * img->stride); if (i < 0) return fz_ioerror(file); img->samples->wp += img->super.h * img->stride; } /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (ismask) { unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = ~*p; } pdf_logimage("}\n"); *imgp = img; return nil; }
static int isfontdesc(fz_obj *obj) { fz_obj *type = fz_dictgets(obj, "Type"); return fz_isname(type) && !strcmp(fz_toname(type), "FontDescriptor"); }
static fz_error loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_obj *descriptor = nil; fz_obj *encoding = nil; fz_obj *widths = nil; unsigned short *etable = nil; pdf_fontdesc *fontdesc; fz_irect bbox; FT_Face face; FT_CharMap cmap; int kind; int symbolic; char *basefont; char *fontname; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; basefont = fz_toname(fz_dictgets(dict, "BaseFont")); fontname = cleanfontname(basefont); /* * Load font file */ fontdesc = pdf_newfontdesc(); if (!fontdesc) return fz_rethrow(-1, "out of memory"); pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("basefont0 %s\n", basefont); pdf_logfont("basefont1 %s\n", fontname); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor && basefont == fontname) error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, nil); else error = pdf_loadbuiltinfont(fontdesc, fontname); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM; bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM; bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM; pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = nil; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn("freetype could not set cmap: %s", ft_errorstring(fterr)); } else fz_warn("freetype could not find any cmaps"); etable = fz_malloc(sizeof(unsigned short) * 256); if (!etable) goto cleanup; for (i = 0; i < 256; i++) { estrings[i] = nil; etable[i] = 0; } encoding = fz_dictgets(dict, "Encoding"); if (encoding && !(kind == TRUETYPE && symbolic)) { if (fz_isname(encoding)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); else if (!fontdesc->isembedded) pdf_loadencoding(estrings, "StandardEncoding"); diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } if (kind == TYPE1) { pdf_logfont("encode type1/cff by strings\n"); for (i = 0; i < 256; i++) if (estrings[i]) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, i); } if (kind == TRUETYPE) { /* Unicode cmap */ if (face->charmap && face->charmap->platform_id == 3) { pdf_logfont("encode truetype via unicode\n"); for (i = 0; i < 256; i++) if (estrings[i]) { int aglbuf[256]; int aglnum; aglnum = pdf_lookupagl(estrings[i], aglbuf, nelem(aglbuf)); if (aglnum != 1) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, aglbuf[0]); } else etable[i] = ftcharindex(face, i); } /* MacRoman cmap */ else if (face->charmap && face->charmap->platform_id == 1) { pdf_logfont("encode truetype via macroman\n"); for (i = 0; i < 256; i++) if (estrings[i]) { k = mrecode(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, k); } else etable[i] = ftcharindex(face, i); } /* Symbolic cmap */ else { pdf_logfont("encode truetype symbolic\n"); for (i = 0; i < 256; i++) { etable[i] = ftcharindex(face, i); fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) { error = fz_throw("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); goto cleanup; } if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } } } } else { pdf_logfont("encode builtin\n"); for (i = 0; i < 256; i++) { etable[i] = ftcharindex(face, i); if (etable[i] == 0) continue; if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) { error = fz_throw("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); goto cleanup; } if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } } } error = pdf_newidentitycmap(&fontdesc->encoding, 0, 1); if (error) goto cleanup; fontdesc->ncidtogid = 256; fontdesc->cidtogid = etable; error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* * Widths */ pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth); widths = fz_dictgets(dict, "Widths"); if (widths) { int first, last; first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = fz_toint(fz_arrayget(widths, i)); error = pdf_addhmtx(fontdesc, i + first, i + first, wid); if (error) goto cleanup; } } else { fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn("freetype set character size: %s", ft_errorstring(fterr)); for (i = 0; i < 256; i++) { error = pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i)); if (error) goto cleanup; } } error = pdf_endhmtx(fontdesc); if (error) goto cleanup; pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: fz_free(etable); fz_dropfont(fontdesc->font); fz_free(fontdesc); return fz_rethrow(error, "cannot load simple font"); }
fz_error * pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; char buf[256]; char *estrings[256]; pdf_font *font; fz_obj *encoding; fz_obj *widths; fz_obj *resources; fz_obj *charprocs; fz_obj *obj; int first, last; int i, k, n; fz_rect bbox; obj = fz_dictgets(dict, "Name"); if (obj) strlcpy(buf, fz_toname(obj), sizeof buf); else sprintf(buf, "Unnamed-T3"); font = pdf_newfont(buf); if (!font) return fz_throw("outofmem: font struct"); pdf_logfont("load type3 font %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), font); pdf_logfont("name %s\n", buf); font->super.render = t3render; font->super.drop = (void(*)(fz_font*)) t3dropfont; obj = fz_dictgets(dict, "FontMatrix"); font->matrix = pdf_tomatrix(obj); pdf_logfont("matrix [%g %g %g %g %g %g]\n", font->matrix.a, font->matrix.b, font->matrix.c, font->matrix.d, font->matrix.e, font->matrix.f); obj = fz_dictgets(dict, "FontBBox"); bbox = pdf_torect(obj); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); bbox = fz_transformaabb(font->matrix, bbox); bbox.x0 = fz_floor(bbox.x0 * 1000); bbox.y0 = fz_floor(bbox.y0 * 1000); bbox.x1 = fz_ceil(bbox.x1 * 1000); bbox.y1 = fz_ceil(bbox.y1 * 1000); fz_setfontbbox((fz_font*)font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding */ for (i = 0; i < 256; i++) estrings[i] = nil; encoding = fz_dictgets(dict, "Encoding"); if (!encoding) { error = fz_throw("syntaxerror: Type3 font missing Encoding"); goto cleanup; } error = pdf_resolve(&encoding, xref); if (error) goto cleanup; if (fz_isname(obj)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { n = fz_arraylen(diff); k = 0; for (i = 0; i < n; i++) { item = fz_arrayget(diff, i); if (fz_isint(item)) k = fz_toint(item); if (fz_isname(item)) estrings[k++] = fz_toname(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } fz_dropobj(encoding); error = pdf_newidentitycmap(&font->encoding, 0, 1); if (error) goto cleanup; error = pdf_loadtounicode(font, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* * Widths */ fz_setdefaulthmtx((fz_font*)font, 0); first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); widths = fz_dictgets(dict, "Widths"); if (!widths) { error = fz_throw("syntaxerror: Type3 font missing Widths"); goto cleanup; } error = pdf_resolve(&widths, xref); if (error) goto cleanup; for (i = first; i <= last; i++) { float w = fz_toreal(fz_arrayget(widths, i - first)); w = font->matrix.a * w * 1000.0; error = fz_addhmtx((fz_font*)font, i, i, w); if (error) { fz_dropobj(widths); goto cleanup; } } fz_dropobj(widths); error = fz_endhmtx((fz_font*)font); if (error) goto cleanup; /* * Resources */ resources = nil; obj = fz_dictgets(dict, "Resources"); if (obj) { error = pdf_resolve(&obj, xref); if (error) goto cleanup; error = pdf_loadresources(&resources, xref, obj); fz_dropobj(obj); if (error) goto cleanup; } else pdf_logfont("no resource dict!\n"); /* * CharProcs */ charprocs = fz_dictgets(dict, "CharProcs"); if (!charprocs) { error = fz_throw("syntaxerror: Type3 font missing CharProcs"); goto cleanup2; } error = pdf_resolve(&charprocs, xref); if (error) goto cleanup2; for (i = 0; i < 256; i++) { if (estrings[i]) { obj = fz_dictgets(charprocs, estrings[i]); if (obj) { pdf_logfont("load charproc %s {\n", estrings[i]); error = loadcharproc(&font->charprocs[i], xref, resources, obj); if (error) goto cleanup2; error = fz_optimizetree(font->charprocs[i]); if (error) goto cleanup2; pdf_logfont("}\n"); } } } fz_dropobj(charprocs); if (resources) fz_dropobj(resources); pdf_logfont("}\n"); *fontp = font; return fz_okay; cleanup2: if (resources) fz_dropobj(resources); cleanup: fz_dropfont((fz_font*)font); return fz_rethrow(error, "cannot load type3 font"); }
/* * Construct a filter to decode a stream, constraining * to stream length and decrypting. */ static fz_error * pdf_buildfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int gen) { fz_error *error; fz_filter *base, *pipe, *tmp; fz_obj *filters; fz_obj *params; error = buildrawfilter(&base, xref, stmobj, oid, gen); if (error) return fz_rethrow(error, "cannot create raw filter chain"); filters = fz_dictgetsa(stmobj, "Filter", "F"); params = fz_dictgetsa(stmobj, "DecodeParms", "DP"); if (filters) { error = pdf_resolve(&filters, xref); if (error) { error = fz_rethrow(error, "cannot resolve stream /Filter"); goto cleanup0; } if (params) { error = pdf_resolve(¶ms, xref); if (error) { error = fz_rethrow(error, "cannot resolve stream /DecodeParms"); goto cleanup1; } } if (fz_isname(filters)) { error = buildonefilter(&tmp, filters, params); if (error) { error = fz_rethrow(error, "cannot create filter"); goto cleanup2; } error = fz_newpipeline(&pipe, base, tmp); fz_dropfilter(base); fz_dropfilter(tmp); if (error) { error = fz_rethrow(error, "cannot create filter pipeline"); goto cleanup2; } } else { error = buildfilterchain(&pipe, base, filters, params); if (error) { error = fz_rethrow(error, "cannot create filter chain"); goto cleanup2; } } if (params) fz_dropobj(params); fz_dropobj(filters); *filterp = pipe; } else { *filterp = base; } return fz_okay; cleanup2: if (params) fz_dropobj(params); cleanup1: fz_dropobj(filters); cleanup0: fz_dropfilter(base); return error; /* already rethrown */ }
static int isimage(fz_obj *obj) { fz_obj *type = fz_dictgets(obj, "Subtype"); return fz_isname(type) && !strcmp(fz_toname(type), "Image"); }