Gfx.cc (xpdf-4.03) | : | Gfx.cc (xpdf-4.04) | ||
---|---|---|---|---|
skipping to change at line 530 | skipping to change at line 530 | |||
double hDPI, double vDPI, PDFRectangle *box, | double hDPI, double vDPI, PDFRectangle *box, | |||
PDFRectangle *cropBox, int rotate, | PDFRectangle *cropBox, int rotate, | |||
GBool (*abortCheckCbkA)(void *data), | GBool (*abortCheckCbkA)(void *data), | |||
void *abortCheckCbkDataA) { | void *abortCheckCbkDataA) { | |||
int i; | int i; | |||
doc = docA; | doc = docA; | |||
xref = doc->getXRef(); | xref = doc->getXRef(); | |||
subPage = gFalse; | subPage = gFalse; | |||
printCommands = globalParams->getPrintCommands(); | printCommands = globalParams->getPrintCommands(); | |||
defaultFont = NULL; | ||||
// start the resource stack | // start the resource stack | |||
res = new GfxResources(xref, resDict, NULL); | res = new GfxResources(xref, resDict, NULL); | |||
// initialize | // initialize | |||
out = outA; | out = outA; | |||
state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); | state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); | |||
fontChanged = gFalse; | fontChanged = gFalse; | |||
clip = clipNone; | clip = clipNone; | |||
ignoreUndef = 0; | ignoreUndef = 0; | |||
skipping to change at line 577 | skipping to change at line 578 | |||
Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, | Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, | |||
PDFRectangle *box, PDFRectangle *cropBox, | PDFRectangle *box, PDFRectangle *cropBox, | |||
GBool (*abortCheckCbkA)(void *data), | GBool (*abortCheckCbkA)(void *data), | |||
void *abortCheckCbkDataA) { | void *abortCheckCbkDataA) { | |||
int i; | int i; | |||
doc = docA; | doc = docA; | |||
xref = doc->getXRef(); | xref = doc->getXRef(); | |||
subPage = gTrue; | subPage = gTrue; | |||
printCommands = globalParams->getPrintCommands(); | printCommands = globalParams->getPrintCommands(); | |||
defaultFont = NULL; | ||||
// start the resource stack | // start the resource stack | |||
res = new GfxResources(xref, resDict, NULL); | res = new GfxResources(xref, resDict, NULL); | |||
// initialize | // initialize | |||
out = outA; | out = outA; | |||
state = new GfxState(72, 72, box, 0, gFalse); | state = new GfxState(72, 72, box, 0, gFalse); | |||
fontChanged = gFalse; | fontChanged = gFalse; | |||
clip = clipNone; | clip = clipNone; | |||
ignoreUndef = 0; | ignoreUndef = 0; | |||
skipping to change at line 612 | skipping to change at line 614 | |||
state->lineTo(cropBox->x2, cropBox->y2); | state->lineTo(cropBox->x2, cropBox->y2); | |||
state->lineTo(cropBox->x1, cropBox->y2); | state->lineTo(cropBox->x1, cropBox->y2); | |||
state->closePath(); | state->closePath(); | |||
state->clip(); | state->clip(); | |||
out->clip(state); | out->clip(state); | |||
state->clearPath(); | state->clearPath(); | |||
} | } | |||
} | } | |||
Gfx::~Gfx() { | Gfx::~Gfx() { | |||
if (defaultFont) { | ||||
delete defaultFont; | ||||
} | ||||
if (!subPage) { | if (!subPage) { | |||
out->endPage(); | out->endPage(); | |||
} | } | |||
while (state->hasSaves()) { | while (state->hasSaves()) { | |||
restoreState(); | restoreState(); | |||
} | } | |||
delete state; | delete state; | |||
while (res) { | while (res) { | |||
popResources(); | popResources(); | |||
} | } | |||
skipping to change at line 2083 | skipping to change at line 2088 | |||
imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det; | imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det; | |||
// save current graphics state | // save current graphics state | |||
savedState = saveStateStack(); | savedState = saveStateStack(); | |||
// set underlying color space (for uncolored tiling patterns); set | // set underlying color space (for uncolored tiling patterns); set | |||
// various other parameters (stroke color, line width) to match | // various other parameters (stroke color, line width) to match | |||
// Adobe's behavior | // Adobe's behavior | |||
state->setFillPattern(NULL); | state->setFillPattern(NULL); | |||
state->setStrokePattern(NULL); | state->setStrokePattern(NULL); | |||
state->setFillOverprint(gFalse); | ||||
state->setStrokeOverprint(gFalse); | ||||
state->setOverprintMode(0); | ||||
if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { | if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { | |||
state->setFillColorSpace(cs->copy()); | state->setFillColorSpace(cs->copy()); | |||
out->updateFillColorSpace(state); | out->updateFillColorSpace(state); | |||
state->setStrokeColorSpace(cs->copy()); | state->setStrokeColorSpace(cs->copy()); | |||
out->updateStrokeColorSpace(state); | out->updateStrokeColorSpace(state); | |||
state->setStrokeColor(state->getFillColor()); | if (stroke) { | |||
state->setFillColor(state->getStrokeColor()); | ||||
} else { | ||||
state->setStrokeColor(state->getFillColor()); | ||||
} | ||||
out->updateFillColor(state); | out->updateFillColor(state); | |||
out->updateStrokeColor(state); | out->updateStrokeColor(state); | |||
state->setIgnoreColorOps(gTrue); | state->setIgnoreColorOps(gTrue); | |||
} else { | } else { | |||
state->setFillColorSpace(GfxColorSpace::create(csDeviceGray)); | state->setFillColorSpace(GfxColorSpace::create(csDeviceGray)); | |||
out->updateFillColorSpace(state); | out->updateFillColorSpace(state); | |||
state->getFillColorSpace()->getDefaultColor(&color); | state->getFillColorSpace()->getDefaultColor(&color); | |||
state->setFillColor(&color); | state->setFillColor(&color); | |||
out->updateFillColor(state); | out->updateFillColor(state); | |||
state->setStrokeColorSpace(GfxColorSpace::create(csDeviceGray)); | state->setStrokeColorSpace(GfxColorSpace::create(csDeviceGray)); | |||
skipping to change at line 3567 | skipping to change at line 3579 | |||
state->setCharSpace(args[0].getNum()); | state->setCharSpace(args[0].getNum()); | |||
out->updateCharSpace(state); | out->updateCharSpace(state); | |||
} | } | |||
void Gfx::opSetFont(Object args[], int numArgs) { | void Gfx::opSetFont(Object args[], int numArgs) { | |||
doSetFont(res->lookupFont(args[0].getName()), args[1].getNum()); | doSetFont(res->lookupFont(args[0].getName()), args[1].getNum()); | |||
} | } | |||
void Gfx::doSetFont(GfxFont *font, double size) { | void Gfx::doSetFont(GfxFont *font, double size) { | |||
if (!font) { | if (!font) { | |||
state->setFont(NULL, 0); | if (!defaultFont) { | |||
return; | defaultFont = GfxFont::makeDefaultFont(xref); | |||
} | ||||
font = defaultFont; | ||||
} | } | |||
if (printCommands) { | if (printCommands) { | |||
printf(" font: tag=%s name='%s' %g\n", | printf(" font: tag=%s name='%s' %g\n", | |||
font->getTag()->getCString(), | font->getTag()->getCString(), | |||
font->getName() ? font->getName()->getCString() : "???", | font->getName() ? font->getName()->getCString() : "???", | |||
size); | size); | |||
fflush(stdout); | fflush(stdout); | |||
} | } | |||
state->setFont(font, size); | state->setFont(font, size); | |||
fontChanged = gTrue; | fontChanged = gTrue; | |||
skipping to change at line 3850 | skipping to change at line 3864 | |||
mat = font->getFontMatrix(); | mat = font->getFontMatrix(); | |||
newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2]; | newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2]; | |||
newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3]; | newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3]; | |||
newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2]; | newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2]; | |||
newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3]; | newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3]; | |||
newCTM[0] *= state->getFontSize(); | newCTM[0] *= state->getFontSize(); | |||
newCTM[1] *= state->getFontSize(); | newCTM[1] *= state->getFontSize(); | |||
newCTM[2] *= state->getFontSize(); | newCTM[2] *= state->getFontSize(); | |||
newCTM[3] *= state->getFontSize(); | newCTM[3] *= state->getFontSize(); | |||
newCTM[0] *= state->getHorizScaling(); | newCTM[0] *= state->getHorizScaling(); | |||
newCTM[2] *= state->getHorizScaling(); | newCTM[1] *= state->getHorizScaling(); | |||
curX = state->getCurX(); | curX = state->getCurX(); | |||
curY = state->getCurY(); | curY = state->getCurY(); | |||
oldParser = parser; | oldParser = parser; | |||
p = s->getCString(); | p = s->getCString(); | |||
len = s->getLength(); | len = s->getLength(); | |||
while (len > 0) { | while (len > 0) { | |||
n = font->getNextChar(p, len, &code, | n = font->getNextChar(p, len, &code, | |||
u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, | u, (int)(sizeof(u) / sizeof(Unicode)), &uLen, | |||
&dx, &dy, &originX, &originY); | &dx, &dy, &originX, &originY); | |||
dx = dx * state->getFontSize() + state->getCharSpace(); | dx = dx * state->getFontSize() + state->getCharSpace(); | |||
skipping to change at line 4038 | skipping to change at line 4052 | |||
out->incCharCount(s->getLength()); | out->incCharCount(s->getLength()); | |||
} | } | |||
} | } | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
// XObject operators | // XObject operators | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
void Gfx::opXObject(Object args[], int numArgs) { | void Gfx::opXObject(Object args[], int numArgs) { | |||
char *name; | char *name; | |||
Object obj1, obj2, obj3, refObj; | Object xObj, refObj, obj2, obj3; | |||
GBool ocSaved, oc; | GBool ocSaved, oc; | |||
#if OPI_SUPPORT | #if OPI_SUPPORT | |||
Object opiDict; | Object opiDict; | |||
#endif | #endif | |||
if (!ocState && !out->needCharCount()) { | if (!ocState && !out->needCharCount()) { | |||
return; | return; | |||
} | } | |||
name = args[0].getName(); | name = args[0].getName(); | |||
if (!res->lookupXObject(name, &obj1)) { | // NB: we get both the reference and the object here, to make sure | |||
// they refer to the same object. There's a problematic corner | ||||
// case: if the resource dict contains an entry for [name] with a | ||||
// reference to a nonexistent object ("/name 99999 0 R", where | ||||
// object 99999 doesn't exist), and a parent resource dict contains | ||||
// a valid entry with the same name, then lookupXObjectNF() will | ||||
// return "99999 0 R", but lookupXObject() will return the valid | ||||
// entry. This causes problems for doImage() and doForm(). | ||||
if (!res->lookupXObjectNF(name, &refObj)) { | ||||
return; | return; | |||
} | } | |||
if (!obj1.isStream()) { | if (!refObj.fetch(xref, &xObj)) { | |||
refObj.free(); | ||||
return; | ||||
} | ||||
if (!xObj.isStream()) { | ||||
error(errSyntaxError, getPos(), "XObject '{0:s}' is wrong type", name); | error(errSyntaxError, getPos(), "XObject '{0:s}' is wrong type", name); | |||
obj1.free(); | xObj.free(); | |||
refObj.free(); | ||||
return; | return; | |||
} | } | |||
// check for optional content key | // check for optional content key | |||
ocSaved = ocState; | ocSaved = ocState; | |||
obj1.streamGetDict()->lookupNF("OC", &obj2); | xObj.streamGetDict()->lookupNF("OC", &obj2); | |||
if (doc->getOptionalContent()->evalOCObject(&obj2, &oc)) { | if (doc->getOptionalContent()->evalOCObject(&obj2, &oc)) { | |||
ocState &= oc; | ocState &= oc; | |||
} | } | |||
obj2.free(); | obj2.free(); | |||
#if USE_EXCEPTIONS | #if USE_EXCEPTIONS | |||
try { | try { | |||
#endif | #endif | |||
#if OPI_SUPPORT | #if OPI_SUPPORT | |||
obj1.streamGetDict()->lookup("OPI", &opiDict); | xObj.streamGetDict()->lookup("OPI", &opiDict); | |||
if (opiDict.isDict()) { | if (opiDict.isDict()) { | |||
out->opiBegin(state, opiDict.getDict()); | out->opiBegin(state, opiDict.getDict()); | |||
} | } | |||
#endif | #endif | |||
obj1.streamGetDict()->lookup("Subtype", &obj2); | xObj.streamGetDict()->lookup("Subtype", &obj2); | |||
if (obj2.isName("Image")) { | if (obj2.isName("Image")) { | |||
if (out->needNonText()) { | if (out->needNonText()) { | |||
res->lookupXObjectNF(name, &refObj); | doImage(&refObj, xObj.getStream(), gFalse); | |||
doImage(&refObj, obj1.getStream(), gFalse); | ||||
refObj.free(); | ||||
} | } | |||
} else if (obj2.isName("Form")) { | } else if (obj2.isName("Form")) { | |||
res->lookupXObjectNF(name, &refObj); | ||||
if (out->useDrawForm() && refObj.isRef()) { | if (out->useDrawForm() && refObj.isRef()) { | |||
if (ocState) { | if (ocState) { | |||
out->drawForm(refObj.getRef()); | out->drawForm(refObj.getRef()); | |||
} | } | |||
} else { | } else { | |||
doForm(&refObj, &obj1); | doForm(&refObj, &xObj); | |||
} | } | |||
refObj.free(); | ||||
} else if (obj2.isName("PS")) { | } else if (obj2.isName("PS")) { | |||
if (ocState) { | if (ocState) { | |||
obj1.streamGetDict()->lookup("Level1", &obj3); | xObj.streamGetDict()->lookup("Level1", &obj3); | |||
out->psXObject(obj1.getStream(), | out->psXObject(xObj.getStream(), | |||
obj3.isStream() ? obj3.getStream() : (Stream *)NULL); | obj3.isStream() ? obj3.getStream() : (Stream *)NULL); | |||
} | } | |||
} else if (obj2.isName()) { | } else if (obj2.isName()) { | |||
error(errSyntaxError, getPos(), | error(errSyntaxError, getPos(), | |||
"Unknown XObject subtype '{0:s}'", obj2.getName()); | "Unknown XObject subtype '{0:s}'", obj2.getName()); | |||
} else { | } else { | |||
error(errSyntaxError, getPos(), | error(errSyntaxError, getPos(), | |||
"XObject subtype is missing or wrong type"); | "XObject subtype is missing or wrong type"); | |||
} | } | |||
obj2.free(); | obj2.free(); | |||
#if OPI_SUPPORT | #if OPI_SUPPORT | |||
if (opiDict.isDict()) { | if (opiDict.isDict()) { | |||
out->opiEnd(state, opiDict.getDict()); | out->opiEnd(state, opiDict.getDict()); | |||
} | } | |||
opiDict.free(); | opiDict.free(); | |||
#endif | #endif | |||
#if USE_EXCEPTIONS | #if USE_EXCEPTIONS | |||
} catch (GMemException e) { | } catch (GMemException e) { | |||
obj1.free(); | xObj.free(); | |||
refObj.free(); | ||||
throw; | throw; | |||
} | } | |||
#endif | #endif | |||
obj1.free(); | ||||
ocState = ocSaved; | ocState = ocSaved; | |||
xObj.free(); | ||||
refObj.free(); | ||||
} | } | |||
GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { | GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { | |||
Dict *dict, *maskDict; | Dict *dict, *maskDict; | |||
int width, height; | int width, height; | |||
int bits, maskBits; | int bits, maskBits; | |||
StreamColorSpaceMode csMode; | StreamColorSpaceMode csMode; | |||
GBool mask, invert; | GBool mask, invert; | |||
GfxColorSpace *colorSpace, *maskColorSpace; | GfxColorSpace *colorSpace, *maskColorSpace; | |||
GfxImageColorMap *colorMap, *maskColorMap; | GfxImageColorMap *colorMap, *maskColorMap; | |||
skipping to change at line 4147 | skipping to change at line 4173 | |||
GBool interpolate; | GBool interpolate; | |||
GfxRenderingIntent riSaved; | GfxRenderingIntent riSaved; | |||
Object obj1, obj2; | Object obj1, obj2; | |||
int i, n; | int i, n; | |||
// check for optional content | // check for optional content | |||
if (!ocState && !inlineImg) { | if (!ocState && !inlineImg) { | |||
return gTrue; | return gTrue; | |||
} | } | |||
// images can have arbitrarily high compression ratios, but the | ||||
// data size is inherently limited | ||||
str->disableDecompressionBombChecking(); | ||||
// get info from the stream | // get info from the stream | |||
bits = 0; | bits = 0; | |||
csMode = streamCSNone; | csMode = streamCSNone; | |||
str->getImageParams(&bits, &csMode); | str->getImageParams(&bits, &csMode); | |||
// get stream dict | // get stream dict | |||
dict = str->getDict(); | dict = str->getDict(); | |||
// save the current rendering intent | // save the current rendering intent | |||
riSaved = state->getRenderingIntent(); | riSaved = state->getRenderingIntent(); | |||
skipping to change at line 4251 | skipping to change at line 4281 | |||
obj1.arrayGet(0, &obj2); | obj1.arrayGet(0, &obj2); | |||
invert = obj2.isNum() && obj2.getNum() == 1; | invert = obj2.isNum() && obj2.getNum() == 1; | |||
obj2.free(); | obj2.free(); | |||
} else if (!obj1.isNull()) { | } else if (!obj1.isNull()) { | |||
goto err2; | goto err2; | |||
} | } | |||
obj1.free(); | obj1.free(); | |||
// if drawing is disabled, skip over inline image data | // if drawing is disabled, skip over inline image data | |||
if (!ocState) { | if (!ocState) { | |||
str->disableDecompressionBombChecking(); | ||||
str->reset(); | str->reset(); | |||
n = height * ((width + 7) / 8); | n = height * ((width + 7) / 8); | |||
for (i = 0; i < n; ++i) { | for (i = 0; i < n; ++i) { | |||
str->getChar(); | str->getChar(); | |||
} | } | |||
str->close(); | str->close(); | |||
// draw it | // draw it | |||
} else { | } else { | |||
if (state->getFillColorSpace()->getMode() == csPattern) { | if (state->getFillColorSpace()->getMode() == csPattern) { | |||
skipping to change at line 4342 | skipping to change at line 4373 | |||
dict->lookup("SMask", &smaskObj); | dict->lookup("SMask", &smaskObj); | |||
if (smaskObj.isStream()) { | if (smaskObj.isStream()) { | |||
// soft mask | // soft mask | |||
if (inlineImg) { | if (inlineImg) { | |||
delete colorMap; | delete colorMap; | |||
maskObj.free(); | maskObj.free(); | |||
smaskObj.free(); | smaskObj.free(); | |||
goto err1; | goto err1; | |||
} | } | |||
maskStr = smaskObj.getStream(); | maskStr = smaskObj.getStream(); | |||
maskStr->disableDecompressionBombChecking(); | ||||
maskDict = smaskObj.streamGetDict(); | maskDict = smaskObj.streamGetDict(); | |||
maskDict->lookup("Width", &obj1); | maskDict->lookup("Width", &obj1); | |||
if (obj1.isNull()) { | if (obj1.isNull()) { | |||
obj1.free(); | obj1.free(); | |||
maskDict->lookup("W", &obj1); | maskDict->lookup("W", &obj1); | |||
} | } | |||
if (!obj1.isInt()) { | if (!obj1.isInt()) { | |||
delete colorMap; | delete colorMap; | |||
maskObj.free(); | maskObj.free(); | |||
smaskObj.free(); | smaskObj.free(); | |||
skipping to change at line 4490 | skipping to change at line 4522 | |||
} | } | |||
} else if (maskObj.isStream()) { | } else if (maskObj.isStream()) { | |||
// explicit mask | // explicit mask | |||
if (inlineImg) { | if (inlineImg) { | |||
delete colorMap; | delete colorMap; | |||
maskObj.free(); | maskObj.free(); | |||
smaskObj.free(); | smaskObj.free(); | |||
goto err1; | goto err1; | |||
} | } | |||
maskStr = maskObj.getStream(); | maskStr = maskObj.getStream(); | |||
maskStr->disableDecompressionBombChecking(); | ||||
maskDict = maskObj.streamGetDict(); | maskDict = maskObj.streamGetDict(); | |||
maskDict->lookup("Width", &obj1); | maskDict->lookup("Width", &obj1); | |||
if (obj1.isNull()) { | if (obj1.isNull()) { | |||
obj1.free(); | obj1.free(); | |||
maskDict->lookup("W", &obj1); | maskDict->lookup("W", &obj1); | |||
} | } | |||
if (!obj1.isInt()) { | if (!obj1.isInt()) { | |||
delete colorMap; | delete colorMap; | |||
maskObj.free(); | maskObj.free(); | |||
smaskObj.free(); | smaskObj.free(); | |||
skipping to change at line 4562 | skipping to change at line 4595 | |||
haveExplicitMask = gTrue; | haveExplicitMask = gTrue; | |||
} | } | |||
// if drawing is disabled, skip over inline image data | // if drawing is disabled, skip over inline image data | |||
if (state->getIgnoreColorOps() || !ocState) { | if (state->getIgnoreColorOps() || !ocState) { | |||
if (state->getIgnoreColorOps()) { | if (state->getIgnoreColorOps()) { | |||
error(errSyntaxWarning, getPos(), "Ignoring image" | error(errSyntaxWarning, getPos(), "Ignoring image" | |||
" in uncolored Type 3 char or tiling pattern"); | " in uncolored Type 3 char or tiling pattern"); | |||
} | } | |||
if (inlineImg) { | if (inlineImg) { | |||
str->disableDecompressionBombChecking(); | ||||
str->reset(); | str->reset(); | |||
n = height * ((width * colorMap->getNumPixelComps() * | n = height * ((width * colorMap->getNumPixelComps() * | |||
colorMap->getBits() + 7) / 8); | colorMap->getBits() + 7) / 8); | |||
str->discardChars(n); | str->discardChars(n); | |||
str->close(); | str->close(); | |||
} | } | |||
// draw it | // draw it | |||
} else { | } else { | |||
if (haveSoftMask) { | if (haveSoftMask) { | |||
dict->lookupNF("Mask", &maskRef); | dict->lookupNF("SMask", &maskRef); | |||
out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, | out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, | |||
&maskRef, maskStr, maskWidth, maskHeight, | &maskRef, maskStr, maskWidth, maskHeight, | |||
maskColorMap, | maskColorMap, | |||
haveMatte ? matte : (double *)NULL, | haveMatte ? matte : (double *)NULL, | |||
interpolate); | interpolate); | |||
maskRef.free(); | maskRef.free(); | |||
delete maskColorMap; | delete maskColorMap; | |||
} else if (haveExplicitMask) { | } else if (haveExplicitMask) { | |||
dict->lookupNF("Mask", &maskRef); | dict->lookupNF("Mask", &maskRef); | |||
out->drawMaskedImage(state, ref, str, width, height, colorMap, | out->drawMaskedImage(state, ref, str, width, height, colorMap, | |||
skipping to change at line 4657 | skipping to change at line 4691 | |||
// check form type | // check form type | |||
dict->lookup("FormType", &obj1); | dict->lookup("FormType", &obj1); | |||
if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { | if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { | |||
error(errSyntaxError, getPos(), "Unknown form type"); | error(errSyntaxError, getPos(), "Unknown form type"); | |||
} | } | |||
obj1.free(); | obj1.free(); | |||
// get bounding box | // get bounding box | |||
dict->lookup("BBox", &bboxObj); | dict->lookup("BBox", &bboxObj); | |||
if (!bboxObj.isArray()) { | if (!(bboxObj.isArray() && bboxObj.arrayGetLength() == 4)) { | |||
bboxObj.free(); | bboxObj.free(); | |||
error(errSyntaxError, getPos(), "Bad form bounding box"); | error(errSyntaxError, getPos(), "Bad form bounding box"); | |||
return; | return; | |||
} | } | |||
for (i = 0; i < 4; ++i) { | for (i = 0; i < 4; ++i) { | |||
bboxObj.arrayGet(i, &obj1); | bboxObj.arrayGet(i, &obj1); | |||
if (!obj1.isNum()) { | ||||
bboxObj.free(); | ||||
error(errSyntaxError, getPos(), "Bad form bounding box"); | ||||
return; | ||||
} | ||||
bbox[i] = obj1.getNum(); | bbox[i] = obj1.getNum(); | |||
obj1.free(); | obj1.free(); | |||
} | } | |||
bboxObj.free(); | bboxObj.free(); | |||
// get matrix | // get matrix | |||
dict->lookup("Matrix", &matrixObj); | dict->lookup("Matrix", &matrixObj); | |||
if (matrixObj.isArray()) { | if (matrixObj.isArray() && matrixObj.arrayGetLength() == 6) { | |||
for (i = 0; i < 6; ++i) { | for (i = 0; i < 6; ++i) { | |||
matrixObj.arrayGet(i, &obj1); | matrixObj.arrayGet(i, &obj1); | |||
m[i] = obj1.getNum(); | if (obj1.isNum()) { | |||
m[i] = obj1.getNum(); | ||||
} else { | ||||
m[i] = 0; | ||||
} | ||||
obj1.free(); | obj1.free(); | |||
} | } | |||
} else { | } else { | |||
m[0] = 1; m[1] = 0; | m[0] = 1; m[1] = 0; | |||
m[2] = 0; m[3] = 1; | m[2] = 0; m[3] = 1; | |||
m[4] = 0; m[5] = 0; | m[4] = 0; m[5] = 0; | |||
} | } | |||
matrixObj.free(); | matrixObj.free(); | |||
// get resources | // get resources | |||
skipping to change at line 4772 | skipping to change at line 4815 | |||
if (strObj.streamGetDict()->lookup("Group", &groupAttrsObj)->isDict()) { | if (strObj.streamGetDict()->lookup("Group", &groupAttrsObj)->isDict()) { | |||
if (!groupAttrsObj.dictLookup("CS", &csObj)->isNull()) { | if (!groupAttrsObj.dictLookup("CS", &csObj)->isNull()) { | |||
blendingColorSpace = GfxColorSpace::parse(&csObj | blendingColorSpace = GfxColorSpace::parse(&csObj | |||
); | ); | |||
} | } | |||
csObj.free(); | csObj.free(); | |||
} | } | |||
groupAttrsObj.free(); | groupAttrsObj.free(); | |||
strObj.free(); | strObj.free(); | |||
traceBegin(oldBaseMatrix, softMask ? "begin soft mask" : "begin t-group"); | if (!out->beginTransparencyGroup(state, bbox, blendingColorSpace, | |||
if (state->getBlendMode() != gfxBlendNormal) { | isolated, knockout, softMask)) { | |||
state->setBlendMode(gfxBlendNormal); | transpGroup = gFalse; | |||
out->updateBlendMode(state); | } | |||
if (softMask || transpGroup) { | ||||
traceBegin(oldBaseMatrix, softMask ? "begin soft mask" : "begin t-group"); | ||||
if (state->getBlendMode() != gfxBlendNormal) { | ||||
state->setBlendMode(gfxBlendNormal); | ||||
out->updateBlendMode(state); | ||||
} | ||||
if (state->getFillOpacity() != 1) { | ||||
state->setFillOpacity(1); | ||||
out->updateFillOpacity(state); | ||||
} | ||||
if (state->getStrokeOpacity() != 1) { | ||||
state->setStrokeOpacity(1); | ||||
out->updateStrokeOpacity(state); | ||||
} | ||||
out->clearSoftMask(state); | ||||
} | } | |||
if (state->getFillOpacity() != 1) { | ||||
state->setFillOpacity(1); | ||||
out->updateFillOpacity(state); | ||||
} | ||||
if (state->getStrokeOpacity() != 1) { | ||||
state->setStrokeOpacity(1); | ||||
out->updateStrokeOpacity(state); | ||||
} | ||||
out->clearSoftMask(state); | ||||
out->beginTransparencyGroup(state, bbox, blendingColorSpace, | ||||
isolated, knockout, softMask); | ||||
} | } | |||
// set new base matrix | // set new base matrix | |||
for (i = 0; i < 6; ++i) { | for (i = 0; i < 6; ++i) { | |||
oldBaseMatrix[i] = baseMatrix[i]; | oldBaseMatrix[i] = baseMatrix[i]; | |||
baseMatrix[i] = state->getCTM()[i]; | baseMatrix[i] = state->getCTM()[i]; | |||
} | } | |||
// save the state stack -- this handles the case where the form | // save the state stack -- this handles the case where the form | |||
// contents have unbalanced q/Q operators | // contents have unbalanced q/Q operators | |||
End of changes. 34 change blocks. | ||||
40 lines changed or deleted | 88 lines changed or added |