diff options
Diffstat (limited to 'Build/source/libs/poppler/poppler-src/poppler/Gfx.cc')
-rw-r--r-- | Build/source/libs/poppler/poppler-src/poppler/Gfx.cc | 910 |
1 files changed, 374 insertions, 536 deletions
diff --git a/Build/source/libs/poppler/poppler-src/poppler/Gfx.cc b/Build/source/libs/poppler/poppler-src/poppler/Gfx.cc index a8f5be95e4b..531acbd41a2 100644 --- a/Build/source/libs/poppler/poppler-src/poppler/Gfx.cc +++ b/Build/source/libs/poppler/poppler-src/poppler/Gfx.cc @@ -14,13 +14,13 @@ // under GPL version 2 or later // // Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com> -// Copyright (C) 2005-2013, 2015, 2016 Albert Astals Cid <aacid@kde.org> +// Copyright (C) 2005-2013, 2015-2017 Albert Astals Cid <aacid@kde.org> // Copyright (C) 2006 Thorkild Stray <thorkild@ifi.uio.no> // Copyright (C) 2006 Kristian Høgsberg <krh@redhat.com> // Copyright (C) 2006-2011 Carlos Garcia Campos <carlosgc@gnome.org> // Copyright (C) 2006, 2007 Jeff Muizelaar <jeff@infidigm.net> // Copyright (C) 2007, 2008 Brad Hards <bradh@kde.org> -// Copyright (C) 2007, 2011 Adrian Johnson <ajohnson@redneon.com> +// Copyright (C) 2007, 2011, 2017 Adrian Johnson <ajohnson@redneon.com> // Copyright (C) 2007, 2008 Iñigo Martínez <inigomartinez@gmail.com> // Copyright (C) 2007 Koji Otani <sho@bbr.jp> // Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk@gmail.com> @@ -55,6 +55,7 @@ #include <stddef.h> #include <string.h> #include <math.h> +#include <memory> #include "goo/gmem.h" #include "goo/GooTimer.h" #include "goo/GooHash.h" @@ -132,10 +133,6 @@ // Operator table //------------------------------------------------------------------------ -#ifdef _MSC_VER // this works around a bug in the VC7 compiler -# pragma optimize("",off) -#endif - Operator Gfx::opTab[] = { {"\"", 3, {tchkNum, tchkNum, tchkString}, &Gfx::opMoveSetShowText}, @@ -305,10 +302,6 @@ Operator Gfx::opTab[] = { &Gfx::opCurveTo2}, }; -#ifdef _MSC_VER // this works around a bug in the VC7 compiler -# pragma optimize("",on) -#endif - #define numOps (sizeof(opTab) / sizeof(Operator)) static inline GBool isSameGfxColor(const GfxColor &colorA, const GfxColor &colorB, Guint nComps, double delta) { @@ -334,61 +327,51 @@ GfxResources::GfxResources(XRef *xref, Dict *resDictA, GfxResources *nextA) : // build font dictionary Dict *resDict = resDictA->copy(xref); fonts = NULL; - resDict->lookupNF("Font", &obj1); + obj1 = resDict->lookupNF("Font"); if (obj1.isRef()) { - obj1.fetch(xref, &obj2); + obj2 = obj1.fetch(xref); if (obj2.isDict()) { r = obj1.getRef(); fonts = new GfxFontDict(xref, &r, obj2.getDict()); } - obj2.free(); } else if (obj1.isDict()) { fonts = new GfxFontDict(xref, NULL, obj1.getDict()); } - obj1.free(); // get XObject dictionary - resDict->lookup("XObject", &xObjDict); + xObjDict = resDict->lookup("XObject"); // get color space dictionary - resDict->lookup("ColorSpace", &colorSpaceDict); + colorSpaceDict = resDict->lookup("ColorSpace"); // get pattern dictionary - resDict->lookup("Pattern", &patternDict); + patternDict = resDict->lookup("Pattern"); // get shading dictionary - resDict->lookup("Shading", &shadingDict); + shadingDict = resDict->lookup("Shading"); // get graphics state parameter dictionary - resDict->lookup("ExtGState", &gStateDict); + gStateDict = resDict->lookup("ExtGState"); // get properties dictionary - resDict->lookup("Properties", &propertiesDict); + propertiesDict = resDict->lookup("Properties"); delete resDict; } else { fonts = NULL; - xObjDict.initNull(); - colorSpaceDict.initNull(); - patternDict.initNull(); - shadingDict.initNull(); - gStateDict.initNull(); - propertiesDict.initNull(); + xObjDict.setToNull(); + colorSpaceDict.setToNull(); + patternDict.setToNull(); + shadingDict.setToNull(); + gStateDict.setToNull(); + propertiesDict.setToNull(); } next = nextA; } GfxResources::~GfxResources() { - if (fonts) { - delete fonts; - } - xObjDict.free(); - colorSpaceDict.free(); - patternDict.free(); - shadingDict.free(); - gStateDict.free(); - propertiesDict.free(); + delete fonts; } GfxFont *GfxResources::lookupFont(char *name) { @@ -405,75 +388,79 @@ GfxFont *GfxResources::lookupFont(char *name) { return NULL; } -GBool GfxResources::lookupXObject(char *name, Object *obj) { +Object GfxResources::lookupXObject(char *name) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->xObjDict.isDict()) { - if (!resPtr->xObjDict.dictLookup(name, obj)->isNull()) - return gTrue; - obj->free(); + Object obj = resPtr->xObjDict.dictLookup(name); + if (!obj.isNull()) + return obj; } } error(errSyntaxError, -1, "XObject '{0:s}' is unknown", name); - return gFalse; + return Object(objNull); } -GBool GfxResources::lookupXObjectNF(char *name, Object *obj) { +Object GfxResources::lookupXObjectNF(char *name) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->xObjDict.isDict()) { - if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull()) - return gTrue; - obj->free(); + Object obj = resPtr->xObjDict.dictLookupNF(name); + if (!obj.isNull()) + return obj; } } error(errSyntaxError, -1, "XObject '{0:s}' is unknown", name); - return gFalse; + return Object(objNull); } -GBool GfxResources::lookupMarkedContentNF(char *name, Object *obj) { +Object GfxResources::lookupMarkedContentNF(char *name) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->propertiesDict.isDict()) { - if (!resPtr->propertiesDict.dictLookupNF(name, obj)->isNull()) - return gTrue; - obj->free(); + Object obj = resPtr->propertiesDict.dictLookupNF(name); + if (!obj.isNull()) + return obj; } } error(errSyntaxError, -1, "Marked Content '{0:s}' is unknown", name); - return gFalse; + return Object(objNull); } -void GfxResources::lookupColorSpace(const char *name, Object *obj) { +Object GfxResources::lookupColorSpace(const char *name) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->colorSpaceDict.isDict()) { - if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) { - return; + Object obj = resPtr->colorSpaceDict.dictLookup(name); + if (!obj.isNull()) { + return obj; } - obj->free(); } } - obj->initNull(); + return Object(objNull); } GfxPattern *GfxResources::lookupPattern(char *name, OutputDev *out, GfxState *state) { GfxResources *resPtr; GfxPattern *pattern; - Object obj; for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->patternDict.isDict()) { - if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) { - pattern = GfxPattern::parse(resPtr, &obj, out, state); - obj.free(); + Object obj = resPtr->patternDict.dictLookupNF(name); + if (!obj.isNull()) { + Ref patternRef = { -1, -1 }; + if (obj.isRef()) { + patternRef = obj.getRef(); + obj = obj.fetch(resPtr->patternDict.getDict()->getXRef()); + } + + pattern = GfxPattern::parse(resPtr, &obj, out, state, patternRef.num); return pattern; } - obj.free(); } } error(errSyntaxError, -1, "Unknown pattern '{0:s}'", name); @@ -483,51 +470,50 @@ GfxPattern *GfxResources::lookupPattern(char *name, OutputDev *out, GfxState *st GfxShading *GfxResources::lookupShading(char *name, OutputDev *out, GfxState *state) { GfxResources *resPtr; GfxShading *shading; - Object obj; for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->shadingDict.isDict()) { - if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) { + Object obj = resPtr->shadingDict.dictLookup(name); + if (!obj.isNull()) { shading = GfxShading::parse(resPtr, &obj, out, state); - obj.free(); return shading; } - obj.free(); } } error(errSyntaxError, -1, "ExtGState '{0:s}' is unknown", name); return NULL; } -GBool GfxResources::lookupGState(char *name, Object *obj) { - if (!lookupGStateNF(name, obj)) - return gFalse; +Object GfxResources::lookupGState(char *name) { + Object obj = lookupGStateNF(name); + if (obj.isNull()) + return Object(objNull); - if (!obj->isRef()) - return gTrue; + if (!obj.isRef()) + return obj; - const Ref ref = obj->getRef(); - if (!gStateCache.lookup(ref, obj)->isNull()) - return gTrue; - obj->free(); + const Ref ref = obj.getRef(); + obj = gStateCache.lookup(ref); + if (!obj.isNull()) + return obj; - gStateCache.put(ref)->copy(obj); - return gTrue; + obj = gStateCache.put(ref)->copy(); + return obj; } -GBool GfxResources::lookupGStateNF(char *name, Object *obj) { +Object GfxResources::lookupGStateNF(char *name) { GfxResources *resPtr; for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->gStateDict.isDict()) { - if (!resPtr->gStateDict.dictLookupNF(name, obj)->isNull()) { - return gTrue; + Object obj = resPtr->gStateDict.dictLookupNF(name); + if (!obj.isNull()) { + return obj; } - obj->free(); } } error(errSyntaxError, -1, "ExtGState '{0:s}' is unknown", name); - return gFalse; + return Object(objNull); } //------------------------------------------------------------------------ @@ -644,25 +630,16 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, #ifdef USE_CMS -#ifdef USE_LCMS1 -#include <lcms.h> -#else #include <lcms2.h> -#define LCMS_FLAGS cmsFLAGS_NOOPTIMIZE -#endif void Gfx::initDisplayProfile() { - Object catDict; - xref->getCatalog(&catDict); + Object catDict = xref->getCatalog(); if (catDict.isDict()) { - Object outputIntents; - catDict.dictLookup("OutputIntents", &outputIntents); + Object outputIntents = catDict.dictLookup("OutputIntents"); if (outputIntents.isArray() && outputIntents.arrayGetLength() == 1) { - Object firstElement; - outputIntents.arrayGet(0, &firstElement); + Object firstElement = outputIntents.arrayGet(0); if (firstElement.isDict()) { - Object profile; - firstElement.dictLookup("DestOutputProfile", &profile); + Object profile = firstElement.dictLookup("DestOutputProfile"); if (profile.isStream()) { Stream *iccStream = profile.getStream(); int length = 0; @@ -675,13 +652,9 @@ void Gfx::initDisplayProfile() { } gfree(profBuf); } - profile.free(); } - firstElement.free(); } - outputIntents.free(); } - catDict.free(); } #endif @@ -708,18 +681,15 @@ Gfx::~Gfx() { } void Gfx::display(Object *obj, GBool topLevel) { - Object obj2; int i; if (obj->isArray()) { for (i = 0; i < obj->arrayGetLength(); ++i) { - obj->arrayGet(i, &obj2); + Object obj2 = obj->arrayGet(i); if (!obj2.isStream()) { error(errSyntaxError, -1, "Weird page contents"); - obj2.free(); return; } - obj2.free(); } } else if (!obj->isStream()) { error(errSyntaxError, -1, "Weird page contents"); @@ -742,7 +712,7 @@ void Gfx::go(GBool topLevel) { updateLevel = 1; // make sure even empty pages trigger a call to dump() lastAbortCheck = 0; numArgs = 0; - parser->getObj(&obj); + obj = parser->getObj(); while (!obj.isEOF()) { commandAborted = gFalse; @@ -757,13 +727,17 @@ void Gfx::go(GBool topLevel) { printf("\n"); fflush(stdout); } - GooTimer timer; + GooTimer *timer = nullptr; + + if (unlikely(profileCommands)) { + timer = new GooTimer(); + } // Run the operation execOp(&obj, args, numArgs); // Update the profile information - if (profileCommands) { + if (unlikely(profileCommands)) { GooHash *hash; hash = out->getProfileHash (); @@ -778,12 +752,12 @@ void Gfx::go(GBool topLevel) { hash->add (cmd_g, data_p); } - data_p->addElement(timer.getElapsed ()); + data_p->addElement(timer->getElapsed ()); } + delete timer; } - obj.free(); for (i = 0; i < numArgs; ++i) - args[i].free(); + args[i].setToNull(); // Free memory early numArgs = 0; // periodically update display @@ -812,8 +786,7 @@ void Gfx::go(GBool topLevel) { // got an argument - save it } else if (numArgs < maxArgs) { - args[numArgs++] = obj; - + args[numArgs++] = std::move(obj); // too many arguments - something is wrong } else { error(errSyntaxError, getPos(), "Too many args in content stream"); @@ -823,13 +796,11 @@ void Gfx::go(GBool topLevel) { printf("\n"); fflush(stdout); } - obj.free(); } // grab the next object - parser->getObj(&obj); + obj = parser->getObj(); } - obj.free(); // args at end with no command if (numArgs > 0) { @@ -843,8 +814,6 @@ void Gfx::go(GBool topLevel) { printf("\n"); fflush(stdout); } - for (i = 0; i < numArgs; ++i) - args[i].free(); } popStateGuard(); @@ -970,7 +939,6 @@ void Gfx::opConcat(Object args[], int numArgs) { void Gfx::opSetDash(Object args[], int numArgs) { Array *a; int length; - Object obj; double *dash; int i; @@ -981,11 +949,10 @@ void Gfx::opSetDash(Object args[], int numArgs) { } else { dash = (double *)gmallocn(length, sizeof(double)); for (i = 0; i < length; ++i) { - a->get(i, &obj); + Object obj = a->get(i); if (obj.isNum()) { dash[i] = obj.getNum(); } - obj.free(); } } state->setLineDash(dash, length, args[1].getNum()); @@ -1018,8 +985,7 @@ void Gfx::opSetLineWidth(Object args[], int numArgs) { } void Gfx::opSetExtGState(Object args[], int numArgs) { - Object obj1, obj2, obj3, obj4, obj5; - Object args2[2]; + Object obj1, obj2; GfxBlendMode mode; GBool haveFillOP; Function *funcs[4]; @@ -1030,12 +996,12 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { double opac; int i; - if (!res->lookupGState(args[0].getName(), &obj1)) { + obj1 = res->lookupGState(args[0].getName()); + if (obj1.isNull()) { return; } if (!obj1.isDict()) { error(errSyntaxError, getPos(), "ExtGState '{0:s}' is wrong type", args[0].getName()); - obj1.free(); return; } if (printCommands) { @@ -1045,33 +1011,31 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { } // parameters that are also set by individual PDF operators - if (obj1.dictLookup("LW", &obj2)->isNum()) { + obj2 = obj1.dictLookup("LW"); + if (obj2.isNum()) { opSetLineWidth(&obj2, 1); } - obj2.free(); - if (obj1.dictLookup("LC", &obj2)->isInt()) { + obj2 = obj1.dictLookup("LC"); + if (obj2.isInt()) { opSetLineCap(&obj2, 1); } - obj2.free(); - if (obj1.dictLookup("LJ", &obj2)->isInt()) { + obj2 = obj1.dictLookup("LJ"); + if (obj2.isInt()) { opSetLineJoin(&obj2, 1); } - obj2.free(); - if (obj1.dictLookup("ML", &obj2)->isNum()) { + obj2 = obj1.dictLookup("ML"); + if (obj2.isNum()) { opSetMiterLimit(&obj2, 1); } - obj2.free(); - if (obj1.dictLookup("D", &obj2)->isArray() && - obj2.arrayGetLength() == 2) { - obj2.arrayGet(0, &args2[0]); - obj2.arrayGet(1, &args2[1]); + obj2 = obj1.dictLookup("D"); + if (obj2.isArray() && obj2.arrayGetLength() == 2) { + Object args2[2]; + args2[0] = obj2.arrayGet(0); + args2[1] = obj2.arrayGet(1); if (args2[0].isArray() && args2[1].isNum()) { opSetDash(args2, 2); } - args2[0].free(); - args2[1].free(); } - obj2.free(); #if 0 //~ need to add a new version of GfxResources::lookupFont() that //~ takes an indirect ref instead of a name if (obj1.dictLookup("Font", &obj2)->isArray() && @@ -1086,13 +1050,14 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { } obj2.free(); #endif - if (obj1.dictLookup("FL", &obj2)->isNum()) { + obj2 = obj1.dictLookup("FL"); + if (obj2.isNum()) { opSetFlat(&obj2, 1); } - obj2.free(); // transparency support: blend mode, fill/stroke opacity - if (!obj1.dictLookup("BM", &obj2)->isNull()) { + obj2 = obj1.dictLookup("BM"); + if (!obj2.isNull()) { if (state->parseBlendMode(&obj2, &mode)) { state->setBlendMode(mode); out->updateBlendMode(state); @@ -1100,27 +1065,27 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { error(errSyntaxError, getPos(), "Invalid blend mode in ExtGState"); } } - obj2.free(); - if (obj1.dictLookup("ca", &obj2)->isNum()) { + obj2 = obj1.dictLookup("ca"); + if (obj2.isNum()) { opac = obj2.getNum(); state->setFillOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac); out->updateFillOpacity(state); } - obj2.free(); - if (obj1.dictLookup("CA", &obj2)->isNum()) { + obj2 = obj1.dictLookup("CA"); + if (obj2.isNum()) { opac = obj2.getNum(); state->setStrokeOpacity(opac < 0 ? 0 : opac > 1 ? 1 : opac); out->updateStrokeOpacity(state); } - obj2.free(); // fill/stroke overprint, overprint mode - if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) { + obj2 = obj1.dictLookup("op"); + if ((haveFillOP = obj2.isBool())) { state->setFillOverprint(obj2.getBool()); out->updateFillOverprint(state); } - obj2.free(); - if (obj1.dictLookup("OP", &obj2)->isBool()) { + obj2 = obj1.dictLookup("OP"); + if (obj2.isBool()) { state->setStrokeOverprint(obj2.getBool()); out->updateStrokeOverprint(state); if (!haveFillOP) { @@ -1128,24 +1093,23 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { out->updateFillOverprint(state); } } - obj2.free(); - if (obj1.dictLookup("OPM", &obj2)->isInt()) { + obj2 = obj1.dictLookup("OPM"); + if (obj2.isInt()) { state->setOverprintMode(obj2.getInt()); out->updateOverprintMode(state); } - obj2.free(); // stroke adjust - if (obj1.dictLookup("SA", &obj2)->isBool()) { + obj2 = obj1.dictLookup("SA"); + if (obj2.isBool()) { state->setStrokeAdjust(obj2.getBool()); out->updateStrokeAdjust(state); } - obj2.free(); // transfer function - if (obj1.dictLookup("TR2", &obj2)->isNull()) { - obj2.free(); - obj1.dictLookup("TR", &obj2); + obj2 = obj1.dictLookup("TR2"); + if (obj2.isNull()) { + obj2 = obj1.dictLookup("TR"); } if (obj2.isName("Default") || obj2.isName("Identity")) { @@ -1154,9 +1118,8 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { out->updateTransfer(state); } else if (obj2.isArray() && obj2.arrayGetLength() == 4) { for (i = 0; i < 4; ++i) { - obj2.arrayGet(i, &obj3); + Object obj3 = obj2.arrayGet(i); funcs[i] = Function::parse(&obj3); - obj3.free(); if (!funcs[i]) { break; } @@ -1174,80 +1137,81 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { } else if (!obj2.isNull()) { error(errSyntaxError, getPos(), "Invalid transfer function in ExtGState"); } - obj2.free(); // alpha is shape - if (obj1.dictLookup("AIS", &obj2)->isBool()) { + obj2 = obj1.dictLookup("AIS"); + if (obj2.isBool()) { state->setAlphaIsShape(obj2.getBool()); out->updateAlphaIsShape(state); } - obj2.free(); // text knockout - if (obj1.dictLookup("TK", &obj2)->isBool()) { + obj2 = obj1.dictLookup("TK"); + if (obj2.isBool()) { state->setTextKnockout(obj2.getBool()); out->updateTextKnockout(state); } - obj2.free(); // soft mask - if (!obj1.dictLookup("SMask", &obj2)->isNull()) { + obj2 = obj1.dictLookup("SMask"); + if (!obj2.isNull()) { if (obj2.isName("None")) { out->clearSoftMask(state); } else if (obj2.isDict()) { - if (obj2.dictLookup("S", &obj3)->isName("Alpha")) { + Object obj3 = obj2.dictLookup("S"); + if (obj3.isName("Alpha")) { alpha = gTrue; } else { // "Luminosity" alpha = gFalse; } - obj3.free(); funcs[0] = NULL; - if (!obj2.dictLookup("TR", &obj3)->isNull()) { + obj3 = obj2.dictLookup("TR"); + if (!obj3.isNull()) { if (obj3.isName("Default") || obj3.isName("Identity")) { funcs[0] = NULL; } else { funcs[0] = Function::parse(&obj3); - if (funcs[0] == NULL || - funcs[0]->getInputSize() != 1 || - funcs[0]->getOutputSize() != 1) { - error(errSyntaxError, getPos(), + if (funcs[0] == NULL || + funcs[0]->getInputSize() != 1 || + funcs[0]->getOutputSize() != 1) { + error(errSyntaxError, getPos(), "Invalid transfer function in soft mask in ExtGState"); - delete funcs[0]; - funcs[0] = NULL; + delete funcs[0]; + funcs[0] = NULL; } } } - obj3.free(); - if ((haveBackdropColor = obj2.dictLookup("BC", &obj3)->isArray())) { + obj3 = obj2.dictLookup("BC"); + if ((haveBackdropColor = obj3.isArray())) { for (i = 0; i < gfxColorMaxComps; ++i) { backdropColor.c[i] = 0; } for (i = 0; i < obj3.arrayGetLength() && i < gfxColorMaxComps; ++i) { - obj3.arrayGet(i, &obj4); + Object obj4 = obj3.arrayGet(i); if (obj4.isNum()) { backdropColor.c[i] = dblToCol(obj4.getNum()); } - obj4.free(); } } - obj3.free(); - if (obj2.dictLookup("G", &obj3)->isStream()) { - if (obj3.streamGetDict()->lookup("Group", &obj4)->isDict()) { + obj3 = obj2.dictLookup("G"); + if (obj3.isStream()) { + Object obj4 = obj3.streamGetDict()->lookup("Group"); + if (obj4.isDict()) { blendingColorSpace = NULL; isolated = knockout = gFalse; - if (!obj4.dictLookup("CS", &obj5)->isNull()) { + Object obj5 = obj4.dictLookup("CS"); + if (!obj5.isNull()) { blendingColorSpace = GfxColorSpace::parse(res, &obj5, out, state); } - obj5.free(); - if (obj4.dictLookup("I", &obj5)->isBool()) { + obj5 = obj4.dictLookup("I"); + if (obj5.isBool()) { isolated = obj5.getBool(); } - obj5.free(); - if (obj4.dictLookup("K", &obj5)->isBool()) { + obj5 = obj4.dictLookup("K"); + if (obj5.isBool()) { knockout = obj5.getBool(); } - obj5.free(); if (!haveBackdropColor) { if (blendingColorSpace) { blendingColorSpace->getDefaultColor(&backdropColor); @@ -1266,85 +1230,70 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { } else { error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState - missing group"); } - obj4.free(); } else { error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState - missing group"); } - obj3.free(); } else if (!obj2.isNull()) { error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState"); } } - obj2.free(); - if (obj1.dictLookup("Font", &obj2)->isArray()) { + obj2 = obj1.dictLookup("Font"); + if (obj2.isArray()) { GfxFont *font; if (obj2.arrayGetLength() == 2) { - Object fargs0, fargs1; - - obj2.arrayGetNF(0,&fargs0); - obj2.arrayGet(1,&fargs1); + Object fargs0 = obj2.arrayGetNF(0); + Object fargs1 = obj2.arrayGet(1); if (fargs0.isRef() && fargs1.isNum()) { - Object fobj; - Ref r; - - fargs0.fetch(xref, &fobj); + Object fobj = fargs0.fetch(xref); if (fobj.isDict()) { - r = fargs0.getRef(); + Ref r = fargs0.getRef(); font = GfxFont::makeFont(xref,args[0].getName(),r,fobj.getDict()); state->setFont(font,fargs1.getNum()); fontChanged = gTrue; } - fobj.free(); } - fargs0.free(); - fargs1.free(); } else { error(errSyntaxError, getPos(), "Number of args mismatch for /Font in ExtGState"); } } - obj2.free(); - if (obj1.dictLookup("LW", &obj2)->isNum()) { + obj2 = obj1.dictLookup("LW"); + if (obj2.isNum()) { opSetLineWidth(&obj2,1); } - obj2.free(); - if (obj1.dictLookup("LC", &obj2)->isInt()) { + obj2 = obj1.dictLookup("LC"); + if (obj2.isInt()) { opSetLineCap(&obj2,1); } - obj2.free(); - if (obj1.dictLookup("LJ", &obj2)->isInt()) { + obj2 = obj1.dictLookup("LJ"); + if (obj2.isInt()) { opSetLineJoin(&obj2,1); } - obj2.free(); - if (obj1.dictLookup("ML", &obj2)->isNum()) { + obj2 = obj1.dictLookup("ML"); + if (obj2.isNum()) { opSetMiterLimit(&obj2,1); } - obj2.free(); - if (obj1.dictLookup("D", &obj2)->isArray()) { + obj2 = obj1.dictLookup("D"); + if (obj2.isArray()) { if (obj2.arrayGetLength() == 2) { Object dargs[2]; - obj2.arrayGetNF(0,&dargs[0]); - obj2.arrayGet(1,&dargs[1]); + dargs[0] = obj2.arrayGetNF(0); + dargs[1] = obj2.arrayGet(1); if (dargs[0].isArray() && dargs[1].isInt()) { opSetDash(dargs,2); } - dargs[0].free(); - dargs[1].free(); } else { error(errSyntaxError, getPos(), "Number of args mismatch for /D in ExtGState"); } } - obj2.free(); - if (obj1.dictLookup("RI", &obj2)->isName()) { + obj2 = obj1.dictLookup("RI"); + if (obj2.isName()) { opSetRenderingIntent(&obj2,1); } - obj2.free(); - if (obj1.dictLookup("FL", &obj2)->isNum()) { + obj2 = obj1.dictLookup("FL"); + if (obj2.isNum()) { opSetFlat(&obj2,1); } - obj2.free(); - - obj1.free(); } void Gfx::doSoftMask(Object *str, GBool alpha, @@ -1353,7 +1302,7 @@ void Gfx::doSoftMask(Object *str, GBool alpha, Function *transferFunc, GfxColor *backdropColor) { Dict *dict, *resDict; double m[6], bbox[4]; - Object obj1, obj2; + Object obj1; int i; // check for excessive recursion @@ -1365,50 +1314,42 @@ void Gfx::doSoftMask(Object *str, GBool alpha, dict = str->streamGetDict(); // check form type - dict->lookup("FormType", &obj1); + obj1 = dict->lookup("FormType"); if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { error(errSyntaxError, getPos(), "Unknown form type"); } - obj1.free(); // get bounding box - dict->lookup("BBox", &obj1); + obj1 = dict->lookup("BBox"); if (!obj1.isArray()) { - obj1.free(); error(errSyntaxError, getPos(), "Bad form bounding box"); return; } for (i = 0; i < 4; ++i) { - obj1.arrayGet(i, &obj2); + Object obj2 = obj1.arrayGet(i); if (likely(obj2.isNum())) bbox[i] = obj2.getNum(); else { - obj2.free(); - obj1.free(); error(errSyntaxError, getPos(), "Bad form bounding box (non number)"); return; } - obj2.free(); } - obj1.free(); // get matrix - dict->lookup("Matrix", &obj1); + obj1 = dict->lookup("Matrix"); if (obj1.isArray()) { for (i = 0; i < 6; ++i) { - obj1.arrayGet(i, &obj2); + Object obj2 = obj1.arrayGet(i); if (likely(obj2.isNum())) m[i] = obj2.getNum(); else m[i] = 0; - obj2.free(); } } else { m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; } - obj1.free(); // get resources - dict->lookup("Resources", &obj1); + obj1 = dict->lookup("Resources"); resDict = obj1.isDict() ? obj1.getDict() : (Dict *)NULL; // draw it @@ -1421,7 +1362,6 @@ void Gfx::doSoftMask(Object *str, GBool alpha, if (blendingColorSpace) { delete blendingColorSpace; } - obj1.free(); } void Gfx::opSetRenderingIntent(Object args[], int numArgs) { @@ -1435,17 +1375,15 @@ void Gfx::opSetRenderingIntent(Object args[], int numArgs) { void Gfx::opSetFillGray(Object args[], int numArgs) { GfxColor color; GfxColorSpace *colorSpace = NULL; - Object obj; state->setFillPattern(NULL); - res->lookupColorSpace("DefaultGray", &obj); + Object obj = res->lookupColorSpace("DefaultGray"); if (!obj.isNull()) { colorSpace = GfxColorSpace::parse(res, &obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceGrayColorSpace(); } - obj.free(); state->setFillColorSpace(colorSpace); out->updateFillColorSpace(state); color.c[0] = dblToCol(args[0].getNum()); @@ -1456,17 +1394,15 @@ void Gfx::opSetFillGray(Object args[], int numArgs) { void Gfx::opSetStrokeGray(Object args[], int numArgs) { GfxColor color; GfxColorSpace *colorSpace = NULL; - Object obj; state->setStrokePattern(NULL); - res->lookupColorSpace("DefaultGray", &obj); + Object obj = res->lookupColorSpace("DefaultGray"); if (!obj.isNull()) { colorSpace = GfxColorSpace::parse(res, &obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceGrayColorSpace(); } - obj.free(); state->setStrokeColorSpace(colorSpace); out->updateStrokeColorSpace(state); color.c[0] = dblToCol(args[0].getNum()); @@ -1477,17 +1413,15 @@ void Gfx::opSetStrokeGray(Object args[], int numArgs) { void Gfx::opSetFillCMYKColor(Object args[], int numArgs) { GfxColor color; GfxColorSpace *colorSpace = NULL; - Object obj; int i; - res->lookupColorSpace("DefaultCMYK", &obj); + Object obj = res->lookupColorSpace("DefaultCMYK"); if (!obj.isNull()) { colorSpace = GfxColorSpace::parse(res, &obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceCMYKColorSpace(); } - obj.free(); state->setFillPattern(NULL); state->setFillColorSpace(colorSpace); out->updateFillColorSpace(state); @@ -1501,18 +1435,16 @@ void Gfx::opSetFillCMYKColor(Object args[], int numArgs) { void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) { GfxColor color; GfxColorSpace *colorSpace = NULL; - Object obj; int i; state->setStrokePattern(NULL); - res->lookupColorSpace("DefaultCMYK", &obj); + Object obj = res->lookupColorSpace("DefaultCMYK"); if (!obj.isNull()) { colorSpace = GfxColorSpace::parse(res, &obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceCMYKColorSpace(); } - obj.free(); state->setStrokeColorSpace(colorSpace); out->updateStrokeColorSpace(state); for (i = 0; i < 4; ++i) { @@ -1523,20 +1455,18 @@ void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) { } void Gfx::opSetFillRGBColor(Object args[], int numArgs) { - Object obj; GfxColorSpace *colorSpace = NULL; GfxColor color; int i; state->setFillPattern(NULL); - res->lookupColorSpace("DefaultRGB", &obj); + Object obj = res->lookupColorSpace("DefaultRGB"); if (!obj.isNull()) { colorSpace = GfxColorSpace::parse(res, &obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceRGBColorSpace(); } - obj.free(); state->setFillColorSpace(colorSpace); out->updateFillColorSpace(state); for (i = 0; i < 3; ++i) { @@ -1547,20 +1477,18 @@ void Gfx::opSetFillRGBColor(Object args[], int numArgs) { } void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) { - Object obj; GfxColorSpace *colorSpace = NULL; GfxColor color; int i; state->setStrokePattern(NULL); - res->lookupColorSpace("DefaultRGB", &obj); + Object obj = res->lookupColorSpace("DefaultRGB"); if (!obj.isNull()) { colorSpace = GfxColorSpace::parse(res, &obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceRGBColorSpace(); } - obj.free(); state->setStrokeColorSpace(colorSpace); out->updateStrokeColorSpace(state); for (i = 0; i < 3; ++i) { @@ -1571,17 +1499,15 @@ void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) { } void Gfx::opSetFillColorSpace(Object args[], int numArgs) { - Object obj; GfxColorSpace *colorSpace; GfxColor color; - res->lookupColorSpace(args[0].getName(), &obj); + Object obj = res->lookupColorSpace(args[0].getName()); if (obj.isNull()) { colorSpace = GfxColorSpace::parse(res, &args[0], out, state); } else { colorSpace = GfxColorSpace::parse(res, &obj, out, state); } - obj.free(); if (colorSpace) { state->setFillPattern(NULL); state->setFillColorSpace(colorSpace); @@ -1595,18 +1521,16 @@ void Gfx::opSetFillColorSpace(Object args[], int numArgs) { } void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { - Object obj; GfxColorSpace *colorSpace; GfxColor color; state->setStrokePattern(NULL); - res->lookupColorSpace(args[0].getName(), &obj); + Object obj = res->lookupColorSpace(args[0].getName()); if (obj.isNull()) { colorSpace = GfxColorSpace::parse(res, &args[0], out, state); } else { colorSpace = GfxColorSpace::parse(res, &obj, out, state); } - obj.free(); if (colorSpace) { state->setStrokeColorSpace(colorSpace); out->updateStrokeColorSpace(state); @@ -2293,18 +2217,34 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, xi0, yi0, xi1, yi1, xstep, ystep)) { goto restore; } else { - out->updatePatternOpacity(state); - for (yi = yi0; yi < yi1; ++yi) { - for (xi = xi0; xi < xi1; ++xi) { - x = xi * xstep; - y = yi * ystep; - m1[4] = x * m[0] + y * m[2] + m[4]; - m1[5] = x * m[1] + y * m[3] + m[5]; - drawForm(tPat->getContentStream(), tPat->getResDict(), - m1, tPat->getBBox()); + bool shouldDrawForm = gTrue; + std::set<int>::iterator patternRefIt; + const int patternRefNum = tPat->getPatternRefNum(); + if (patternRefNum != -1) { + if (formsDrawing.find(patternRefNum) == formsDrawing.end()) { + patternRefIt = formsDrawing.insert(patternRefNum).first; + } else { + shouldDrawForm = gFalse; + } + } + + if (shouldDrawForm) { + out->updatePatternOpacity(state); + for (yi = yi0; yi < yi1; ++yi) { + for (xi = xi0; xi < xi1; ++xi) { + x = xi * xstep; + y = yi * ystep; + m1[4] = x * m[0] + y * m[2] + m[4]; + m1[5] = x * m[1] + y * m[3] + m[5]; + drawForm(tPat->getContentStream(), tPat->getResDict(), + m1, tPat->getBBox()); + } + } + out->clearPatternOpacity(state); + if (patternRefNum != -1) { + formsDrawing.erase(patternRefIt); } } - out->clearPatternOpacity(state); } // restore graphics state @@ -3881,7 +3821,6 @@ void Gfx::opMoveSetShowText(Object args[], int numArgs) { void Gfx::opShowSpaceText(Object args[], int numArgs) { Array *a; - Object obj; int wMode; int i; @@ -3897,7 +3836,7 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) { wMode = state->getFont()->getWMode(); a = args[0].getArray(); for (i = 0; i < a->getLength(); ++i) { - a->get(i, &obj); + Object obj = a->get(i); if (obj.isNum()) { // this uses the absolute value of the font size to match // Acrobat's behavior @@ -3916,17 +3855,15 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) { error(errSyntaxError, getPos(), "Element of show/space array must be number or string"); } - obj.free(); } out->endStringOp(state); if (!ocState) { a = args[0].getArray(); for (i = 0; i < a->getLength(); ++i) { - a->get(i, &obj); + Object obj = a->get(i); if (obj.isString()) { doIncCharCount(obj.getString()); } - obj.free(); } } } @@ -3942,7 +3879,6 @@ void Gfx::doShowText(GooString *s) { double x0, y0, x1, y1; double oldCTM[6], newCTM[6]; double *mat; - Object charProc; Dict *resDict; Parser *oldParser; GfxState *savedState; @@ -4026,12 +3962,33 @@ void Gfx::doShowText(GooString *s) { state->transformDelta(dx, dy, &ddx, &ddy); if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy, code, u, uLen)) { - ((Gfx8BitFont *)font)->getCharProc(code, &charProc); + Object charProc = ((Gfx8BitFont *)font)->getCharProcNF(code); + int refNum = -1; + if (charProc.isRef()) { + refNum = charProc.getRef().num; + charProc = charProc.fetch(((Gfx8BitFont *)font)->getCharProcs()->getXRef()); + } if ((resDict = ((Gfx8BitFont *)font)->getResources())) { pushResources(resDict); } if (charProc.isStream()) { - display(&charProc, gFalse); + std::set<int>::iterator charProcDrawingIt; + bool displayCharProc = true; + if (refNum != -1) { + if (charProcDrawing.find(refNum) == charProcDrawing.end()) { + charProcDrawingIt = charProcDrawing.insert(refNum).first; + } else { + displayCharProc = false; + error(errSyntaxError, -1, "CharProc wants to draw a CharProc that is already beign drawn"); + } + } + if (displayCharProc) { + display(&charProc, gFalse); + + if (refNum != -1) { + charProcDrawing.erase(charProcDrawingIt); + } + } } else { error(errSyntaxError, getPos(), "Missing or bad Type3 CharProc entry"); } @@ -4039,7 +3996,6 @@ void Gfx::doShowText(GooString *s) { if (resDict) { popResources(); } - charProc.free(); } restoreStateStack(savedState); // GfxState::restore() does *not* restore the current position, @@ -4177,39 +4133,34 @@ void Gfx::doIncCharCount(GooString *s) { void Gfx::opXObject(Object args[], int numArgs) { char *name; - Object obj1, obj2, obj3, refObj; -#if OPI_SUPPORT - Object opiDict; -#endif if (!ocState && !out->needCharCount()) { return; } name = args[0].getName(); - if (!res->lookupXObject(name, &obj1)) { + Object obj1 = res->lookupXObject(name); + if (obj1.isNull()) { return; } if (!obj1.isStream()) { error(errSyntaxError, getPos(), "XObject '{0:s}' is wrong type", name); - obj1.free(); return; } -#if OPI_SUPPORT - obj1.streamGetDict()->lookup("OPI", &opiDict); +#ifdef OPI_SUPPORT + Object opiDict = obj1.streamGetDict()->lookup("OPI"); if (opiDict.isDict()) { out->opiBegin(state, opiDict.getDict()); } #endif - obj1.streamGetDict()->lookup("Subtype", &obj2); + Object obj2 = obj1.streamGetDict()->lookup("Subtype"); if (obj2.isName("Image")) { if (out->needNonText()) { - res->lookupXObjectNF(name, &refObj); + Object refObj = res->lookupXObjectNF(name); doImage(&refObj, obj1.getStream(), gFalse); - refObj.free(); } } else if (obj2.isName("Form")) { - res->lookupXObjectNF(name, &refObj); + Object refObj = res->lookupXObjectNF(name); GBool shouldDoForm = gTrue; std::set<int>::iterator drawingFormIt; if (refObj.isRef()) { @@ -4230,9 +4181,8 @@ void Gfx::opXObject(Object args[], int numArgs) { if (refObj.isRef() && shouldDoForm) { formsDrawing.erase(drawingFormIt); } - refObj.free(); } else if (obj2.isName("PS")) { - obj1.streamGetDict()->lookup("Level1", &obj3); + Object obj3 = obj1.streamGetDict()->lookup("Level1"); out->psXObject(obj1.getStream(), obj3.isStream() ? obj3.getStream() : (Stream *)NULL); } else if (obj2.isName()) { @@ -4240,14 +4190,11 @@ void Gfx::opXObject(Object args[], int numArgs) { } else { error(errSyntaxError, getPos(), "XObject subtype is missing or wrong type"); } - obj2.free(); -#if OPI_SUPPORT +#ifdef OPI_SUPPORT if (opiDict.isDict()) { out->opiEnd(state, opiDict.getDict()); } - opiDict.free(); #endif - obj1.free(); } void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { @@ -4259,15 +4206,13 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { GBool mask; GBool invert; GfxColorSpace *colorSpace, *maskColorSpace; - GfxImageColorMap *colorMap, *maskColorMap; - Object maskObj, smaskObj; GBool haveColorKeyMask, haveExplicitMask, haveSoftMask; int maskColors[2*gfxColorMaxComps]; int maskWidth, maskHeight; GBool maskInvert; GBool maskInterpolate; Stream *maskStr; - Object obj1, obj2; + Object obj1; int i, n; // get info from the stream @@ -4280,84 +4225,72 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { // check for optional content key if (ref) { - dict->lookupNF("OC", &obj1); + obj1 = dict->lookupNF("OC"); if (catalog->getOptContentConfig() && !catalog->getOptContentConfig()->optContentIsVisible(&obj1)) { - obj1.free(); return; } - obj1.free(); } // get size - dict->lookup("Width", &obj1); + obj1 = dict->lookup("Width"); if (obj1.isNull()) { - obj1.free(); - dict->lookup("W", &obj1); + obj1 = dict->lookup("W"); } if (obj1.isInt()) width = obj1.getInt(); else if (obj1.isReal()) width = (int)obj1.getReal(); else - goto err2; - obj1.free(); - dict->lookup("Height", &obj1); + goto err1; + obj1 = dict->lookup("Height"); if (obj1.isNull()) { - obj1.free(); - dict->lookup("H", &obj1); + obj1 = dict->lookup("H"); } if (obj1.isInt()) height = obj1.getInt(); else if (obj1.isReal()) height = (int)obj1.getReal(); else - goto err2; - obj1.free(); + goto err1; if (width < 1 || height < 1) goto err1; // image interpolation - dict->lookup("Interpolate", &obj1); + obj1 = dict->lookup("Interpolate"); if (obj1.isNull()) { - obj1.free(); - dict->lookup("I", &obj1); + obj1 = dict->lookup("I"); } if (obj1.isBool()) interpolate = obj1.getBool(); else interpolate = gFalse; - obj1.free(); maskInterpolate = gFalse; // image or mask? - dict->lookup("ImageMask", &obj1); + obj1 = dict->lookup("ImageMask"); if (obj1.isNull()) { - obj1.free(); - dict->lookup("IM", &obj1); + obj1 = dict->lookup("IM"); } mask = gFalse; if (obj1.isBool()) mask = obj1.getBool(); else if (!obj1.isNull()) - goto err2; - obj1.free(); + goto err1; // bit depth if (bits == 0) { - dict->lookup("BitsPerComponent", &obj1); + obj1 = dict->lookup("BitsPerComponent"); if (obj1.isNull()) { - obj1.free(); - dict->lookup("BPC", &obj1); + obj1 = dict->lookup("BPC"); } if (obj1.isInt()) { bits = obj1.getInt(); } else if (mask) { bits = 1; } else { - goto err2; + goto err1; } - obj1.free(); } // display a mask @@ -4367,22 +4300,20 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { if (bits != 1) goto err1; invert = gFalse; - dict->lookup("Decode", &obj1); + obj1 = dict->lookup("Decode"); if (obj1.isNull()) { - obj1.free(); - dict->lookup("D", &obj1); + obj1 = dict->lookup("D"); } if (obj1.isArray()) { - obj1.arrayGet(0, &obj2); + Object obj2; + obj2 = obj1.arrayGet(0); // Table 4.39 says /Decode must be [1 0] or [0 1]. Adobe // accepts [1.0 0.0] as well. if (obj2.isNum() && obj2.getNum() >= 0.9) invert = gTrue; - obj2.free(); } else if (!obj1.isNull()) { - goto err2; + goto err1; } - obj1.free(); // if drawing is disabled, skip over inline image data if (!ocState || !out->needNonText()) { @@ -4402,26 +4333,24 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } } } else { + if (bits == 0) { + goto err1; + } // get color space and color map - dict->lookup("ColorSpace", &obj1); + obj1 = dict->lookup("ColorSpace"); if (obj1.isNull()) { - obj1.free(); - dict->lookup("CS", &obj1); + obj1 = dict->lookup("CS"); } if (obj1.isName() && inlineImg) { - res->lookupColorSpace(obj1.getName(), &obj2); + Object obj2 = res->lookupColorSpace(obj1.getName()); if (!obj2.isNull()) { - obj1.free(); - obj1 = obj2; - } else { - obj2.free(); + obj1 = std::move(obj2); } } if (!obj1.isNull()) { - Object objIntent; char *tempIntent = NULL; - dict->lookup("Intent", &objIntent); + Object objIntent = dict->lookup("Intent"); if (objIntent.isName()) { tempIntent = state->getRenderingIntent(); if (tempIntent != NULL) { @@ -4434,54 +4363,39 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { state->setRenderingIntent(tempIntent); free(tempIntent); } - objIntent.free(); } else if (csMode == streamCSDeviceGray) { - Object objCS; - res->lookupColorSpace("DefaultGray", &objCS); + Object objCS = res->lookupColorSpace("DefaultGray"); if (objCS.isNull()) { colorSpace = new GfxDeviceGrayColorSpace(); } else { colorSpace = GfxColorSpace::parse(res, &objCS, out, state); } - objCS.free(); } else if (csMode == streamCSDeviceRGB) { - Object objCS; - res->lookupColorSpace("DefaultRGB", &objCS); + Object objCS = res->lookupColorSpace("DefaultRGB"); if (objCS.isNull()) { colorSpace = new GfxDeviceRGBColorSpace(); } else { colorSpace = GfxColorSpace::parse(res, &objCS, out, state); } - objCS.free(); } else if (csMode == streamCSDeviceCMYK) { - Object objCS; - res->lookupColorSpace("DefaultCMYK", &objCS); + Object objCS = res->lookupColorSpace("DefaultCMYK"); if (objCS.isNull()) { colorSpace = new GfxDeviceCMYKColorSpace(); } else { colorSpace = GfxColorSpace::parse(res, &objCS, out, state); } - objCS.free(); } else { colorSpace = NULL; } - obj1.free(); if (!colorSpace) { goto err1; } - dict->lookup("Decode", &obj1); + obj1 = dict->lookup("Decode"); if (obj1.isNull()) { - obj1.free(); - dict->lookup("D", &obj1); + obj1 = dict->lookup("D"); } - if (bits == 0) { - delete colorSpace; - goto err2; - } - colorMap = new GfxImageColorMap(bits, &obj1, colorSpace); - obj1.free(); - if (!colorMap->isOk()) { - delete colorMap; + GfxImageColorMap colorMap(bits, &obj1, colorSpace); + if (!colorMap.isOk()) { goto err1; } @@ -4490,9 +4404,9 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskStr = NULL; // make gcc happy maskWidth = maskHeight = 0; // make gcc happy maskInvert = gFalse; // make gcc happy - maskColorMap = NULL; // make gcc happy - dict->lookup("Mask", &maskObj); - dict->lookup("SMask", &smaskObj); + std::unique_ptr<GfxImageColorMap> maskColorMap; + Object maskObj = dict->lookup("Mask"); + Object smaskObj = dict->lookup("SMask"); if (smaskObj.isStream()) { // soft mask if (inlineImg) { @@ -4500,78 +4414,62 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } maskStr = smaskObj.getStream(); maskDict = smaskObj.streamGetDict(); - maskDict->lookup("Width", &obj1); + obj1 = maskDict->lookup("Width"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("W", &obj1); + obj1 = maskDict->lookup("W"); } if (!obj1.isInt()) { - goto err2; + goto err1; } maskWidth = obj1.getInt(); - obj1.free(); - maskDict->lookup("Height", &obj1); + obj1 = maskDict->lookup("Height"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("H", &obj1); + obj1 = maskDict->lookup("H"); } if (!obj1.isInt()) { - goto err2; + goto err1; } maskHeight = obj1.getInt(); - obj1.free(); - maskDict->lookup("Interpolate", &obj1); + obj1 = maskDict->lookup("Interpolate"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("I", &obj1); + obj1 = maskDict->lookup("I"); } if (obj1.isBool()) maskInterpolate = obj1.getBool(); else maskInterpolate = gFalse; - obj1.free(); - maskDict->lookup("BitsPerComponent", &obj1); + obj1 = maskDict->lookup("BitsPerComponent"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("BPC", &obj1); + obj1 = maskDict->lookup("BPC"); } if (!obj1.isInt()) { - goto err2; + goto err1; } maskBits = obj1.getInt(); - obj1.free(); - maskDict->lookup("ColorSpace", &obj1); + obj1 = maskDict->lookup("ColorSpace"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("CS", &obj1); + obj1 = maskDict->lookup("CS"); } if (obj1.isName()) { - res->lookupColorSpace(obj1.getName(), &obj2); + Object obj2 = res->lookupColorSpace(obj1.getName()); if (!obj2.isNull()) { - obj1.free(); - obj1 = obj2; - } else { - obj2.free(); + obj1 = std::move(obj2); } } maskColorSpace = GfxColorSpace::parse(NULL, &obj1, out, state); - obj1.free(); if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { goto err1; } - maskDict->lookup("Decode", &obj1); + obj1 = maskDict->lookup("Decode"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("D", &obj1); + obj1 = maskDict->lookup("D"); } - maskColorMap = new GfxImageColorMap(maskBits, &obj1, maskColorSpace); - obj1.free(); + maskColorMap.reset(new GfxImageColorMap(maskBits, &obj1, maskColorSpace)); if (!maskColorMap->isOk()) { - delete maskColorMap; goto err1; } // handle the Matte entry - maskDict->lookup("Matte", &obj1); + obj1 = maskDict->lookup("Matte"); if (obj1.isArray()) { if (obj1.getArray()->getLength() != colorSpace->getNComps()) { error(errSyntaxError, -1, "Matte entry should have {0:d} components but has {1:d}", @@ -4582,29 +4480,26 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } else { GfxColor matteColor; for (i = 0; i < colorSpace->getNComps(); i++) { - obj1.getArray()->get(i, &obj2); + Object obj2 = obj1.getArray()->get(i); if (!obj2.isNum()) { - obj2.free(); error(errSyntaxError, -1, "Matte entry {0:d} should be a number but it's of type {1:d}", i, obj2.getType()); break; } matteColor.c[i] = dblToCol(obj2.getNum()); - obj2.free(); } if (i == colorSpace->getNComps()) { maskColorMap->setMatteColor(&matteColor); } } } - obj1.free(); haveSoftMask = gTrue; } else if (maskObj.isArray()) { // color key mask for (i = 0; i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps; ++i) { - maskObj.arrayGet(i, &obj1); + obj1 = maskObj.arrayGet(i); if (obj1.isInt()) { maskColors[i] = obj1.getInt(); } else if (obj1.isReal()) { @@ -4612,10 +4507,8 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskColors[i] = (int) obj1.getReal(); } else { error(errSyntaxError, -1, "Mask entry should be an integer but it's of type {0:d}", obj1.getType()); - obj1.free(); goto err1; } - obj1.free(); } haveColorKeyMask = gTrue; } else if (maskObj.isStream()) { @@ -4625,71 +4518,60 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } maskStr = maskObj.getStream(); maskDict = maskObj.streamGetDict(); - maskDict->lookup("Width", &obj1); + obj1 = maskDict->lookup("Width"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("W", &obj1); + obj1 = maskDict->lookup("W"); } if (!obj1.isInt()) { - goto err2; + goto err1; } maskWidth = obj1.getInt(); - obj1.free(); - maskDict->lookup("Height", &obj1); + obj1 = maskDict->lookup("Height"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("H", &obj1); + obj1 = maskDict->lookup("H"); } if (!obj1.isInt()) { - goto err2; + goto err1; } maskHeight = obj1.getInt(); - obj1.free(); - maskDict->lookup("Interpolate", &obj1); + obj1 = maskDict->lookup("Interpolate"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("I", &obj1); + obj1 = maskDict->lookup("I"); } if (obj1.isBool()) maskInterpolate = obj1.getBool(); else maskInterpolate = gFalse; - obj1.free(); - maskDict->lookup("ImageMask", &obj1); + obj1 = maskDict->lookup("ImageMask"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("IM", &obj1); + obj1 = maskDict->lookup("IM"); } if (!obj1.isBool() || !obj1.getBool()) { - goto err2; + goto err1; } - obj1.free(); maskInvert = gFalse; - maskDict->lookup("Decode", &obj1); + obj1 = maskDict->lookup("Decode"); if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("D", &obj1); + obj1 = maskDict->lookup("D"); } if (obj1.isArray()) { - obj1.arrayGet(0, &obj2); + Object obj2 = obj1.arrayGet(0); // Table 4.39 says /Decode must be [1 0] or [0 1]. Adobe // accepts [1.0 0.0] as well. if (obj2.isNum() && obj2.getNum() >= 0.9) { maskInvert = gTrue; } - obj2.free(); } else if (!obj1.isNull()) { - goto err2; + goto err1; } - obj1.free(); haveExplicitMask = gTrue; } // if drawing is disabled, skip over inline image data if (!ocState || !out->needNonText()) { str->reset(); - n = height * ((width * colorMap->getNumPixelComps() * - colorMap->getBits() + 7) / 8); + n = height * ((width * colorMap.getNumPixelComps() * + colorMap.getBits() + 7) / 8); for (i = 0; i < n; ++i) { str->getChar(); } @@ -4698,21 +4580,16 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { // draw it } else { if (haveSoftMask) { - out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, interpolate, - maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate); - delete maskColorMap; + out->drawSoftMaskedImage(state, ref, str, width, height, &colorMap, interpolate, + maskStr, maskWidth, maskHeight, maskColorMap.get(), maskInterpolate); } else if (haveExplicitMask) { - out->drawMaskedImage(state, ref, str, width, height, colorMap, interpolate, + out->drawMaskedImage(state, ref, str, width, height, &colorMap, interpolate, maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate); } else { - out->drawImage(state, ref, str, width, height, colorMap, interpolate, + out->drawImage(state, ref, str, width, height, &colorMap, interpolate, haveColorKeyMask ? maskColors : (int *)NULL, inlineImg); } } - delete colorMap; - - maskObj.free(); - smaskObj.free(); } if ((i = width * height) > 1000) { @@ -4722,8 +4599,6 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { return; - err2: - obj1.free(); err1: error(errSyntaxError, getPos(), "Bad image parameters"); } @@ -4731,22 +4606,22 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { GBool Gfx::checkTransparencyGroup(Dict *resDict) { // check the effect of compositing objects as a group: // look for ExtGState entries with ca != 1 or CA != 1 or BM != normal - Object extGStates; GBool transpGroup = gFalse; double opac; if (resDict == NULL) return gFalse; pushResources(resDict); - resDict->lookup("ExtGState", &extGStates); + Object extGStates = resDict->lookup("ExtGState"); if (extGStates.isDict()) { Dict *dict = extGStates.getDict(); for (int i = 0; i < dict->getLength() && !transpGroup; i++) { - Object obj1, obj2; GfxBlendMode mode; - if (res->lookupGState(dict->getKey(i), &obj1) && obj1.isDict()) { - if (!obj1.dictLookup("BM", &obj2)->isNull()) { + Object obj1 = res->lookupGState(dict->getKey(i)); + if (obj1.isDict()) { + Object obj2 = obj1.dictLookup("BM"); + if (!obj2.isNull()) { if (state->parseBlendMode(&obj2, &mode)) { if (mode != gfxBlendNormal) transpGroup = gTrue; @@ -4754,38 +4629,35 @@ GBool Gfx::checkTransparencyGroup(Dict *resDict) { error(errSyntaxError, getPos(), "Invalid blend mode in ExtGState"); } } - obj2.free(); - if (obj1.dictLookup("ca", &obj2)->isNum()) { + obj2 = obj1.dictLookup("ca"); + if (obj2.isNum()) { opac = obj2.getNum(); opac = opac < 0 ? 0 : opac > 1 ? 1 : opac; if (opac != 1) transpGroup = gTrue; } - obj2.free(); - if (obj1.dictLookup("CA", &obj2)->isNum()) { + obj2 = obj1.dictLookup("CA"); + if (obj2.isNum()) { opac = obj2.getNum(); opac = opac < 0 ? 0 : opac > 1 ? 1 : opac; if (opac != 1) transpGroup = gTrue; } - obj2.free(); // alpha is shape - if (!transpGroup && obj1.dictLookup("AIS", &obj2)->isBool()) { + obj2 = obj1.dictLookup("AIS"); + if (!transpGroup && obj2.isBool()) { transpGroup = obj2.getBool(); } - obj2.free(); // soft mask - if (!transpGroup && !obj1.dictLookup("SMask", &obj2)->isNull()) { + obj2 = obj1.dictLookup("SMask"); + if (!transpGroup && !obj2.isNull()) { if (!obj2.isName("None")) { transpGroup = gTrue; } } - obj2.free(); } - obj1.free(); } } - extGStates.free(); popResources(); return transpGroup; } @@ -4794,12 +4666,10 @@ void Gfx::doForm(Object *str) { Dict *dict; GBool transpGroup, isolated, knockout; GfxColorSpace *blendingColorSpace; - Object matrixObj, bboxObj; double m[6], bbox[4]; - Object resObj; Dict *resDict; GBool ocSaved; - Object obj1, obj2, obj3; + Object obj1; int i; // check for excessive recursion @@ -4811,88 +4681,79 @@ void Gfx::doForm(Object *str) { dict = str->streamGetDict(); // check form type - dict->lookup("FormType", &obj1); + obj1 = dict->lookup("FormType"); if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { error(errSyntaxError, getPos(), "Unknown form type"); } - obj1.free(); // check for optional content key ocSaved = ocState; - dict->lookupNF("OC", &obj1); + obj1 = dict->lookupNF("OC"); if (catalog->getOptContentConfig() && !catalog->getOptContentConfig()->optContentIsVisible(&obj1)) { - obj1.free(); if (out->needCharCount()) { ocState = gFalse; } else { return; } } - obj1.free(); // get bounding box - dict->lookup("BBox", &bboxObj); + Object bboxObj = dict->lookup("BBox"); if (!bboxObj.isArray()) { - bboxObj.free(); error(errSyntaxError, getPos(), "Bad form bounding box"); ocState = ocSaved; return; } for (i = 0; i < 4; ++i) { - bboxObj.arrayGet(i, &obj1); + obj1 = bboxObj.arrayGet(i); if (likely(obj1.isNum())) { bbox[i] = obj1.getNum(); - obj1.free(); } else { - obj1.free(); error(errSyntaxError, getPos(), "Bad form bounding box value"); return; } } - bboxObj.free(); // get matrix - dict->lookup("Matrix", &matrixObj); + Object matrixObj = dict->lookup("Matrix"); if (matrixObj.isArray()) { for (i = 0; i < 6; ++i) { - matrixObj.arrayGet(i, &obj1); + obj1 = matrixObj.arrayGet(i); if (likely(obj1.isNum())) m[i] = obj1.getNum(); else m[i] = 0; - obj1.free(); } } else { m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; } - matrixObj.free(); // get resources - dict->lookup("Resources", &resObj); + Object resObj = dict->lookup("Resources"); resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; // check for a transparency group transpGroup = isolated = knockout = gFalse; blendingColorSpace = NULL; - if (dict->lookup("Group", &obj1)->isDict()) { - if (obj1.dictLookup("S", &obj2)->isName("Transparency")) { - if (!obj1.dictLookup("CS", &obj3)->isNull()) { + obj1 = dict->lookup("Group"); + if (obj1.isDict()) { + Object obj2 = obj1.dictLookup("S"); + if (obj2.isName("Transparency")) { + Object obj3 = obj1.dictLookup("CS"); + if (!obj3.isNull()) { blendingColorSpace = GfxColorSpace::parse(res, &obj3, out, state); } - obj3.free(); - if (obj1.dictLookup("I", &obj3)->isBool()) { + obj3 = obj1.dictLookup("I"); + if (obj3.isBool()) { isolated = obj3.getBool(); } - obj3.free(); - if (obj1.dictLookup("K", &obj3)->isBool()) { + obj3 = obj1.dictLookup("K"); + if (obj3.isBool()) { knockout = obj3.getBool(); } - obj3.free(); transpGroup = isolated || out->checkTransparencyGroup(state, knockout) || checkTransparencyGroup(resDict); } - obj2.free(); } - obj1.free(); // draw it ++formDepth; @@ -4903,7 +4764,6 @@ void Gfx::doForm(Object *str) { if (blendingColorSpace) { delete blendingColorSpace; } - resObj.free(); ocState = ocSaved; } @@ -5044,45 +4904,37 @@ void Gfx::opBeginImage(Object args[], int numArgs) { } Stream *Gfx::buildImageStream() { - Object dict; - Object obj; char *key; Stream *str; // build dictionary - dict.initDict(xref); - parser->getObj(&obj); + Object dict(new Dict(xref)); + Object obj = parser->getObj(); while (!obj.isCmd("ID") && !obj.isEOF()) { if (!obj.isName()) { error(errSyntaxError, getPos(), "Inline image dictionary key must be a name object"); - obj.free(); } else { key = copyString(obj.getName()); - obj.free(); - parser->getObj(&obj); + obj = parser->getObj(); if (obj.isEOF() || obj.isError()) { gfree(key); break; } - dict.dictAdd(key, &obj); + dict.dictAdd(key, std::move(obj)); } - parser->getObj(&obj); + obj = parser->getObj(); } if (obj.isEOF()) { error(errSyntaxError, getPos(), "End of file in inline image"); - obj.free(); - dict.free(); return NULL; } - obj.free(); // make stream if (parser->getStream()) { - str = new EmbedStream(parser->getStream(), &dict, gFalse, 0); - str = str->addFilters(&dict); + str = new EmbedStream(parser->getStream(), std::move(dict), gFalse, 0, gTrue); + str = str->addFilters(str->getDict()); } else { str = NULL; - dict.free(); } return str; @@ -5175,27 +5027,25 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) { error(errSyntaxError, getPos(), "Unexpected MC Type: {0:d}", args[1].getType()); } char* name1 = args[1].getName(); - Object markedContent; MarkedContentStack *mc = mcStack; mc->kind = gfxMCOptionalContent; - if ( res->lookupMarkedContentNF( name1, &markedContent ) ) { + Object markedContent = res->lookupMarkedContentNF( name1 ); + if (!markedContent.isNull()) { bool visible = contentConfig->optContentIsVisible(&markedContent); mc->ocSuppressed = !(visible); } else { error(errSyntaxError, getPos(), "DID NOT find {0:s}", name1); } - markedContent.free(); } else { error(errSyntaxError, getPos(), "insufficient arguments for Marked Content"); } } else if (args[0].isName("Span") && numArgs == 2 && args[1].isDict()) { - Object obj; - if (args[1].dictLookup("ActualText", &obj)->isString()) { + Object obj = args[1].dictLookup("ActualText"); + if (obj.isString()) { out->beginActualText(state, obj.getString()); MarkedContentStack *mc = mcStack; mc->kind = gfxMCActualText; } - obj.free(); } if (printCommands) { @@ -5269,7 +5119,6 @@ struct GfxStackStateSaver { void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor, double xMin, double yMin, double xMax, double yMax, int rotate) { Dict *dict, *resDict; - Object matrixObj, bboxObj, resObj, obj1; double formXMin, formYMin, formXMax, formYMax; double x, y, sx, sy, tx, ty; double m[6], bbox[4]; @@ -5317,37 +5166,29 @@ void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor, dict = str->streamGetDict(); // get the form bounding box - dict->lookup("BBox", &bboxObj); + Object bboxObj = dict->lookup("BBox"); if (!bboxObj.isArray()) { - bboxObj.free(); error(errSyntaxError, getPos(), "Bad form bounding box"); return; } for (i = 0; i < 4; ++i) { - bboxObj.arrayGet(i, &obj1); + Object obj1 = bboxObj.arrayGet(i); if (likely(obj1.isNum())) { bbox[i] = obj1.getNum(); - obj1.free(); } else { - obj1.free(); - bboxObj.free(); error(errSyntaxError, getPos(), "Bad form bounding box value"); return; } } - bboxObj.free(); // get the form matrix - dict->lookup("Matrix", &matrixObj); + Object matrixObj = dict->lookup("Matrix"); if (matrixObj.isArray() && matrixObj.arrayGetLength() >= 6) { for (i = 0; i < 6; ++i) { - matrixObj.arrayGet(i, &obj1); + Object obj1 = matrixObj.arrayGet(i); if (likely(obj1.isNum())) { m[i] = obj1.getNum(); - obj1.free(); } else { - obj1.free(); - matrixObj.free(); error(errSyntaxError, getPos(), "Bad form matrix"); return; } @@ -5357,7 +5198,6 @@ void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor, m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; } - matrixObj.free(); // transform the four corners of the form bbox to default user // space, and construct the transformed bbox @@ -5430,13 +5270,11 @@ void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor, m[5] = m[5] * sy + ty; // get the resources - dict->lookup("Resources", &resObj); + Object resObj = dict->lookup("Resources"); resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; // draw it drawForm(str, resDict, m, bbox); - - resObj.free(); } // draw the border |