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; }
static int pdf_resourcesuseblending(fz_obj *rdb) { fz_obj *dict; fz_obj *tmp; int i; /* stop on cyclic resource dependencies */ if (fz_dictgets(rdb, ".useBM")) return fz_tobool(fz_dictgets(rdb, ".useBM")); tmp = fz_newbool(0); fz_dictputs(rdb, ".useBM", tmp); fz_dropobj(tmp); dict = fz_dictgets(rdb, "ExtGState"); for (i = 0; i < fz_dictlen(dict); i++) if (pdf_extgstateusesblending(fz_dictgetval(dict, i))) goto found; dict = fz_dictgets(rdb, "Pattern"); for (i = 0; i < fz_dictlen(dict); i++) if (pdf_patternusesblending(fz_dictgetval(dict, i))) goto found; dict = fz_dictgets(rdb, "XObject"); for (i = 0; i < fz_dictlen(dict); i++) if (pdf_xobjectusesblending(fz_dictgetval(dict, i))) goto found; return 0; found: tmp = fz_newbool(1); fz_dictputs(rdb, ".useBM", tmp); fz_dropobj(tmp); return 1; }
static fz_error gathershadings(int page, fz_obj *pageobj, fz_obj *dict) { int i; for (i = 0; i < fz_dictlen(dict); i++) { fz_obj *ref; fz_obj *shade; fz_obj *type; int k; shade = ref = fz_dictgetval(dict, i); if (!fz_isdict(shade)) return fz_throw("not a shading dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); type = fz_dictgets(shade, "ShadingType"); if (!fz_isint(type) || fz_toint(type) < 1 || fz_toint(type) > 7) { fz_warn("not a shading type (%d %d R)", fz_tonum(ref), fz_togen(ref)); type = nil; } for (k = 0; k < shadings; k++) if (fz_tonum(shading[k]->ref) == fz_tonum(ref) && fz_togen(shading[k]->ref) == fz_togen(ref)) break; if (k < shadings) continue; shadings++; shading = fz_realloc(shading, shadings * sizeof (struct info *)); if (!shading) return fz_throw("out of memory"); shading[shadings - 1] = fz_malloc(sizeof (struct info)); if (!shading[shadings - 1]) return fz_throw("out of memory"); shading[shadings - 1]->page = page; shading[shadings - 1]->pageobj = pageobj; shading[shadings - 1]->ref = ref; shading[shadings - 1]->u.shading.type = type; } return fz_okay; }
static void sweepobj(fz_obj *obj) { int i; if (fz_isindirect(obj)) sweepref(obj); else if (fz_isdict(obj)) for (i = 0; i < fz_dictlen(obj); i++) sweepobj(fz_dictgetval(obj, i)); else if (fz_isarray(obj)) for (i = 0; i < fz_arraylen(obj); i++) sweepobj(fz_arrayget(obj, i)); }
static void renumberobj(fz_obj *obj) { int i; if (fz_isdict(obj)) { for (i = 0; i < fz_dictlen(obj); i++) { fz_obj *key = fz_dictgetkey(obj, i); fz_obj *val = fz_dictgetval(obj, i); if (fz_isindirect(val)) { val = fz_newindirect(renumbermap[fz_tonum(val)], 0, xref); fz_dictput(obj, key, val); fz_dropobj(val); } else { renumberobj(val); } } } else if (fz_isarray(obj)) { for (i = 0; i < fz_arraylen(obj); i++) { fz_obj *val = fz_arrayget(obj, i); if (fz_isindirect(val)) { val = fz_newindirect(renumbermap[fz_tonum(val)], 0, xref); fz_arrayput(obj, i, val); fz_dropobj(val); } else { renumberobj(val); } } } }
static fz_error gatherpatterns(int page, fz_obj *pageobj, fz_obj *dict) { int i; for (i = 0; i < fz_dictlen(dict); i++) { fz_obj *ref; fz_obj *patterndict; fz_obj *type; fz_obj *paint = nil; fz_obj *tiling = nil; int k; patterndict = ref = fz_dictgetval(dict, i); if (!fz_isdict(patterndict)) return fz_throw("not a pattern dict (%d %d R)", fz_tonum(ref), fz_togen(ref)); type = fz_dictgets(patterndict, "PatternType"); if (!fz_isint(type) || fz_toint(type) < 1 || fz_toint(type) > 2) { fz_warn("not a pattern type (%d %d R)", fz_tonum(ref), fz_togen(ref)); type = nil; } if (fz_toint(type) == 1) { paint = fz_dictgets(patterndict, "PaintType"); if (!fz_isint(paint) || fz_toint(paint) < 1 || fz_toint(paint) > 2) { fz_warn("not a pattern paint type (%d %d R)", fz_tonum(ref), fz_togen(ref)); paint = nil; } tiling = fz_dictgets(patterndict, "TilingType"); if (!fz_isint(tiling) || fz_toint(tiling) < 1 || fz_toint(tiling) > 3) { fz_warn("not a pattern tiling type (%d %d R)", fz_tonum(ref), fz_togen(ref)); tiling = nil; } } for (k = 0; k < patterns; k++) if (fz_tonum(pattern[k]->ref) == fz_tonum(ref) && fz_togen(pattern[k]->ref) == fz_togen(ref)) break; if (k < patterns) continue; patterns++; pattern = fz_realloc(pattern, patterns * sizeof (struct info *)); if (!pattern) return fz_throw("out of memory"); pattern[patterns - 1] = fz_malloc(sizeof (struct info)); if (!pattern[patterns - 1]) return fz_throw("out of memory"); pattern[patterns - 1]->page = page; pattern[patterns - 1]->pageobj = pageobj; pattern[patterns - 1]->ref = ref; pattern[patterns - 1]->u.pattern.pattern = type; pattern[patterns - 1]->u.pattern.paint = paint; pattern[patterns - 1]->u.pattern.tiling = tiling; } 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; }