diff options
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc')
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc | 514 |
1 files changed, 330 insertions, 184 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc index 1539b8404bc..ea7951a75fc 100644 --- a/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc +++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Gfx.cc @@ -8,10 +8,6 @@ #include <aconf.h> -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - #include <stdlib.h> #include <stdio.h> #include <stddef.h> @@ -536,6 +532,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, out = outA; state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); fontChanged = gFalse; + haveSavedClipPath = gFalse; clip = clipNone; ignoreUndef = 0; out->startPage(pageNum, state); @@ -584,6 +581,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, out = outA; state = new GfxState(72, 72, box, 0, gFalse); fontChanged = gFalse; + haveSavedClipPath = gFalse; clip = clipNone; ignoreUndef = 0; for (i = 0; i < 6; ++i) { @@ -1829,15 +1827,20 @@ void Gfx::opFillStroke(Object args[], int numArgs) { } if (state->isPath()) { if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gFalse); } } } @@ -1852,15 +1855,20 @@ void Gfx::opCloseFillStroke(Object args[], int numArgs) { if (state->isPath()) { state->closePath(); if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gFalse); + } else { + out->fill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gFalse); } } } @@ -1874,15 +1882,20 @@ void Gfx::opEOFillStroke(Object args[], int numArgs) { } if (state->isPath()) { if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gTrue); } } } @@ -1897,15 +1910,20 @@ void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { if (state->isPath()) { state->closePath(); if (ocState) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - if (state->getStrokeColorSpace()->getMode() == csPattern) { - doPatternStroke(); + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + if (state->getFillColorSpace()->getMode() == csPattern) { + doPatternFill(gTrue); + } else { + out->eoFill(state); + } + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doPatternStroke(); + } else { + out->stroke(state); + } } else { - out->stroke(state); + out->fillStroke(state, gTrue); } } } @@ -1966,7 +1984,7 @@ void Gfx::doPatternStroke() { } } -void Gfx::doPatternText() { +void Gfx::doPatternText(GBool stroke) { GfxPattern *pattern; // this is a bit of a kludge -- patterns can be really slow, so we @@ -1976,7 +1994,8 @@ void Gfx::doPatternText() { return; } - if (!(pattern = state->getFillPattern())) { + pattern = stroke ? state->getStrokePattern() : state->getFillPattern(); + if (!pattern) { return; } switch (pattern->getType()) { @@ -2193,16 +2212,30 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, if (bbox[1] > bbox[3]) { t = bbox[1]; bbox[1] = bbox[3]; bbox[3] = t; } - xstep = fabs(tPat->getXStep()); - ystep = fabs(tPat->getYStep()); - xi0 = (int)ceil((xMin - bbox[2]) / xstep); - xi1 = (int)floor((xMax - bbox[0]) / xstep) + 1; - yi0 = (int)ceil((yMin - bbox[3]) / ystep); - yi1 = (int)floor((yMax - bbox[1]) / ystep) + 1; + xstep = tPat->getXStep(); + ystep = tPat->getYStep(); + if (xstep == 0 || ystep == 0) { + error(errSyntaxError, getPos(), "Zero x or y step in tiling pattern fill"); + goto err; + } + if (xstep > 0) { + xi0 = (int)ceil((xMin - bbox[2]) / xstep); + xi1 = (int)floor((xMax - bbox[0]) / xstep) + 1; + } else { + xi0 = (int)ceil((xMax - bbox[0]) / xstep); + xi1 = (int)floor((xMin - bbox[2]) / xstep) + 1; + } + if (ystep > 0) { + yi0 = (int)ceil((yMin - bbox[3]) / ystep); + yi1 = (int)floor((yMax - bbox[1]) / ystep) + 1; + } else { + yi0 = (int)ceil((yMax - bbox[1]) / ystep); + yi1 = (int)floor((yMin - bbox[3]) / ystep) + 1; + } for (i = 0; i < 4; ++i) { m1[i] = m[i]; } - if (out->useTilingPatternFill()) { + if (out->useTilingPatternFill() && !tPat->usesBlendMode(xref)) { m1[4] = m[4]; m1[5] = m[5]; out->tilingPatternFill(state, this, tPat->getContentStreamRef(), @@ -3521,12 +3554,16 @@ void Gfx::fillPatch(GfxPatch *patch, GfxPatchMeshShading *shading, int depth) { } void Gfx::doEndPath() { - if (state->isCurPt() && clip != clipNone) { - state->clip(); - if (clip == clipNormal) { - out->clip(state); + if (clip != clipNone) { + if (state->isCurPt()) { + state->clip(); + if (clip == clipNormal) { + out->clip(state); + } else { + out->eoClip(state); + } } else { - out->eoClip(state); + error(errSyntaxError, getPos(), "Empty path in clip"); } } clip = clipNone; @@ -3555,9 +3592,15 @@ void Gfx::opBeginText(Object args[], int numArgs) { out->updateTextMat(state); out->updateTextPos(state); fontChanged = gTrue; + haveSavedClipPath = gFalse; } void Gfx::opEndText(Object args[], int numArgs) { + if (haveSavedClipPath) { + out->clipToSavedClipPath(state); + haveSavedClipPath = gFalse; + } + out->endTextObject(state); } @@ -3786,27 +3829,8 @@ void Gfx::opShowSpaceText(Object args[], int numArgs) { } void Gfx::doShowText(GString *s) { - GfxFont *font; - int wMode; - double riseX, riseY; - CharCode code; - Unicode u[8]; - double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, ddx, ddy; - double originX, originY, tOriginX, tOriginY; - double x0, y0, x1, y1; - double oldCTM[6], newCTM[6]; - double *mat; - Object charProcRef, charProc; - Dict *resDict; - Parser *oldParser; - GfxState *savedState; - char *p; - int render; - GBool patternFill; - int len, n, uLen, nChars, nSpaces, i; - - font = state->getFont(); - wMode = font->getWMode(); + GfxFont *font = state->getFont(); + int wMode = font->getWMode(); if (globalParams->isDroppedFont(font->getName() ? font->getName()->getCString() : "")) { @@ -3818,35 +3842,63 @@ void Gfx::doShowText(GString *s) { out->beginString(state, s); } - // if we're doing a pattern fill, set up clipping - render = state->getRender(); - if (!(render & 1) && - state->getFillColorSpace()->getMode() == csPattern) { - patternFill = gTrue; - saveState(); - // disable fill, enable clipping, leave stroke unchanged - if ((render ^ (render >> 1)) & 1) { - render = 5; + // figure out the drawing mode + // note: clipping, pattern fill, and pattern stroke are all handled + // by saving the path and then performing the appropriate + // actions in opEndText() + GBool doFill = gFalse; + GBool doStroke = gFalse; + GBool doMakePath = gFalse; + int render = state->getRender() & 7; + switch (render & 7) { + case 0: // fill + if (state->getFillColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; } else { - render = 7; + doFill = gTrue; } - state->setRender(render); - out->updateRender(state); - } else { - patternFill = gFalse; + break; + case 1: // stroke + if (state->getStrokeColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; + } else { + doStroke = gTrue; + } + break; + case 2: // fill + stroke + if (state->getFillColorSpace()->getMode() == csPattern || + state->getStrokeColorSpace()->getMode() == csPattern) { + doMakePath = gTrue; + } else { + doFill = gTrue; + doStroke = gTrue; + } + break; + case 3: // invisible + // nothing + break; + case 4: // fill + clip + case 5: // stroke + clip + case 6: // fill + stroke + clip + case 7: // clip + doMakePath = gTrue; + break; } + double riseX, riseY; state->textTransformDelta(0, state->getRise(), &riseX, &riseY); - x0 = state->getCurX() + riseX; - y0 = state->getCurY() + riseY; + double xMin = state->getCurX() + riseX; + double yMin = state->getCurY() + riseY; // handle a Type 3 char if (font->getType() == fontType3 && out->interpretType3Chars()) { - mat = state->getCTM(); - for (i = 0; i < 6; ++i) { + double *mat = state->getCTM(); + double oldCTM[6]; + for (int i = 0; i < 6; ++i) { oldCTM[i] = mat[i]; } mat = state->getTextMat(); + double newCTM[6]; newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2]; newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3]; newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2]; @@ -3862,24 +3914,29 @@ void Gfx::doShowText(GString *s) { newCTM[3] *= state->getFontSize(); newCTM[0] *= state->getHorizScaling(); newCTM[1] *= state->getHorizScaling(); - curX = state->getCurX(); - curY = state->getCurY(); - oldParser = parser; - p = s->getCString(); - len = s->getLength(); + double curX = state->getCurX(); + double curY = state->getCurY(); + Parser *oldParser = parser; + char *p = s->getCString(); + int len = s->getLength(); while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx, dy, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); dx = dx * state->getFontSize() + state->getCharSpace(); if (n == 1 && *p == ' ') { dx += state->getWordSpace(); } dx *= state->getHorizScaling(); dy *= state->getFontSize(); + double tdx, tdy, ddx, ddy, x, y; state->textTransformDelta(dx, dy, &tdx, &tdy); state->transform(curX + riseX, curY + riseY, &x, &y); - savedState = saveStateStack(); + GfxState *savedState = saveStateStack(); state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); //~ the CTM concat values here are wrong (but never used) out->updateCTM(state, 1, 0, 0, 1, 0, 0); @@ -3899,9 +3956,11 @@ void Gfx::doShowText(GString *s) { #endif if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy, code, u, uLen)) { + Object charProcRef, charProc; ((Gfx8BitFont *)font)->getCharProcNF(code, &charProcRef); charProcRef.fetch(xref, &charProc); - if ((resDict = ((Gfx8BitFont *)font)->getResources())) { + Dict *resDict = ((Gfx8BitFont *)font)->getResources(); + if (resDict) { pushResources(resDict); } if (charProc.isStream()) { @@ -3927,12 +3986,16 @@ void Gfx::doShowText(GString *s) { parser = oldParser; } else if (out->useDrawChar()) { - p = s->getCString(); - len = s->getLength(); + char *p = s->getCString(); + int len = s->getLength(); while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx, &dy, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx, dy, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx, &dy, &originX, &originY); if (wMode) { dx *= state->getFontSize(); dy = dy * state->getFontSize() + state->getCharSpace(); @@ -3947,26 +4010,32 @@ void Gfx::doShowText(GString *s) { dx *= state->getHorizScaling(); dy *= state->getFontSize(); } + double tdx, tdy, tOriginX, tOriginY; state->textTransformDelta(dx, dy, &tdx, &tdy); originX *= state->getFontSize(); originY *= state->getFontSize(); state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY, - tdx, tdy, tOriginX, tOriginY, code, n, u, uLen); + tdx, tdy, tOriginX, tOriginY, code, n, u, uLen, + doFill, doStroke, doMakePath); state->shift(tdx, tdy); p += n; len -= n; } } else { - dx = dy = 0; - p = s->getCString(); - len = s->getLength(); - nChars = nSpaces = 0; + double dx = 0, dy = 0; + char *p = s->getCString(); + int len = s->getLength(); + int nChars = 0, nSpaces = 0; while (len > 0) { - n = font->getNextChar(p, len, &code, - u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, - &dx2, &dy2, &originX, &originY); + CharCode code; + Unicode u[8]; + int uLen; + double dx2, dy2, originX, originY; + int n = font->getNextChar(p, len, &code, + u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, + &dx2, &dy2, &originX, &originY); dx += dx2; dy += dy2; if (n == 1 && *p == ' ') { @@ -3988,8 +4057,9 @@ void Gfx::doShowText(GString *s) { dx *= state->getHorizScaling(); dy *= state->getFontSize(); } + double tdx, tdy; state->textTransformDelta(dx, dy, &tdx, &tdy); - out->drawString(state, s); + out->drawString(state, s, doFill, doStroke, doMakePath); state->shift(tdx, tdy); } @@ -3997,40 +4067,70 @@ void Gfx::doShowText(GString *s) { out->endString(state); } - if (patternFill) { - out->saveTextPos(state); - // tell the OutputDev to do the clipping - out->endTextObject(state); - // set up a clipping bbox so doPatternText will work -- assume + if (doMakePath) { + // compute the clipping bbox for the saved text path -- assume // that the text bounding box does not extend past the baseline in // any direction by more than twice the font size - x1 = state->getCurX() + riseX; - y1 = state->getCurY() + riseY; - if (x0 > x1) { - x = x0; x0 = x1; x1 = x; + double xMax = state->getCurX() + riseX; + double yMax = state->getCurY() + riseY; + double t; + if (xMin > xMax) { + t = xMin; xMin = xMax; xMax = t; } - if (y0 > y1) { - y = y0; y0 = y1; y1 = y; + if (yMin > yMax) { + t = yMin; yMin = yMax; yMax = t; } - state->textTransformDelta(0, state->getFontSize(), &dx, &dy); + double dx1, dy1, dx2, dy2; + state->textTransformDelta(0, state->getFontSize(), &dx1, &dy1); state->textTransformDelta(state->getFontSize(), 0, &dx2, &dy2); - dx = fabs(dx); + dx1 = fabs(dx1); dx2 = fabs(dx2); - if (dx2 > dx) { - dx = dx2; + if (dx2 > dx1) { + dx1 = dx2; } - dy = fabs(dy); + dy1 = fabs(dy1); dy2 = fabs(dy2); - if (dy2 > dy) { - dy = dy2; - } - state->clipToRect(x0 - 2 * dx, y0 - 2 * dy, x1 + 2 * dx, y1 + 2 * dy); - // set render mode to fill-only - state->setRender(0); - out->updateRender(state); - doPatternText(); - restoreState(); - out->restoreTextPos(state); + if (dy2 > dy1) { + dy1 = dy2; + } + xMin -= 2 * dx1; + yMin -= 2 * dy1; + xMax += 2 * dx1; + yMax += 2 * dy1; + + //--- fill + if ((render & 3) == 0 || (render & 3) == 2) { + if (state->getFillColorSpace()->getMode() == csPattern) { + saveState(); + state->clipToRect(xMin, yMin, xMax, yMax); + out->clipToTextPath(state); + doPatternText(gFalse); + restoreState(); + } else { + out->fillTextPath(state); + } + } + + //--- stroke + if ((render & 3) == 1 || (render & 3) == 2) { + if (state->getStrokeColorSpace()->getMode() == csPattern) { + saveState(); + state->clipToRect(xMin, yMin, xMax, yMax); + out->clipToTextStrokePath(state); + doPatternText(gTrue); + restoreState(); + } else { + out->strokeTextPath(state); + } + } + + //--- clip + if (render & 4) { + out->addTextPathToSavedClipPath(state); + haveSavedClipPath = gTrue; + } else { + out->clearTextPath(state); + } } opCounter += 10 * s->getLength(); @@ -4116,6 +4216,7 @@ void Gfx::opXObject(Object args[], int numArgs) { xObj.streamGetDict()->lookup("Level1", &obj3); out->psXObject(xObj.getStream(), obj3.isStream() ? obj3.getStream() : (Stream *)NULL); + obj3.free(); } } else if (obj2.isName()) { error(errSyntaxError, getPos(), @@ -4191,10 +4292,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("W", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + width = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image width"); + width = (int)obj1.getReal(); + } else { goto err2; } - width = obj1.getInt(); obj1.free(); if (width <= 0) { goto err1; @@ -4204,10 +4309,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("H", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + height = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image height"); + height = (int)obj1.getReal(); + } else { goto err2; } - height = obj1.getInt(); obj1.free(); if (height <= 0) { goto err1; @@ -4233,8 +4342,14 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); dict->lookup("BPC", &obj1); } - if (obj1.isInt()) { - bits = obj1.getInt(); + if (obj1.isNum()) { + if (obj1.isInt()) { + bits = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), + "Non-integer image bits per component"); + bits = (int)obj1.getReal(); + } if (bits < 1 || bits > 16) { goto err2; } @@ -4377,26 +4492,34 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("W", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskWidth = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask width"); + maskWidth = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskWidth = obj1.getInt(); obj1.free(); maskDict->lookup("Height", &obj1); if (obj1.isNull()) { obj1.free(); maskDict->lookup("H", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskHeight = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask height"); + maskHeight = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskHeight = obj1.getInt(); obj1.free(); if (maskWidth <= 0 || maskHeight <= 0) { delete colorMap; @@ -4409,13 +4532,18 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("BPC", &obj1); } - if (!obj1.isInt()) { + if (obj1.isInt()) { + maskBits = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), + "Non-integer image mask bits per component"); + maskBits = (int)obj1.getReal(); + } else { delete colorMap; maskObj.free(); smaskObj.free(); goto err2; } - maskBits = obj1.getInt(); obj1.free(); if (maskBits < 1 || maskBits > 16) { delete colorMap; @@ -4512,6 +4640,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } } else if (maskObj.isStream()) { // explicit mask + haveExplicitMask = gTrue; if (inlineImg) { delete colorMap; maskObj.free(); @@ -4526,32 +4655,31 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj1.free(); maskDict->lookup("W", &obj1); } - if (!obj1.isInt()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + if (obj1.isInt()) { + maskWidth = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask width"); + maskWidth = (int)obj1.getReal(); + } else { + haveExplicitMask = gFalse; } - maskWidth = obj1.getInt(); obj1.free(); maskDict->lookup("Height", &obj1); if (obj1.isNull()) { obj1.free(); maskDict->lookup("H", &obj1); } - if (!obj1.isInt()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + if (obj1.isInt()) { + maskHeight = obj1.getInt(); + } else if (obj1.isReal()) { + error(errSyntaxWarning, getPos(), "Non-integer image mask height"); + maskHeight = (int)obj1.getReal(); + } else { + haveExplicitMask = gFalse; } - maskHeight = obj1.getInt(); obj1.free(); if (maskWidth <= 0 || maskHeight <= 0) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } maskDict->lookup("ImageMask", &obj1); if (obj1.isNull()) { @@ -4559,10 +4687,7 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskDict->lookup("IM", &obj1); } if (!obj1.isBool() || !obj1.getBool()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } obj1.free(); maskInvert = gFalse; @@ -4576,13 +4701,12 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskInvert = obj2.isNum() && obj2.getNum() == 1; obj2.free(); } else if (!obj1.isNull()) { - delete colorMap; - maskObj.free(); - smaskObj.free(); - goto err2; + haveExplicitMask = gFalse; } obj1.free(); - haveExplicitMask = gTrue; + if (!haveExplicitMask) { + error(errSyntaxError, getPos(), "Bad image parameters"); + } } // if drawing is disabled, skip over inline image data @@ -4768,6 +4892,8 @@ void Gfx::drawForm(Object *strRef, Dict *resDict, double oldBaseMatrix[6]; int i; + out->startStream(strRef->getRef(), state); + // push new resources on stack pushResources(resDict); @@ -4897,7 +5023,7 @@ void Gfx::drawForm(Object *strRef, Dict *resDict, delete blendingColorSpace; } - return; + out->endStream(strRef->getRef()); } void Gfx::takeContentStreamStack(Gfx *oldGfx) { @@ -4936,7 +5062,9 @@ void Gfx::opBeginImage(Object args[], int numArgs) { // if we have the stream length, skip to end-of-stream and then // skip 'EI' in the original stream } else if (haveLength) { - while ((c1 = str->getChar()) != EOF) ; + // NB: getUndecodedStream() returns the EmbedStream created by + // buildImageStream() + while ((c1 = str->getUndecodedStream()->getChar()) != EOF) ; delete str; str = parser->getStream(); c1 = str->getChar(); @@ -5091,15 +5219,28 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) { } obj.free(); mcKind = gfxMCOptionalContent; - } else if (args[0].isName("Span") && numArgs == 2 && args[1].isDict()) { - if (args[1].dictLookup("ActualText", &obj)->isString()) { - s = new TextString(obj.getString()); - out->beginActualText(state, s->getUnicode(), s->getLength()); - delete s; - mcKind = gfxMCActualText; + } else if (numArgs == 2 && args[1].isDict()) { + if (args[0].isName("Span")) { + if (args[1].dictLookup("ActualText", &obj)->isString()) { + s = new TextString(obj.getString()); + out->beginActualText(state, s->getUnicode(), s->getLength()); + delete s; + mcKind = gfxMCActualText; + } + obj.free(); + } + if (args[1].dictLookup("MCID", &obj)->isInt()) { + out->beginStructureItem(args[0].getName(), obj.getInt(), + args[1].getDict()); + if (mcKind == gfxMCActualText) { + mcKind = gfxMCStructureItemAndActualText; + } else { + mcKind = gfxMCStructureItem; + } } obj.free(); } + mc = new GfxMarkedContent(mcKind, ocState); markedContentStack->append(mc); } @@ -5123,6 +5264,11 @@ void Gfx::opEndMarkedContent(Object args[], int numArgs) { } } else if (mcKind == gfxMCActualText) { out->endActualText(state); + } else if (mcKind == gfxMCStructureItem) { + out->endStructureItem(); + } else if (mcKind == gfxMCStructureItemAndActualText) { + out->endStructureItem(); + out->endActualText(state); } } else { error(errSyntaxWarning, getPos(), "Mismatched EMC operator"); |