fz_error * pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; char *subtype; if ((*fontp = pdf_finditem(xref->store, PDF_KFONT, ref))) { fz_keepfont((fz_font*)*fontp); return fz_okay; } subtype = fz_toname(fz_dictgets(dict, "Subtype")); if (!strcmp(subtype, "Type0")) error = loadtype0(fontp, xref, dict, ref); else if (!strcmp(subtype, "Type1") || !strcmp(subtype, "MMType1")) error = loadsimplefont(fontp, xref, dict, ref); else if (!strcmp(subtype, "TrueType")) error = loadsimplefont(fontp, xref, dict, ref); else if (!strcmp(subtype, "Type3")) error = pdf_loadtype3font(fontp, xref, dict, ref); else return fz_throw("cannot recognize font format %s", subtype); if (error) return fz_rethrow(error, "cannot load font"); error = pdf_storeitem(xref->store, PDF_KFONT, ref, *fontp); if (error) return fz_rethrow(error, "cannot store font resource"); return fz_okay; }
fz_error pdf_loadfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) { fz_error error; char *subtype; fz_obj *dfonts; fz_obj *charprocs; if ((*fontdescp = pdf_finditem(xref->store, pdf_dropfont, dict))) { pdf_keepfont(*fontdescp); return fz_okay; } subtype = fz_toname(fz_dictgets(dict, "Subtype")); dfonts = fz_dictgets(dict, "DescendantFonts"); charprocs = fz_dictgets(dict, "CharProcs"); if (subtype && !strcmp(subtype, "Type0")) error = loadtype0(fontdescp, xref, dict); else if (subtype && !strcmp(subtype, "Type1")) error = loadsimplefont(fontdescp, xref, dict); else if (subtype && !strcmp(subtype, "MMType1")) error = loadsimplefont(fontdescp, xref, dict); else if (subtype && !strcmp(subtype, "TrueType")) error = loadsimplefont(fontdescp, xref, dict); else if (subtype && !strcmp(subtype, "Type3")) error = pdf_loadtype3font(fontdescp, xref, rdb, dict); else if (charprocs) { fz_warn("unknown font format, guessing type3."); error = pdf_loadtype3font(fontdescp, xref, rdb, dict); } else if (dfonts) { fz_warn("unknown font format, guessing type0."); error = loadtype0(fontdescp, xref, dict); } else { fz_warn("unknown font format, guessing type1 or truetype."); error = loadsimplefont(fontdescp, xref, dict); } if (error) return fz_rethrow(error, "cannot load font (%d %d R)", fz_tonum(dict), fz_togen(dict)); /* Save the widths to stretch non-CJK substitute fonts */ if ((*fontdescp)->font->ftsubstitute && !(*fontdescp)->tottfcmap) pdf_makewidthtable(*fontdescp); /* SumatraPDF: this font renders wrong without hinting */ if (strstr((*fontdescp)->font->name, "MingLiU")) (*fontdescp)->font->fthint = 1; pdf_storeitem(xref->store, pdf_keepfont, pdf_dropfont, dict, *fontdescp); return fz_okay; }
fz_error pdf_loadfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) { fz_error error; char *subtype; fz_obj *dfonts; fz_obj *charprocs; if ((*fontdescp = pdf_finditem(xref->store, PDF_KFONT, dict))) { pdf_keepfont(*fontdescp); return fz_okay; } subtype = fz_toname(fz_dictgets(dict, "Subtype")); dfonts = fz_dictgets(dict, "DescendantFonts"); charprocs = fz_dictgets(dict, "CharProcs"); if (subtype && !strcmp(subtype, "Type0")) error = loadtype0(fontdescp, xref, dict); else if (subtype && !strcmp(subtype, "Type1")) error = loadsimplefont(fontdescp, xref, dict); else if (subtype && !strcmp(subtype, "MMType1")) error = loadsimplefont(fontdescp, xref, dict); else if (subtype && !strcmp(subtype, "TrueType")) error = loadsimplefont(fontdescp, xref, dict); else if (subtype && !strcmp(subtype, "Type3")) error = pdf_loadtype3font(fontdescp, xref, rdb, dict); else if (charprocs) { fz_warn("unknown font format, guessing type3."); error = pdf_loadtype3font(fontdescp, xref, rdb, dict); } else if (dfonts) { fz_warn("unknown font format, guessing type0."); error = loadtype0(fontdescp, xref, dict); } else { fz_warn("unknown font format, guessing type1 or truetype."); error = loadsimplefont(fontdescp, xref, dict); } if (error) return fz_rethrow(error, "cannot load font"); error = pdf_storeitem(xref->store, PDF_KFONT, dict, *fontdescp); if (error) return fz_rethrow(error, "cannot store font resource"); return fz_okay; }
fz_error pdf_loadcolorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj) { fz_error error; if ((*csp = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj))) { fz_keepcolorspace(*csp); return fz_okay; } error = pdf_loadcolorspaceimp(csp, xref, obj); if (error) return fz_rethrow(error, "cannot load colorspace"); pdf_storeitem(xref->store, PDF_KCOLORSPACE, obj, *csp); return fz_okay; }
fz_error pdf_loadimage(fz_pixmap **pixp, pdf_xref *xref, fz_obj *dict) { fz_error error; if ((*pixp = pdf_finditem(xref->store, fz_droppixmap, dict))) { fz_keeppixmap(*pixp); return fz_okay; } pdf_logimage("load image (%d 0 R) {\n", fz_tonum(dict)); error = pdf_loadimageimp(pixp, xref, nil, dict, nil, 0); if (error) return fz_rethrow(error, "cannot load image (%d 0 R)", fz_tonum(dict)); pdf_storeitem(xref->store, fz_keeppixmap, fz_droppixmap, dict, *pixp); pdf_logimage("}\n"); return fz_okay; }
fz_error pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict) { fz_error error; pdf_pattern *pat; fz_obj *obj; if ((*patp = pdf_finditem(xref->store, pdf_droppattern, dict))) { pdf_keeppattern(*patp); return fz_okay; } pdf_logrsrc("load pattern (%d %d R) {\n", fz_tonum(dict), fz_togen(dict)); pat = fz_malloc(sizeof(pdf_pattern)); pat->refs = 1; pat->resources = nil; pat->contents = nil; /* Store pattern now, to avoid possible recursion if objects refer back to this one */ pdf_storeitem(xref->store, pdf_keeppattern, pdf_droppattern, dict, pat); pat->ismask = fz_toint(fz_dictgets(dict, "PaintType")) == 2; pat->xstep = fz_toreal(fz_dictgets(dict, "XStep")); pat->ystep = fz_toreal(fz_dictgets(dict, "YStep")); pdf_logrsrc("mask %d\n", pat->ismask); pdf_logrsrc("xstep %g\n", pat->xstep); pdf_logrsrc("ystep %g\n", pat->ystep); obj = fz_dictgets(dict, "BBox"); pat->bbox = pdf_torect(obj); pdf_logrsrc("bbox [%g %g %g %g]\n", pat->bbox.x0, pat->bbox.y0, pat->bbox.x1, pat->bbox.y1); obj = fz_dictgets(dict, "Matrix"); if (obj) pat->matrix = pdf_tomatrix(obj); else pat->matrix = fz_identity; pdf_logrsrc("matrix [%g %g %g %g %g %g]\n", pat->matrix.a, pat->matrix.b, pat->matrix.c, pat->matrix.d, pat->matrix.e, pat->matrix.f); pat->resources = fz_dictgets(dict, "Resources"); if (pat->resources) fz_keepobj(pat->resources); error = pdf_loadstream(&pat->contents, xref, fz_tonum(dict), fz_togen(dict)); if (error) { pdf_removeitem(xref->store, pdf_droppattern, dict); pdf_droppattern(pat); return fz_rethrow(error, "cannot load pattern stream (%d %d R)", fz_tonum(dict), fz_togen(dict)); } pdf_logrsrc("}\n"); *patp = pat; return fz_okay; }
fz_error * pdf_loadshade(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; fz_matrix mat; fz_obj *obj; fz_obj *shd; if ((*shadep = pdf_finditem(xref->store, PDF_KSHADE, ref))) return nil; /* * Type 2 pattern dictionary */ if (fz_dictgets(dict, "PatternType")) { pdf_logshade("load shade pattern %d %d {\n", fz_tonum(ref), fz_togen(ref)); obj = fz_dictgets(dict, "Matrix"); if (obj) { mat = pdf_tomatrix(obj); pdf_logshade("matrix [%g %g %g %g %g %g]\n", mat.a, mat.b, mat.c, mat.d, mat.e, mat.f); } else { mat = fz_identity(); } obj = fz_dictgets(dict, "ExtGState"); if (obj) { pdf_logshade("extgstate ...\n"); } obj = fz_dictgets(dict, "Shading"); if (!obj) return fz_throw("syntaxerror: missing shading dictionary"); shd = obj; error = pdf_resolve(&shd, xref); if (error) return error; error = loadshadedict(shadep, xref, shd, obj, mat); fz_dropobj(shd); if (error) return error; pdf_logshade("}\n"); } /* * Naked shading dictionary */ else { error = loadshadedict(shadep, xref, dict, ref, fz_identity()); if (error) return error; } error = pdf_storeitem(xref->store, PDF_KSHADE, ref, *shadep); if (error) { fz_dropshade(*shadep); return error; } return nil; }
/* * 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_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; pdf_xobject *form; fz_obj *obj; if ((*formp = pdf_finditem(xref->store, PDF_KXOBJECT, ref))) { pdf_keepxobject(*formp); return fz_okay; } form = fz_malloc(sizeof(pdf_xobject)); if (!form) return fz_throw("outofmem: xobject struct"); form->refs = 1; form->resources = nil; form->contents = nil; /* Store item immediately, to avoid infinite recursion if contained objects refer again to this xobject */ error = pdf_storeitem(xref->store, PDF_KXOBJECT, ref, form); if (error) { pdf_dropxobject(form); return fz_rethrow(error, "cannot store xobject resource"); } pdf_logrsrc("load xobject %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), 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); obj = fz_dictgets(dict, "I"); form->isolated = fz_tobool(obj); obj = fz_dictgets(dict, "K"); form->knockout = fz_tobool(obj); pdf_logrsrc("isolated %d\n", form->isolated); pdf_logrsrc("knockout %d\n", form->knockout); obj = fz_dictgets(dict, "Resources"); if (obj) { error = pdf_resolve(&obj, xref); if (error) { fz_dropobj(obj); error = fz_rethrow(error, "cannot resolve xobject resources"); goto cleanup; } error = pdf_loadresources(&form->resources, xref, obj); fz_dropobj(obj); if (error) { error = fz_rethrow(error, "cannot load xobject resources"); goto cleanup; } } error = pdf_loadstream(&form->contents, xref, fz_tonum(ref), fz_togen(ref)); if (error) { error = fz_rethrow(error, "cannot load xobject content stream"); goto cleanup; } pdf_logrsrc("stream %d bytes\n", form->contents->wp - form->contents->rp); pdf_logrsrc("}\n"); *formp = form; return fz_okay; cleanup: pdf_removeitem(xref->store, PDF_KXOBJECT, ref); pdf_dropxobject(form); return error; }
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; }
/* TODO error cleanup */ fz_error * pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; pdf_image *img; pdf_image *mask; int ismask; fz_obj *obj; fz_obj *sub; int i; int w, h, bpc; int n = 0; int a = 0; int usecolorkey = 0; fz_colorspace *cs = nil; pdf_indexed *indexed = nil; int stride; #ifndef PSP printf("LI\n"); #endif if ((*imgp = pdf_finditem(xref->store, PDF_KIMAGE, ref))) { fz_keepimage((fz_image*)*imgp); return nil; } img = fz_malloc(sizeof(pdf_image)); if (!img) return fz_outofmem; img->super.refs = 0; pdf_logimage("load image %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), img); /* * Dimensions, BPC and ColorSpace */ w = fz_toint(fz_dictgets(dict, "Width")); h = fz_toint(fz_dictgets(dict, "Height")); bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent")); pdf_logimage("size %dx%d %d\n", w, h, bpc); cs = nil; obj = fz_dictgets(dict, "ColorSpace"); if (obj) { cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj); if (cs) fz_keepcolorspace(cs); else { error = pdf_resolve(&obj, xref); if (error) return error; error = pdf_loadcolorspace(&cs, xref, obj); if (error) return error; fz_dropobj(obj); } if (!strcmp(cs->name, "Indexed")) { pdf_logimage("indexed\n"); indexed = (pdf_indexed*)cs; cs = indexed->base; } n = cs->n; a = 0; pdf_logimage("colorspace %s\n", cs->name); } /* * ImageMask, Mask and SoftMask */ mask = nil; ismask = fz_tobool(fz_dictgets(dict, "ImageMask")); if (ismask) { pdf_logimage("is mask\n"); bpc = 1; n = 0; a = 1; } obj = fz_dictgets(dict, "SMask"); if (fz_isindirect(obj)) { pdf_logimage("has soft mask\n"); error = pdf_loadindirect(&sub, xref, obj); if (error) return error; error = pdf_loadimage(&mask, xref, sub, obj); if (error) return error; if (mask->super.cs != pdf_devicegray) return fz_throw("syntaxerror: SMask must be DeviceGray"); mask->super.cs = 0; mask->super.n = 0; mask->super.a = 1; fz_dropobj(sub); } obj = fz_dictgets(dict, "Mask"); if (fz_isindirect(obj)) { error = pdf_loadindirect(&sub, xref, obj); if (error) return error; if (fz_isarray(sub)) { usecolorkey = 1; loadcolorkey(img->colorkey, bpc, indexed != nil, sub); } else { pdf_logimage("has mask\n"); error = pdf_loadimage(&mask, xref, sub, obj); if (error) return error; } fz_dropobj(sub); } else if (fz_isarray(obj)) { usecolorkey = 1; loadcolorkey(img->colorkey, bpc, indexed != nil, obj); } /* * Decode */ obj = fz_dictgets(dict, "Decode"); if (fz_isarray(obj)) { pdf_logimage("decode array\n"); if (indexed) for (i = 0; i < 2; i++) img->decode[i] = fz_toreal(fz_arrayget(obj, i)); else for (i = 0; i < (n + a) * 2; i++) img->decode[i] = fz_toreal(fz_arrayget(obj, i)); } else { if (indexed) for (i = 0; i < 2; i++) img->decode[i] = i & 1 ? (1 << bpc) - 1 : 0; else for (i = 0; i < (n + a) * 2; i++) img->decode[i] = i & 1; } /* * Load samples */ if (indexed) stride = (w * bpc + 7) / 8; else stride = (w * (n + a) * bpc + 7) / 8; // ccm // do not load images larger than 2MB uncompressed int early_reject = 0; if (h * stride <= 2*1024*1024) { error = pdf_loadstream(&img->samples, xref, fz_tonum(ref), fz_togen(ref)); if (error) { /* TODO: colorspace? */ fz_free(img); return error; } if (img->samples->wp - img->samples->bp < stride * h) { /* TODO: colorspace? */ fz_dropbuffer(img->samples); fz_free(img); return fz_throw("syntaxerror: truncated image data"); } /* 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; } } else { #ifndef PSP printf("LI - %p - early reject\n", img); #endif img->samples = nil; early_reject = 1; } /* * Create image object */ img->super.loadtile = pdf_loadtile; img->super.drop = pdf_dropimage; img->super.cs = cs; img->super.w = w; img->super.h = h; img->super.n = n; img->super.a = a; img->indexed = indexed; img->stride = stride; img->bpc = bpc; img->mask = (fz_image*)mask; img->usecolorkey = usecolorkey; if (img->mask) fz_keepimage(img->mask); // ccm #if 1 int bs = 0; if (img->samples) bs = (int)(img->samples->wp) - (int)(img->samples->rp); if (early_reject || (image_buffers_size + bs >= image_buffers_size_max)) { #ifndef PSP printf("LI - %p - optimized out\n", img); #endif if (img->samples) fz_dropbuffer(img->samples); if (img->mask) fz_dropimage(img->mask); fz_newbuffer(&img->samples, 8); img->super.w = 1; img->super.h = 1; img->super.n = 3; img->super.a = 0; img->super.refs = 0; unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = 0x7f; img->indexed = 0; img->stride = (1 * (3 + 0) * 8 + 7) / 8; //(w * (n + a) * bpc + 7) / 8; img->super.cs = cs; img->super.loadtile = fakeImageTile; img->bpc = 8; img->mask = NULL; img->usecolorkey = 0; } else { image_buffers_size += bs; } #endif pdf_logimage("}\n"); error = pdf_storeitem(xref->store, PDF_KIMAGE, ref, img); if (error) { fz_dropimage((fz_image*)img); return error; } *imgp = img; return nil; }