diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc index 827bbed..11bd780 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -4580,6 +4580,68 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { error(errSyntaxError, getPos(), "Bad image parameters"); } +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); + 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)) { + if (!obj1.dictLookup("BM", &obj2)->isNull()) { + if (state->parseBlendMode(&obj2, &mode)) { + if (mode != gfxBlendNormal) + transpGroup = gTrue; + } else { + error(errSyntaxError, getPos(), "Invalid blend mode in ExtGState"); + } + } + obj2.free(); + if (obj1.dictLookup("ca", &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()) { + 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()) { + transpGroup = obj2.getBool(); + } + obj2.free(); + // soft mask + if (!transpGroup && !obj1.dictLookup("SMask", &obj2)->isNull()) { + if (!obj2.isName("None")) { + transpGroup = gTrue; + } + } + obj2.free(); + } + obj1.free(); + } + } + extGStates.free(); + popResources(); + return transpGroup; +} + void Gfx::doForm(Object *str) { Dict *dict; GBool transpGroup, isolated, knockout; @@ -4666,7 +4728,6 @@ void Gfx::doForm(Object *str) { blendingColorSpace = NULL; if (dict->lookup("Group", &obj1)->isDict()) { if (obj1.dictLookup("S", &obj2)->isName("Transparency")) { - transpGroup = gTrue; if (!obj1.dictLookup("CS", &obj3)->isNull()) { blendingColorSpace = GfxColorSpace::parse(&obj3, this); } @@ -4679,6 +4740,7 @@ void Gfx::doForm(Object *str) { knockout = obj3.getBool(); } obj3.free(); + transpGroup = isolated || out->checkTransparencyGroup(state, knockout) || checkTransparencyGroup(resDict); } obj2.free(); } diff --git a/poppler/Gfx.h b/poppler/Gfx.h index 689d362..23253bb 100644 --- a/poppler/Gfx.h +++ b/poppler/Gfx.h @@ -181,6 +181,8 @@ public: // Get the current graphics state object. GfxState *getState() { return state; } + GBool checkTransparencyGroup(Dict *resDict); + void drawForm(Object *str, Dict *resDict, double *matrix, double *bbox, GBool transpGroup = gFalse, GBool softMask = gFalse, GfxColorSpace *blendingColorSpace = NULL, diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc index 5962fcb..e274b9f 100644 --- a/poppler/GfxState.cc +++ b/poppler/GfxState.cc @@ -5609,6 +5609,8 @@ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, lineCap = 0; miterLimit = 10; strokeAdjust = gFalse; + alphaIsShape = gFalse; + textKnockout = gFalse; font = NULL; fontSize = 0; diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h index 803d922..5e96d72 100644 --- a/poppler/OutputDev.h +++ b/poppler/OutputDev.h @@ -300,6 +300,7 @@ public: virtual GooHash *endProfile(); //----- transparency groups and soft masks + virtual GBool checkTransparencyGroup(GfxState * /*state*/, GBool /*knockout*/) { return gTrue; } virtual void beginTransparencyGroup(GfxState * /*state*/, double * /*bbox*/, GfxColorSpace * /*blendingColorSpace*/, GBool /*isolated*/, GBool /*knockout*/, diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index ce666b9..be35c25 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -3517,6 +3517,17 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, str->close(); } +GBool SplashOutputDev::checkTransparencyGroup(GfxState *state, GBool knockout) { + if (state->getFillOpacity() != 1 || + state->getStrokeOpacity() != 1 || + state->getAlphaIsShape() || + state->getBlendMode() != gfxBlendNormal || + splash->getSoftMask() != NULL || + knockout) + return gTrue; + return transpGroupStack != NULL && transpGroupStack->shape != NULL; +} + void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, GfxColorSpace *blendingColorSpace, GBool isolated, GBool knockout, diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h index b70ec38..f1c87ec 100644 --- a/poppler/SplashOutputDev.h +++ b/poppler/SplashOutputDev.h @@ -292,6 +292,7 @@ public: double llx, double lly, double urx, double ury); //----- transparency groups and soft masks + virtual GBool checkTransparencyGroup(GfxState *state, GBool knockout); virtual void beginTransparencyGroup(GfxState *state, double *bbox, GfxColorSpace *blendingColorSpace, GBool isolated, GBool knockout,