diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp
index c64f5de06fe3b4fbfda037c531dd2d0b773b0957..118896fd30318d74881f4d97a1a273ee592bc1ed 100644 (file)
// constants
//------------------------------------------------------------------------
-// Max recursive depth for a function shading fill.
-#define functionMaxDepth 6
+// Default max delta allowed in any color component for a shading fill.
+#define defaultShadingColorDelta (dblToCol( 1 / 2.0 ))
-// Max delta allowed in any color component for a function shading fill.
-#define functionColorDelta (dblToCol(1 / 256.0))
-
-// Max number of splits along the t axis for an axial shading fill.
-#define axialMaxSplits 256
-
-// Max delta allowed in any color component for an axial shading fill.
-#define axialColorDelta (dblToCol(1 / 256.0))
-
-// Max number of splits along the t axis for a radial shading fill.
-#define radialMaxSplits 256
-
-// Max delta allowed in any color component for a radial shading fill.
-#define radialColorDelta (dblToCol(1 / 256.0))
-
-// Max recursive depth for a Gouraud triangle shading fill.
-#define gouraudMaxDepth 6
-
-// Max delta allowed in any color component for a Gouraud triangle
-// shading fill.
-#define gouraudColorDelta (dblToCol(1 / 256.0))
-
-// Max recursive depth for a patch mesh shading fill.
-#define patchMaxDepth 6
-
-// Max delta allowed in any color component for a patch mesh shading
-// fill.
-#define patchColorDelta (dblToCol(1 / 256.0))
+// Default max recursive depth for a shading fill.
+#define defaultShadingMaxDepth 6
// Max number of operators kept in the history list.
#define maxOperatorHistoryDepth 16
//------------------------------------------------------------------------
PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *builderA,
- int pageNum, int rotate, Dict *resDict, PDFRectangle *cropBox) {
+ int pageNum, int rotate, Dict *resDict,
+ PDFRectangle *box, PDFRectangle *cropBox) {
int i;
@@ -295,7 +270,9 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui
res = new GfxResources(xref, resDict, NULL);
// initialize
- state = new GfxState(72.0, 72.0, cropBox, rotate, gTrue);
+ state = new GfxState(72.0, 72.0, box, rotate, gTrue);
+ clipHistory = new ClipHistoryEntry();
+ setDefaultApproximationPrecision();
fontChanged = gFalse;
clip = clipNone;
ignoreUndef = 0;
@@ -310,6 +287,7 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui
baseMatrix[i] = ctm[i];
scaledCTM[i] = PX_PER_PT * ctm[i];
}
+ saveState();
builder->setTransform((double*)&scaledCTM);
formDepth = 0;
@@ -327,6 +305,7 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui
state->lineTo(cropBox->x1, cropBox->y2);
state->closePath();
state->clip();
+ clipHistory->setClip(state->getPath(), clipNormal);
builder->setClipPath(state);
state->clearPath();
}
@@ -334,6 +313,34 @@ PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *bui
pushOperator("startPage");
}
+PdfParser::PdfParser(XRef *xrefA, Inkscape::Extension::Internal::SvgBuilder *builderA,
+ Dict *resDict, PDFRectangle *box) {
+
+ int i;
+
+ xref = xrefA;
+ subPage = gTrue;
+ printCommands = false;
+
+ // start the resource stack
+ res = new GfxResources(xref, resDict, NULL);
+
+ // initialize
+ operatorHistory = NULL;
+ builder = builderA;
+ state = new GfxState(72, 72, box, 0, gFalse);
+ clipHistory = new ClipHistoryEntry();
+ setDefaultApproximationPrecision();
+
+ fontChanged = gFalse;
+ clip = clipNone;
+ ignoreUndef = 0;
+ for (i = 0; i < 6; ++i) {
+ baseMatrix[i] = state->getCTM()[i];
+ }
+ formDepth = 0;
+}
+
PdfParser::~PdfParser() {
while (state->hasSaves()) {
restoreState();
if (state) {
delete state;
}
+ if (clipHistory) {
+ delete clipHistory;
+ }
}
void PdfParser::parse(Object *obj, GBool topLevel) {
for (i = 0; i < obj->arrayGetLength(); ++i) {
obj->arrayGet(i, &obj2);
if (!obj2.isStream()) {
- error(-1, "Weird page contents");
+ error(-1, const_cast<char*>("Weird page contents"));
obj2.free();
return;
}
obj2.free();
}
} else if (!obj->isStream()) {
- error(-1, "Weird page contents");
+ error(-1, const_cast<char*>("Weird page contents"));
return;
}
parser = new Parser(xref, new Lexer(xref, obj), gFalse);
Object obj;
Object args[maxArgs];
int numArgs, i;
- int lastAbortCheck;
// scan a sequence of objects
numArgs = 0;
// too many arguments - something is wrong
} else {
- error(getPos(), "Too many args in content stream");
+ error(getPos(), const_cast<char*>("Too many args in content stream"));
if (printCommands) {
printf("throwing away arg: ");
obj.print(stdout);
// args at end with no command
if (numArgs > 0) {
- error(getPos(), "Leftover args in content stream");
+ error(getPos(), const_cast<char*>("Leftover args in content stream"));
if (printCommands) {
printf("%d leftovers:", numArgs);
for (i = 0; i < numArgs; ++i) {
name = cmd->getCmd();
if (!(op = findOp(name))) {
if (ignoreUndef == 0)
- error(getPos(), "Unknown operator '%s'", name);
+ error(getPos(), const_cast<char*>("Unknown operator '%s'"), name);
return;
}
argPtr = args;
if (op->numArgs >= 0) {
if (numArgs < op->numArgs) {
- error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name);
+ error(getPos(), const_cast<char*>("Too few (%d) args to '%s' operator"), numArgs, name);
return;
}
if (numArgs > op->numArgs) {
}
} else {
if (numArgs > -op->numArgs) {
- error(getPos(), "Too many (%d) args to '%s' operator",
+ error(getPos(), const_cast<char*>("Too many (%d) args to '%s' operator"),
numArgs, name);
return;
}
}
for (i = 0; i < numArgs; ++i) {
if (!checkArg(&argPtr[i], op->tchk[i])) {
- error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)",
+ error(getPos(), const_cast<char*>("Arg #%d to '%s' operator is wrong type (%s)"),
i, name, argPtr[i].getTypeName());
return;
}
double a5 = args[5].getNum();
if (!strcmp(prevOp, "q")) {
builder->setTransform(a0, a1, a2, a3, a4, a5);
- } else if (!strcmp(prevOp, "cm")) {
+ } else if (!strcmp(prevOp, "cm") || !strcmp(prevOp, "startPage")) {
// multiply it with the previous transform
double otherMatrix[6];
- if (!builder->getTransform((double*)&otherMatrix)) { // invalid transform
+ if (!builder->getTransform(otherMatrix)) { // invalid transform
// construct identity matrix
otherMatrix[0] = otherMatrix[3] = 1.0;
otherMatrix[1] = otherMatrix[2] = otherMatrix[4] = otherMatrix[5] = 0.0;
}
- double c0 = otherMatrix[0]*a0 + otherMatrix[1]*a2;
- double c1 = otherMatrix[0]*a1 + otherMatrix[1]*a3;
- double c2 = otherMatrix[2]*a0 + otherMatrix[3]*a2;
- double c3 = otherMatrix[2]*a1 + otherMatrix[3]*a3;
- double c4 = otherMatrix[4]*a0 + otherMatrix[5]*a2 + a4;
- double c5 = otherMatrix[4]*a1 + otherMatrix[5]*a3 + a5;
+ double c0 = a0*otherMatrix[0] + a1*otherMatrix[2];
+ double c1 = a0*otherMatrix[1] + a1*otherMatrix[3];
+ double c2 = a2*otherMatrix[0] + a3*otherMatrix[2];
+ double c3 = a2*otherMatrix[1] + a3*otherMatrix[3];
+ double c4 = a4*otherMatrix[0] + a5*otherMatrix[2] + otherMatrix[4];
+ double c5 = a4*otherMatrix[1] + a5*otherMatrix[3] + otherMatrix[5];
builder->setTransform(c0, c1, c2, c3, c4, c5);
} else {
builder->pushGroup();
return;
}
if (!obj1.isDict()) {
- error(getPos(), "ExtGState '%s' is wrong type", args[0].getName());
+ error(getPos(), const_cast<char*>("ExtGState '%s' is wrong type"), args[0].getName());
obj1.free();
return;
}
}
// transparency support: blend mode, fill/stroke opacity
- if (!obj1.dictLookup("BM", &obj2)->isNull()) {
+ if (!obj1.dictLookup(const_cast<char*>("BM"), &obj2)->isNull()) {
if (state->parseBlendMode(&obj2, &mode)) {
state->setBlendMode(mode);
} else {
- error(getPos(), "Invalid blend mode in ExtGState");
+ error(getPos(), const_cast<char*>("Invalid blend mode in ExtGState"));
}
}
obj2.free();
- if (obj1.dictLookup("ca", &obj2)->isNum()) {
+ if (obj1.dictLookup(const_cast<char*>("ca"), &obj2)->isNum()) {
state->setFillOpacity(obj2.getNum());
}
obj2.free();
- if (obj1.dictLookup("CA", &obj2)->isNum()) {
+ if (obj1.dictLookup(const_cast<char*>("CA"), &obj2)->isNum()) {
state->setStrokeOpacity(obj2.getNum());
}
obj2.free();
// fill/stroke overprint
- if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) {
+ if ((haveFillOP = (obj1.dictLookup(const_cast<char*>("op"), &obj2)->isBool()))) {
state->setFillOverprint(obj2.getBool());
}
obj2.free();
- if (obj1.dictLookup("OP", &obj2)->isBool()) {
+ if (obj1.dictLookup(const_cast<char*>("OP"), &obj2)->isBool()) {
state->setStrokeOverprint(obj2.getBool());
if (!haveFillOP) {
state->setFillOverprint(obj2.getBool());
obj2.free();
// stroke adjust
- if (obj1.dictLookup("SA", &obj2)->isBool()) {
+ if (obj1.dictLookup(const_cast<char*>("SA"), &obj2)->isBool()) {
state->setStrokeAdjust(obj2.getBool());
}
obj2.free();
// transfer function
- if (obj1.dictLookup("TR2", &obj2)->isNull()) {
+ if (obj1.dictLookup(const_cast<char*>("TR2"), &obj2)->isNull()) {
obj2.free();
- obj1.dictLookup("TR", &obj2);
+ obj1.dictLookup(const_cast<char*>("TR"), &obj2);
}
- if (obj2.isName("Default") ||
- obj2.isName("Identity")) {
+ if (obj2.isName(const_cast<char*>("Default")) ||
+ obj2.isName(const_cast<char*>("Identity"))) {
funcs[0] = funcs[1] = funcs[2] = funcs[3] = NULL;
state->setTransfer(funcs);
} else if (obj2.isArray() && obj2.arrayGetLength() == 4) {
state->setTransfer(funcs);
}
} else if (!obj2.isNull()) {
- error(getPos(), "Invalid transfer function in ExtGState");
+ error(getPos(), const_cast<char*>("Invalid transfer function in ExtGState"));
}
obj2.free();
// soft mask
- if (!obj1.dictLookup("SMask", &obj2)->isNull()) {
- if (obj2.isName("None")) {
- //out->clearSoftMask(state);
+ if (!obj1.dictLookup(const_cast<char*>("SMask"), &obj2)->isNull()) {
+ if (obj2.isName(const_cast<char*>("None"))) {
+ builder->clearSoftMask(state);
} else if (obj2.isDict()) {
- if (obj2.dictLookup("S", &obj3)->isName("Alpha")) {
+ if (obj2.dictLookup(const_cast<char*>("S"), &obj3)->isName(const_cast<char*>("Alpha"))) {
alpha = gTrue;
} else { // "Luminosity"
alpha = gFalse;
}
obj3.free();
funcs[0] = NULL;
- if (!obj2.dictLookup("TR", &obj3)->isNull()) {
+ if (!obj2.dictLookup(const_cast<char*>("TR"), &obj3)->isNull()) {
funcs[0] = Function::parse(&obj3);
if (funcs[0]->getInputSize() != 1 ||
funcs[0]->getOutputSize() != 1) {
error(getPos(),
- "Invalid transfer function in soft mask in ExtGState");
+ const_cast<char*>("Invalid transfer function in soft mask in ExtGState"));
delete funcs[0];
funcs[0] = NULL;
}
}
obj3.free();
- if ((haveBackdropColor = obj2.dictLookup("BC", &obj3)->isArray())) {
+ if ((haveBackdropColor = obj2.dictLookup(const_cast<char*>("BC"), &obj3)->isArray())) {
for (i = 0; i < gfxColorMaxComps; ++i) {
backdropColor.c[i] = 0;
}
}
}
obj3.free();
- if (obj2.dictLookup("G", &obj3)->isStream()) {
- if (obj3.streamGetDict()->lookup("Group", &obj4)->isDict()) {
+ if (obj2.dictLookup(const_cast<char*>("G"), &obj3)->isStream()) {
+ if (obj3.streamGetDict()->lookup(const_cast<char*>("Group"), &obj4)->isDict()) {
blendingColorSpace = NULL;
isolated = knockout = gFalse;
- if (!obj4.dictLookup("CS", &obj5)->isNull()) {
+ if (!obj4.dictLookup(const_cast<char*>("CS"), &obj5)->isNull()) {
blendingColorSpace = GfxColorSpace::parse(&obj5);
}
obj5.free();
- if (obj4.dictLookup("I", &obj5)->isBool()) {
+ if (obj4.dictLookup(const_cast<char*>("I"), &obj5)->isBool()) {
isolated = obj5.getBool();
}
obj5.free();
- if (obj4.dictLookup("K", &obj5)->isBool()) {
+ if (obj4.dictLookup(const_cast<char*>("K"), &obj5)->isBool()) {
knockout = obj5.getBool();
}
obj5.free();
delete funcs[0];
}
} else {
- error(getPos(), "Invalid soft mask in ExtGState - missing group");
+ error(getPos(), const_cast<char*>("Invalid soft mask in ExtGState - missing group"));
}
obj4.free();
} else {
- error(getPos(), "Invalid soft mask in ExtGState - missing group");
+ error(getPos(), const_cast<char*>("Invalid soft mask in ExtGState - missing group"));
}
obj3.free();
} else if (!obj2.isNull()) {
- error(getPos(), "Invalid soft mask in ExtGState");
+ error(getPos(), const_cast<char*>("Invalid soft mask in ExtGState"));
}
}
obj2.free();
dict = str->streamGetDict();
// check form type
- dict->lookup("FormType", &obj1);
+ dict->lookup(const_cast<char*>("FormType"), &obj1);
if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) {
- error(getPos(), "Unknown form type");
+ error(getPos(), const_cast<char*>("Unknown form type"));
}
obj1.free();
// get bounding box
- dict->lookup("BBox", &obj1);
+ dict->lookup(const_cast<char*>("BBox"), &obj1);
if (!obj1.isArray()) {
obj1.free();
- error(getPos(), "Bad form bounding box");
+ error(getPos(), const_cast<char*>("Bad form bounding box"));
return;
}
for (i = 0; i < 4; ++i) {
obj1.free();
// get matrix
- dict->lookup("Matrix", &obj1);
+ dict->lookup(const_cast<char*>("Matrix"), &obj1);
if (obj1.isArray()) {
for (i = 0; i < 6; ++i) {
obj1.arrayGet(i, &obj2);
obj1.free();
// get resources
- dict->lookup("Resources", &obj1);
+ dict->lookup(const_cast<char*>("Resources"), &obj1);
resDict = obj1.isDict() ? obj1.getDict() : (Dict *)NULL;
// draw it
state->setFillColor(&color);
builder->updateStyle(state);
} else {
- error(getPos(), "Bad color space (fill)");
+ error(getPos(), const_cast<char*>("Bad color space (fill)"));
}
}
state->setStrokeColor(&color);
builder->updateStyle(state);
} else {
- error(getPos(), "Bad color space (stroke)");
+ error(getPos(), const_cast<char*>("Bad color space (stroke)"));
}
}
int i;
if (numArgs != state->getFillColorSpace()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'sc' command");
+ error(getPos(), const_cast<char*>("Incorrect number of arguments in 'sc' command"));
return;
}
state->setFillPattern(NULL);
int i;
if (numArgs != state->getStrokeColorSpace()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'SC' command");
+ error(getPos(), const_cast<char*>("Incorrect number of arguments in 'SC' command"));
return;
}
state->setStrokePattern(NULL);
if (!((GfxPatternColorSpace *)state->getFillColorSpace())->getUnder() ||
numArgs - 1 != ((GfxPatternColorSpace *)state->getFillColorSpace())
->getUnder()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'scn' command");
+ error(getPos(), const_cast<char*>("Incorrect number of arguments in 'scn' command"));
return;
}
for (i = 0; i < numArgs - 1 && i < gfxColorMaxComps; ++i) {
if (args[numArgs-1].isName() &&
(pattern = res->lookupPattern(args[numArgs-1].getName()))) {
state->setFillPattern(pattern);
+ builder->updateStyle(state);
}
} else {
if (numArgs != state->getFillColorSpace()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'scn' command");
+ error(getPos(), const_cast<char*>("Incorrect number of arguments in 'scn' command"));
return;
}
state->setFillPattern(NULL);
->getUnder() ||
numArgs - 1 != ((GfxPatternColorSpace *)state->getStrokeColorSpace())
->getUnder()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'SCN' command");
+ error(getPos(), const_cast<char*>("Incorrect number of arguments in 'SCN' command"));
return;
}
for (i = 0; i < numArgs - 1 && i < gfxColorMaxComps; ++i) {
if (args[numArgs-1].isName() &&
(pattern = res->lookupPattern(args[numArgs-1].getName()))) {
state->setStrokePattern(pattern);
+ builder->updateStyle(state);
}
} else {
if (numArgs != state->getStrokeColorSpace()->getNComps()) {
- error(getPos(), "Incorrect number of arguments in 'SCN' command");
+ error(getPos(), const_cast<char*>("Incorrect number of arguments in 'SCN' command"));
return;
}
state->setStrokePattern(NULL);
void PdfParser::opLineTo(Object args[], int numArgs) {
if (!state->isCurPt()) {
- error(getPos(), "No current point in lineto");
+ error(getPos(), const_cast<char*>("No current point in lineto"));
return;
}
state->lineTo(args[0].getNum(), args[1].getNum());
double x1, y1, x2, y2, x3, y3;
if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto");
+ error(getPos(), const_cast<char*>("No current point in curveto"));
return;
}
x1 = args[0].getNum();
double x1, y1, x2, y2, x3, y3;
if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto1");
+ error(getPos(), const_cast<char*>("No current point in curveto1"));
return;
}
x1 = state->getCurX();
double x1, y1, x2, y2, x3, y3;
if (!state->isCurPt()) {
- error(getPos(), "No current point in curveto2");
+ error(getPos(), const_cast<char*>("No current point in curveto2"));
return;
}
x1 = args[0].getNum();
void PdfParser::opClosePath(Object args[], int numArgs) {
if (!state->isCurPt()) {
- error(getPos(), "No current point in closepath");
+ error(getPos(), const_cast<char*>("No current point in closepath"));
return;
}
state->closePath();
void PdfParser::opStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in stroke");
+ //error(getPos(), const_cast<char*>("No path in stroke"));
return;
}
if (state->isPath()) {
void PdfParser::opCloseStroke(Object * /*args[]*/, int /*numArgs*/) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/stroke");
+ //error(getPos(), const_cast<char*>("No path in closepath/stroke"));
return;
}
state->closePath();
void PdfParser::opFill(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in fill");
+ //error(getPos(), const_cast<char*>("No path in fill"));
return;
}
if (state->isPath()) {
void PdfParser::opEOFill(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in eofill");
+ //error(getPos(), const_cast<char*>("No path in eofill"));
return;
}
if (state->isPath()) {
void PdfParser::opFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in fill/stroke");
+ //error(getPos(), const_cast<char*>("No path in fill/stroke"));
return;
}
if (state->isPath()) {
void PdfParser::opCloseFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/fill/stroke");
+ //error(getPos(), const_cast<char*>("No path in closepath/fill/stroke"));
return;
}
if (state->isPath()) {
void PdfParser::opEOFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in eofill/stroke");
+ //error(getPos(), const_cast<char*>("No path in eofill/stroke"));
return;
}
if (state->isPath()) {
void PdfParser::opCloseEOFillStroke(Object args[], int numArgs) {
if (!state->isCurPt()) {
- //error(getPos(), "No path in closepath/eofill/stroke");
+ //error(getPos(), const_cast<char*>("No path in closepath/eofill/stroke"));
return;
}
if (state->isPath()) {
doShadingPatternFillFallback((GfxShadingPattern *)pattern, gFalse, eoFill);
break;
default:
- error(getPos(), "Unimplemented pattern type (%d) in fill",
+ error(getPos(), const_cast<char*>("Unimplemented pattern type (%d) in fill"),
pattern->getType());
break;
}
doShadingPatternFillFallback((GfxShadingPattern *)pattern, gTrue, gFalse);
break;
default:
- error(getPos(), "Unimplemented pattern type (%d) in stroke",
+ error(getPos(), const_cast<char*>("Unimplemented pattern type (%d) in stroke"),
pattern->getType());
break;
}
} else {
state->clip();
if (eoFill) {
- builder->clip(state, true);
+ builder->setClipPath(state, true);
} else {
- builder->clip(state);
+ builder->setClipPath(state);
}
}
void PdfParser::opShFill(Object args[], int numArgs) {
GfxShading *shading;
- GfxPath *savedPath;
+ GfxPath *savedPath = NULL;
double xMin, yMin, xMax, yMax;
+ double gradientTransform[6];
+ double *matrix = NULL;
+ GBool savedState = gFalse;
if (!(shading = res->lookupShading(args[0].getName()))) {
return;
}
// save current graphics state
- savedPath = state->getPath()->copy();
- saveState();
+ if (shading->getType() != 2 && shading->getType() != 3) {
+ savedPath = state->getPath()->copy();
+ saveState();
+ savedState = gTrue;
+ } else { // get gradient transform if possible
+ // check proper operator sequence
+ // first there should be one W(*) and then one 'cm' somewhere before 'sh'
+ GBool seenClip, seenConcat;
+ seenClip = (clipHistory->getClipPath() != NULL);
+ seenConcat = gFalse;
+ int i = 1;
+ while (i <= maxOperatorHistoryDepth) {
+ const char *opName = getPreviousOperator(i);
+ if (!strcmp(opName, "cm")) {
+ if (seenConcat) { // more than one 'cm'
+ break;
+ } else {
+ seenConcat = gTrue;
+ }
+ }
+ i++;
+ }
+
+ if (seenConcat && seenClip) {
+ if (builder->getTransform(gradientTransform)) {
+ matrix = (double*)&gradientTransform;
+ builder->setTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); // remove transform
+ }
+ }
+ }
// clip to bbox
if (shading->getHasBBox()) {
state->lineTo(xMin, yMax);
state->closePath();
state->clip();
- builder->clip(state);
+ if (savedState)
+ builder->setClipPath(state);
+ else
+ builder->clip(state);
state->clearPath();
}
// set the color space
- state->setFillColorSpace(shading->getColorSpace()->copy());
+ if (savedState)
+ state->setFillColorSpace(shading->getColorSpace()->copy());
// do shading type-specific operations
switch (shading->getType()) {
break;
case 2:
case 3:
- // no need to implement these
+ if (clipHistory->getClipPath()) {
+ builder->addShadedFill(shading, matrix, clipHistory->getClipPath(),
+ clipHistory->getClipType() == clipEO ? true : false);
+ }
break;
case 4:
case 5:
}
// restore graphics state
- restoreState();
- state->setPath(savedPath);
+ if (savedState) {
+ restoreState();
+ state->setPath(savedPath);
+ }
delete shading;
}
GfxColor fillColor;
GfxColor color0M, color1M, colorM0, colorM1, colorMM;
GfxColor colors2[4];
+ double functionColorDelta = colorDeltas[pdfFunctionShading-1];
double *matrix;
double xM, yM;
int nComps, i, j;
// -- fill the rectangle; but require at least one subdivision
// (depth==0) to avoid problems when the four outer corners of the
// shaded region are the same color
- if ((i == 4 && depth > 0) || depth == functionMaxDepth) {
+ if ((i == 4 && depth > 0) || depth == maxDepths[pdfFunctionShading-1]) {
// use the center color
shading->getColor(xM, yM, &fillColor);
double x2, double y2, GfxColor *color2,
int nComps, int depth) {
double x01, y01, x12, y12, x20, y20;
+ double gouraudColorDelta = colorDeltas[pdfGouraudTriangleShading-1];
GfxColor color01, color12, color20;
int i;
for (i = 0; i < nComps; ++i) {
if (abs(color0->c[i] - color1->c[i]) > gouraudColorDelta ||
- abs(color1->c[i] - color2->c[i]) > gouraudColorDelta) {
+ abs(color1->c[i] - color2->c[i]) > gouraudColorDelta) {
break;
}
}
- if (i == nComps || depth == gouraudMaxDepth) {
+ if (i == nComps || depth == maxDepths[pdfGouraudTriangleShading-1]) {
state->setFillColor(color0);
state->moveTo(x0, y0);
state->lineTo(x1, y1);
GfxPatch patch00, patch01, patch10, patch11;
double xx[4][8], yy[4][8];
double xxm, yym;
+ double patchColorDelta = colorDeltas[pdfPatchMeshShading-1];
int i;
for (i = 0; i < nComps; ++i) {
break;
}
}
- if (i == nComps || depth == patchMaxDepth) {
+ if (i == nComps || depth == maxDepths[pdfPatchMeshShading-1]) {
state->setFillColor(&patch->color[0][0]);
state->moveTo(patch->x[0][0], patch->y[0][0]);
state->curveTo(patch->x[0][1], patch->y[0][1],
if (state->isCurPt() && clip != clipNone) {
state->clip();
if (clip == clipNormal) {
+ clipHistory->setClip(state->getPath(), clipNormal);
builder->clip(state);
} else {
+ clipHistory->setClip(state->getPath(), clipEO);
builder->clip(state, true);
}
}
void PdfParser::opBeginText(Object args[], int numArgs) {
state->setTextMat(1, 0, 0, 1, 0, 0);
state->textMoveTo(0, 0);
+ builder->updateTextPosition(0.0, 0.0);
fontChanged = gTrue;
builder->beginTextObject(state);
}
GfxFont *font;
if (!(font = res->lookupFont(args[0].getName()))) {
+ // unsetting the font (drawing no text) is better than using the
+ // previous one and drawing random glyphs from it
+ state->setFont(NULL, args[1].getNum());
+ fontChanged = gTrue;
return;
}
if (printCommands) {
void PdfParser::opSetHorizScaling(Object args[], int numArgs) {
state->setHorizScaling(args[0].getNum());
+ builder->updateTextMatrix(state);
fontChanged = gTrue;
}
tx = state->getLineX() + args[0].getNum();
ty = state->getLineY() + args[1].getNum();
state->textMoveTo(tx, ty);
+ builder->updateTextPosition(tx, ty);
}
void PdfParser::opTextMoveSet(Object args[], int numArgs) {
state->setLeading(-ty);
ty += state->getLineY();
state->textMoveTo(tx, ty);
+ builder->updateTextPosition(tx, ty);
}
void PdfParser::opSetTextMatrix(Object args[], int numArgs) {
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
state->textMoveTo(0, 0);
+ builder->updateTextMatrix(state);
+ builder->updateTextPosition(0.0, 0.0);
fontChanged = gTrue;
}
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
+ builder->updateTextPosition(tx, ty);
}
//------------------------------------------------------------------------
void PdfParser::opShowText(Object args[], int numArgs) {
if (!state->getFont()) {
- error(getPos(), "No font in show");
+ error(getPos(), const_cast<char*>("No font in show"));
return;
}
if (fontChanged) {
double tx, ty;
if (!state->getFont()) {
- error(getPos(), "No font in move/show");
+ error(getPos(), const_cast<char*>("No font in move/show"));
return;
}
if (fontChanged) {
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
+ builder->updateTextPosition(tx, ty);
doShowText(args[0].getString());
}
double tx, ty;
if (!state->getFont()) {
- error(getPos(), "No font in move/set/show");
+ error(getPos(), const_cast<char*>("No font in move/set/show"));
return;
}
if (fontChanged) {
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
+ builder->updateTextPosition(tx, ty);
doShowText(args[2].getString());
}
int i;
if (!state->getFont()) {
- error(getPos(), "No font in show/space");
+ error(getPos(), const_cast<char*>("No font in show/space"));
return;
}
if (fontChanged) {
state->textShift(-obj.getNum() * 0.001 *
fabs(state->getFontSize()), 0);
}
+ builder->updateTextShift(state, obj.getNum());
} else if (obj.isString()) {
doShowText(obj.getString());
} else {
- error(getPos(), "Element of show/space array must be number or string");
+ error(getPos(), const_cast<char*>("Element of show/space array must be number or string"));
}
obj.free();
}
}
+
+
+/*
+ * The `POPPLER_NEW_GFXFONT' stuff is for the change to GfxFont's getNextChar() call.
+ * Thanks to tsdgeos for the fix.
+ * Miklos, does this look ok?
+ */
+
void PdfParser::doShowText(GooString *s) {
GfxFont *font;
int wMode;
double riseX, riseY;
CharCode code;
+#ifdef POPPLER_NEW_GFXFONT
+ Unicode *u = NULL;
+#else
Unicode u[8];
- double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY;
+#endif
+ double x, y, dx, dy, curX, curY, tdx, tdy, lineX, lineY;
double originX, originY, tOriginX, tOriginY;
double oldCTM[6], newCTM[6];
double *mat;
Dict *resDict;
Parser *oldParser;
char *p;
- int len, n, uLen, nChars, nSpaces, i;
+ int len, n, uLen, i;
font = state->getFont();
wMode = font->getWMode();
len = s->getLength();
while (len > 0) {
n = font->getNextChar(p, len, &code,
+#ifdef POPPLER_NEW_GFXFONT
+ &u, &uLen, /* TODO: This looks like a memory leak for u. */
+#else
u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
+#endif
&dx, &dy, &originX, &originY);
dx = dx * state->getFontSize() + state->getCharSpace();
if (n == 1 && *p == ' ') {
if (charProc.isStream()) {
//parse(&charProc, gFalse); // TODO: parse into SVG font
} else {
- error(getPos(), "Missing or bad Type3 CharProc entry");
+ error(getPos(), const_cast<char*>("Missing or bad Type3 CharProc entry"));
}
//out->endType3Char(state);
if (resDict) {
len = s->getLength();
while (len > 0) {
n = font->getNextChar(p, len, &code,
+#ifdef POPPLER_NEW_GFXFONT
+ &u, &uLen, /* TODO: This looks like a memory leak for u. */
+#else
u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
+#endif
&dx, &dy, &originX, &originY);
if (wMode) {
originY *= state->getFontSize();
state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
builder->addChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
- tdx, tdy, tOriginX, tOriginY, code, n, u, uLen);
+ dx, dy, tOriginX, tOriginY, code, n, u, uLen);
state->shift(tdx, tdy);
p += n;
len -= n;
builder->endString(state);
}
+
//------------------------------------------------------------------------
// XObject operators
//------------------------------------------------------------------------
return;
}
if (!obj1.isStream()) {
- error(getPos(), "XObject '%s' is wrong type", name);
+ error(getPos(), const_cast<char*>("XObject '%s' is wrong type"), name);
obj1.free();
return;
}
- obj1.streamGetDict()->lookup("Subtype", &obj2);
- if (obj2.isName("Image")) {
+ obj1.streamGetDict()->lookup(const_cast<char*>("Subtype"), &obj2);
+ if (obj2.isName(const_cast<char*>("Image"))) {
res->lookupXObjectNF(name, &refObj);
doImage(&refObj, obj1.getStream(), gFalse);
refObj.free();
- } else if (obj2.isName("Form")) {
+ } else if (obj2.isName(const_cast<char*>("Form"))) {
doForm(&obj1);
- } else if (obj2.isName("PS")) {
- obj1.streamGetDict()->lookup("Level1", &obj3);
+ } else if (obj2.isName(const_cast<char*>("PS"))) {
+ obj1.streamGetDict()->lookup(const_cast<char*>("Level1"), &obj3);
/* out->psXObject(obj1.getStream(),
obj3.isStream() ? obj3.getStream() : (Stream *)NULL);*/
} else if (obj2.isName()) {
- error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
+ error(getPos(), const_cast<char*>("Unknown XObject subtype '%s'"), obj2.getName());
} else {
- error(getPos(), "XObject subtype is missing or wrong type");
+ error(getPos(), const_cast<char*>("XObject subtype is missing or wrong type"));
}
obj2.free();
obj1.free();
dict = str->getDict();
// get size
- dict->lookup("Width", &obj1);
+ dict->lookup(const_cast<char*>("Width"), &obj1);
if (obj1.isNull()) {
obj1.free();
- dict->lookup("W", &obj1);
+ dict->lookup(const_cast<char*>("W"), &obj1);
}
if (obj1.isInt())
width = obj1.getInt();
else
goto err2;
obj1.free();
- dict->lookup("Height", &obj1);
+ dict->lookup(const_cast<char*>("Height"), &obj1);
if (obj1.isNull()) {
obj1.free();
- dict->lookup("H", &obj1);
+ dict->lookup(const_cast<char*>("H"), &obj1);
}
if (obj1.isInt())
height = obj1.getInt();
obj1.free();
// image or mask?
- dict->lookup("ImageMask", &obj1);
+ dict->lookup(const_cast<char*>("ImageMask"), &obj1);
if (obj1.isNull()) {
obj1.free();
- dict->lookup("IM", &obj1);
+ dict->lookup(const_cast<char*>("IM"), &obj1);
}
mask = gFalse;
if (obj1.isBool())
// bit depth
if (bits == 0) {
- dict->lookup("BitsPerComponent", &obj1);
+ dict->lookup(const_cast<char*>("BitsPerComponent"), &obj1);
if (obj1.isNull()) {
obj1.free();
- dict->lookup("BPC", &obj1);
+ dict->lookup(const_cast<char*>("BPC"), &obj1);
}
if (obj1.isInt()) {
bits = obj1.getInt();
if (bits != 1)
goto err1;
invert = gFalse;
- dict->lookup("Decode", &obj1);
+ dict->lookup(const_cast<char*>("Decode"), &obj1);
if (obj1.isNull()) {
obj1.free();
- dict->lookup("D", &obj1);
+ dict->lookup(const_cast<char*>("D"), &obj1);
}
if (obj1.isArray()) {
obj1.arrayGet(0, &obj2);
obj1.free();
// draw it
- //out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
+ builder->addImageMask(state, str, width, height, invert);
} else {
// get color space and color map
- dict->lookup("ColorSpace", &obj1);
+ dict->lookup(const_cast<char*>("ColorSpace"), &obj1);
if (obj1.isNull()) {
obj1.free();
- dict->lookup("CS", &obj1);
+ dict->lookup(const_cast<char*>("CS"), &obj1);
}
if (obj1.isName()) {
res->lookupColorSpace(obj1.getName(), &obj2);
if (!colorSpace) {
goto err1;
}
- dict->lookup("Decode", &obj1);
+ dict->lookup(const_cast<char*>("Decode"), &obj1);
if (obj1.isNull()) {
obj1.free();
- dict->lookup("D", &obj1);
+ dict->lookup(const_cast<char*>("D"), &obj1);
}
colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
obj1.free();
maskWidth = maskHeight = 0; // make gcc happy
maskInvert = gFalse; // make gcc happy
maskColorMap = NULL; // make gcc happy
- dict->lookup("Mask", &maskObj);
- dict->lookup("SMask", &smaskObj);
+ dict->lookup(const_cast<char*>("Mask"), &maskObj);
+ dict->lookup(const_cast<char*>("SMask"), &smaskObj);
if (smaskObj.isStream()) {
// soft mask
if (inlineImg) {
}
maskStr = smaskObj.getStream();
maskDict = smaskObj.streamGetDict();
- maskDict->lookup("Width", &obj1);
+ maskDict->lookup(const_cast<char*>("Width"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("W", &obj1);
+ maskDict->lookup(const_cast<char*>("W"), &obj1);
}
if (!obj1.isInt()) {
goto err2;
}
maskWidth = obj1.getInt();
obj1.free();
- maskDict->lookup("Height", &obj1);
+ maskDict->lookup(const_cast<char*>("Height"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("H", &obj1);
+ maskDict->lookup(const_cast<char*>("H"), &obj1);
}
if (!obj1.isInt()) {
goto err2;
}
maskHeight = obj1.getInt();
obj1.free();
- maskDict->lookup("BitsPerComponent", &obj1);
+ maskDict->lookup(const_cast<char*>("BitsPerComponent"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("BPC", &obj1);
+ maskDict->lookup(const_cast<char*>("BPC"), &obj1);
}
if (!obj1.isInt()) {
goto err2;
}
maskBits = obj1.getInt();
obj1.free();
- maskDict->lookup("ColorSpace", &obj1);
+ maskDict->lookup(const_cast<char*>("ColorSpace"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("CS", &obj1);
+ maskDict->lookup(const_cast<char*>("CS"), &obj1);
}
if (obj1.isName()) {
res->lookupColorSpace(obj1.getName(), &obj2);
if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) {
goto err1;
}
- maskDict->lookup("Decode", &obj1);
+ maskDict->lookup(const_cast<char*>("Decode"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("D", &obj1);
+ maskDict->lookup(const_cast<char*>("D"), &obj1);
}
maskColorMap = new GfxImageColorMap(maskBits, &obj1, maskColorSpace);
obj1.free();
}
maskStr = maskObj.getStream();
maskDict = maskObj.streamGetDict();
- maskDict->lookup("Width", &obj1);
+ maskDict->lookup(const_cast<char*>("Width"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("W", &obj1);
+ maskDict->lookup(const_cast<char*>("W"), &obj1);
}
if (!obj1.isInt()) {
goto err2;
}
maskWidth = obj1.getInt();
obj1.free();
- maskDict->lookup("Height", &obj1);
+ maskDict->lookup(const_cast<char*>("Height"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("H", &obj1);
+ maskDict->lookup(const_cast<char*>("H"), &obj1);
}
if (!obj1.isInt()) {
goto err2;
}
maskHeight = obj1.getInt();
obj1.free();
- maskDict->lookup("ImageMask", &obj1);
+ maskDict->lookup(const_cast<char*>("ImageMask"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("IM", &obj1);
+ maskDict->lookup(const_cast<char*>("IM"), &obj1);
}
if (!obj1.isBool() || !obj1.getBool()) {
goto err2;
}
obj1.free();
maskInvert = gFalse;
- maskDict->lookup("Decode", &obj1);
+ maskDict->lookup(const_cast<char*>("Decode"), &obj1);
if (obj1.isNull()) {
obj1.free();
- maskDict->lookup("D", &obj1);
+ maskDict->lookup(const_cast<char*>("D"), &obj1);
}
if (obj1.isArray()) {
obj1.arrayGet(0, &obj2);
// draw it
if (haveSoftMask) {
-/* out->drawSoftMaskedImage(state, ref, str, width, height, colorMap,
- maskStr, maskWidth, maskHeight, maskColorMap);*/
+ builder->addSoftMaskedImage(state, str, width, height, colorMap,
+ maskStr, maskWidth, maskHeight, maskColorMap);
delete maskColorMap;
} else if (haveExplicitMask) {
-/* out->drawMaskedImage(state, ref, str, width, height, colorMap,
- maskStr, maskWidth, maskHeight, maskInvert);*/
+ builder->addMaskedImage(state, str, width, height, colorMap,
+ maskStr, maskWidth, maskHeight, maskInvert);
} else {
builder->addImage(state, str, width, height, colorMap,
haveColorKeyMask ? maskColors : (int *)NULL);
err2:
obj1.free();
err1:
- error(getPos(), "Bad image parameters");
+ error(getPos(), const_cast<char*>("Bad image parameters"));
}
void PdfParser::doForm(Object *str) {
dict = str->streamGetDict();
// check form type
- dict->lookup("FormType", &obj1);
+ dict->lookup(const_cast<char*>("FormType"), &obj1);
if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) {
- error(getPos(), "Unknown form type");
+ error(getPos(), const_cast<char*>("Unknown form type"));
}
obj1.free();
// get bounding box
- dict->lookup("BBox", &bboxObj);
+ dict->lookup(const_cast<char*>("BBox"), &bboxObj);
if (!bboxObj.isArray()) {
bboxObj.free();
- error(getPos(), "Bad form bounding box");
+ error(getPos(), const_cast<char*>("Bad form bounding box"));
return;
}
for (i = 0; i < 4; ++i) {
bboxObj.free();
// get matrix
- dict->lookup("Matrix", &matrixObj);
+ dict->lookup(const_cast<char*>("Matrix"), &matrixObj);
if (matrixObj.isArray()) {
for (i = 0; i < 6; ++i) {
matrixObj.arrayGet(i, &obj1);
matrixObj.free();
// get resources
- dict->lookup("Resources", &resObj);
+ dict->lookup(const_cast<char*>("Resources"), &resObj);
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 (dict->lookup(const_cast<char*>("Group"), &obj1)->isDict()) {
+ if (obj1.dictLookup(const_cast<char*>("S"), &obj2)->isName(const_cast<char*>("Transparency"))) {
transpGroup = gTrue;
- if (!obj1.dictLookup("CS", &obj3)->isNull()) {
+ if (!obj1.dictLookup(const_cast<char*>("CS"), &obj3)->isNull()) {
blendingColorSpace = GfxColorSpace::parse(&obj3);
}
obj3.free();
- if (obj1.dictLookup("I", &obj3)->isBool()) {
+ if (obj1.dictLookup(const_cast<char*>("I"), &obj3)->isBool()) {
isolated = obj3.getBool();
}
obj3.free();
- if (obj1.dictLookup("K", &obj3)->isBool()) {
+ if (obj1.dictLookup(const_cast<char*>("K"), &obj3)->isBool()) {
knockout = obj3.getBool();
}
obj3.free();
@@ -2723,6 +2814,12 @@ void PdfParser::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox
// kill any pre-existing path
state->clearPath();
+ if (softMask || transpGroup) {
+ builder->clearSoftMask(state);
+ builder->pushTransparencyGroup(state, bbox, blendingColorSpace,
+ isolated, knockout, softMask);
+ }
+
// save current parser
oldParser = parser;
@@ -2739,6 +2836,7 @@ void PdfParser::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox
state->lineTo(bbox[0], bbox[3]);
state->closePath();
state->clip();
+ clipHistory->setClip(state->getPath());
builder->clip(state);
state->clearPath();
@@ -2747,14 +2845,12 @@ void PdfParser::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox
state->setBlendMode(gfxBlendNormal);
}
if (state->getFillOpacity() != 1) {
+ builder->setGroupOpacity(state->getFillOpacity());
state->setFillOpacity(1);
}
if (state->getStrokeOpacity() != 1) {
state->setStrokeOpacity(1);
}
- //out->clearSoftMask(state);
- //out->beginTransparencyGroup(state, bbox, blendingColorSpace,
- // isolated, knockout, softMask);
}
// set new base matrix
@@ -2766,10 +2862,6 @@ void PdfParser::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox
// draw the form
parse(str, gFalse);
- if (softMask || transpGroup) {
- //out->endTransparencyGroup(state);
- }
-
// restore base matrix
for (i = 0; i < 6; ++i) {
baseMatrix[i] = oldBaseMatrix[i];
@@ -2778,6 +2870,10 @@ void PdfParser::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox
// restore parser
parser = oldParser;
+ if (softMask || transpGroup) {
+ builder->popTransparencyGroup(state);
+ }
+
// restore graphics state
restoreState();
@@ -2785,9 +2881,9 @@ void PdfParser::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox
popResources();
if (softMask) {
- //out->setSoftMask(state, bbox, alpha, transferFunc, backdropColor);
+ builder->setSoftMask(state, bbox, alpha, transferFunc, backdropColor);
} else if (transpGroup) {
- //out->paintTransparencyGroup(state, bbox);
+ builder->paintTransparencyGroup(state, bbox);
}
return;
// build dictionary
dict.initDict(xref);
parser->getObj(&obj);
- while (!obj.isCmd("ID") && !obj.isEOF()) {
+ while (!obj.isCmd(const_cast<char*>("ID")) && !obj.isEOF()) {
if (!obj.isName()) {
- error(getPos(), "Inline image dictionary key must be a name object");
+ error(getPos(), const_cast<char*>("Inline image dictionary key must be a name object"));
obj.free();
} else {
key = copyString(obj.getName());
parser->getObj(&obj);
}
if (obj.isEOF()) {
- error(getPos(), "End of file in inline image");
+ error(getPos(), const_cast<char*>("End of file in inline image"));
obj.free();
dict.free();
return NULL;
}
void PdfParser::opImageData(Object args[], int numArgs) {
- error(getPos(), "Internal: got 'ID' operator");
+ error(getPos(), const_cast<char*>("Internal: got 'ID' operator"));
}
void PdfParser::opEndImage(Object args[], int numArgs) {
- error(getPos(), "Internal: got 'EI' operator");
+ error(getPos(), const_cast<char*>("Internal: got 'EI' operator"));
}
//------------------------------------------------------------------------
void PdfParser::saveState() {
builder->saveState();
state = state->save();
+ clipHistory = clipHistory->save();
}
void PdfParser::restoreState() {
+ clipHistory = clipHistory->restore();
state = state->restore();
builder->restoreState();
}
res = resPtr;
}
+void PdfParser::setDefaultApproximationPrecision() {
+ int i;
+
+ for (i = 1; i <= pdfNumShadingTypes; ++i) {
+ setApproximationPrecision(i, defaultShadingColorDelta, defaultShadingMaxDepth);
+ }
+}
+
+void PdfParser::setApproximationPrecision(int shadingType, double colorDelta,
+ int maxDepth) {
+
+ if (shadingType > pdfNumShadingTypes || shadingType < 1) {
+ return;
+ }
+ colorDeltas[shadingType-1] = dblToCol(colorDelta);
+ maxDepths[shadingType-1] = maxDepth;
+}
+
+//------------------------------------------------------------------------
+// ClipHistoryEntry
+//------------------------------------------------------------------------
+
+ClipHistoryEntry::ClipHistoryEntry(GfxPath *clipPathA, GfxClipType clipTypeA) {
+ if (clipPathA) {
+ clipPath = clipPathA->copy();
+ } else {
+ clipPath = NULL;
+ }
+ clipType = clipTypeA;
+ saved = NULL;
+}
+
+ClipHistoryEntry::~ClipHistoryEntry() {
+ if (clipPath) {
+ delete clipPath;
+ }
+}
+
+void ClipHistoryEntry::setClip(GfxPath *clipPathA, GfxClipType clipTypeA) {
+ // Free previous clip path
+ if (clipPath) {
+ delete clipPath;
+ }
+ if (clipPathA) {
+ clipPath = clipPathA->copy();
+ clipType = clipTypeA;
+ } else {
+ clipPath = NULL;
+ }
+}
+
+ClipHistoryEntry *ClipHistoryEntry::save() {
+ ClipHistoryEntry *newEntry = new ClipHistoryEntry(this);
+ newEntry->saved = this;
+
+ return newEntry;
+}
+
+ClipHistoryEntry *ClipHistoryEntry::restore() {
+ ClipHistoryEntry *oldEntry;
+
+ if (saved) {
+ oldEntry = saved;
+ saved = NULL;
+ delete this;
+ } else {
+ oldEntry = this;
+ }
+
+ return oldEntry;
+}
+
+ClipHistoryEntry::ClipHistoryEntry(ClipHistoryEntry *other) {
+ if (other->clipPath) {
+ this->clipPath = other->clipPath->copy();
+ this->clipType = other->clipType;
+ } else {
+ this->clipPath = NULL;
+ }
+ saved = NULL;
+}
+
#endif /* HAVE_POPPLER */