Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/pdf/xpdf/GfxState.cc
diff options
context:
space:
mode:
authorMartin Kretzschmar <mkretzschmar@src.gnome.org>2002-09-18 22:20:42 (GMT)
committer Martin Kretzschmar <mkretzschmar@src.gnome.org>2002-09-18 22:20:42 (GMT)
commit2a393c134fe3fe8eb85bf818cb7ad6ae4396322a (patch)
treeeba8b0dcaba42d799ed8313faee15fb74a5a0cd2 /pdf/xpdf/GfxState.cc
parent7aac8dc8533347e21311b15186e0af82f1b22fd6 (diff)
Synched with Xpdf 1.01
Diffstat (limited to 'pdf/xpdf/GfxState.cc')
-rw-r--r--pdf/xpdf/GfxState.cc1015
1 files changed, 532 insertions, 483 deletions
diff --git a/pdf/xpdf/GfxState.cc b/pdf/xpdf/GfxState.cc
index 1abf9a5..1668c24 100644
--- a/pdf/xpdf/GfxState.cc
+++ b/pdf/xpdf/GfxState.cc
@@ -2,7 +2,7 @@
//
// GfxState.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
@@ -10,6 +10,7 @@
#pragma implementation
#endif
+#include <aconf.h>
#include <stddef.h>
#include <math.h>
#include <string.h> // for memcpy()
@@ -17,6 +18,7 @@
#include "Error.h"
#include "Object.h"
#include "Array.h"
+#include "Page.h"
#include "GfxState.h"
//------------------------------------------------------------------------
@@ -261,9 +263,9 @@ GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
whiteX = whiteY = whiteZ = 1;
blackX = blackY = blackZ = 0;
gammaR = gammaG = gammaB = 1;
- m[0] = 1; m[1] = 0; m[2] = 0;
- m[3] = 0; m[4] = 1; m[5] = 0;
- m[6] = 0; m[7] = 0; m[8] = 1;
+ mat[0] = 1; mat[1] = 0; mat[2] = 0;
+ mat[3] = 0; mat[4] = 1; mat[5] = 0;
+ mat[6] = 0; mat[7] = 0; mat[8] = 1;
}
GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
@@ -284,7 +286,7 @@ GfxColorSpace *GfxCalRGBColorSpace::copy() {
cs->gammaG = gammaG;
cs->gammaB = gammaB;
for (i = 0; i < 9; ++i) {
- cs->m[i] = m[i];
+ cs->mat[i] = mat[i];
}
return cs;
}
@@ -344,7 +346,7 @@ GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
obj2.arrayGetLength() == 9) {
for (i = 0; i < 9; ++i) {
obj2.arrayGet(i, &obj3);
- cs->m[i] = obj3.getNum();
+ cs->mat[i] = obj3.getNum();
obj3.free();
}
}
@@ -406,9 +408,22 @@ void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, double *gray) {
}
void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- rgb->r = clip01(1 - (color->c[0] + color->c[3]));
- rgb->g = clip01(1 - (color->c[1] + color->c[3]));
- rgb->b = clip01(1 - (color->c[2] + color->c[3]));
+ double c, m, y, aw, ac, am, ay, ar, ag, ab;
+
+ c = clip01(color->c[0] + color->c[3]);
+ m = clip01(color->c[1] + color->c[3]);
+ y = clip01(color->c[2] + color->c[3]);
+ aw = (1-c) * (1-m) * (1-y);
+ ac = c * (1-m) * (1-y);
+ am = (1-c) * m * (1-y);
+ ay = (1-c) * (1-m) * y;
+ ar = (1-c) * m * y;
+ ag = c * (1-m) * y;
+ ab = c * m * (1-y);
+ rgb->r = clip01(aw + 0.9137*am + 0.9961*ay + 0.9882*ar);
+ rgb->g = clip01(aw + 0.6196*ac + ay + 0.5176*ag);
+ rgb->b = clip01(aw + 0.7804*ac + 0.5412*am + 0.0667*ar + 0.2118*ag +
+ 0.4863*ab);
}
void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
@@ -609,11 +624,11 @@ void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
// GfxICCBasedColorSpace
//------------------------------------------------------------------------
-GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nComps, GfxColorSpace *alt,
- Ref *iccProfileStream) {
- this->nComps = nComps;
- this->alt = alt;
- this->iccProfileStream = *iccProfileStream;
+GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
+ Ref *iccProfileStreamA) {
+ nComps = nCompsA;
+ alt = altA;
+ iccProfileStream = *iccProfileStreamA;
rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
}
@@ -636,19 +651,19 @@ GfxColorSpace *GfxICCBasedColorSpace::copy() {
GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
GfxICCBasedColorSpace *cs;
- Ref iccProfileStream;
- int nComps;
- GfxColorSpace *alt;
+ Ref iccProfileStreamA;
+ int nCompsA;
+ GfxColorSpace *altA;
Dict *dict;
Object obj1, obj2, obj3;
int i;
arr->getNF(1, &obj1);
if (obj1.isRef()) {
- iccProfileStream = obj1.getRef();
+ iccProfileStreamA = obj1.getRef();
} else {
- iccProfileStream.num = 0;
- iccProfileStream.gen = 0;
+ iccProfileStreamA.num = 0;
+ iccProfileStreamA.gen = 0;
}
obj1.free();
arr->get(1, &obj1);
@@ -664,19 +679,19 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
obj1.free();
return NULL;
}
- nComps = obj2.getInt();
+ nCompsA = obj2.getInt();
obj2.free();
if (dict->lookup("Alternate", &obj2)->isNull() ||
- !(alt = GfxColorSpace::parse(&obj2))) {
- switch (nComps) {
+ !(altA = GfxColorSpace::parse(&obj2))) {
+ switch (nCompsA) {
case 1:
- alt = new GfxDeviceGrayColorSpace();
+ altA = new GfxDeviceGrayColorSpace();
break;
case 3:
- alt = new GfxDeviceRGBColorSpace();
+ altA = new GfxDeviceRGBColorSpace();
break;
case 4:
- alt = new GfxDeviceCMYKColorSpace();
+ altA = new GfxDeviceCMYKColorSpace();
break;
default:
error(-1, "Bad ICCBased color space - invalid N");
@@ -686,10 +701,10 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
}
}
obj2.free();
- cs = new GfxICCBasedColorSpace(nComps, alt, &iccProfileStream);
+ cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
if (dict->lookup("Range", &obj2)->isArray() &&
- obj2.arrayGetLength() == 2 * nComps) {
- for (i = 0; i < nComps; ++i) {
+ obj2.arrayGetLength() == 2 * nCompsA) {
+ for (i = 0; i < nCompsA; ++i) {
obj2.arrayGet(2*i, &obj3);
cs->rangeMin[i] = obj3.getNum();
obj3.free();
@@ -730,12 +745,12 @@ void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
// GfxIndexedColorSpace
//------------------------------------------------------------------------
-GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *base,
- int indexHigh) {
- this->base = base;
- this->indexHigh = indexHigh;
- this->lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
- sizeof(Guchar));
+GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
+ int indexHighA) {
+ base = baseA;
+ indexHigh = indexHighA;
+ lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
+ sizeof(Guchar));
}
GfxIndexedColorSpace::~GfxIndexedColorSpace() {
@@ -754,8 +769,8 @@ GfxColorSpace *GfxIndexedColorSpace::copy() {
GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
GfxIndexedColorSpace *cs;
- GfxColorSpace *base;
- int indexHigh;
+ GfxColorSpace *baseA;
+ int indexHighA;
Object obj1;
int x;
char *s;
@@ -766,7 +781,7 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
goto err1;
}
arr->get(1, &obj1);
- if (!(base = GfxColorSpace::parse(&obj1))) {
+ if (!(baseA = GfxColorSpace::parse(&obj1))) {
error(-1, "Bad Indexed color space (base color space)");
goto err2;
}
@@ -775,14 +790,14 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
error(-1, "Bad Indexed color space (hival)");
goto err2;
}
- indexHigh = obj1.getInt();
+ indexHighA = obj1.getInt();
obj1.free();
- cs = new GfxIndexedColorSpace(base, indexHigh);
+ cs = new GfxIndexedColorSpace(baseA, indexHighA);
arr->get(3, &obj1);
- n = base->getNComps();
+ n = baseA->getNComps();
if (obj1.isStream()) {
obj1.streamReset();
- for (i = 0; i <= indexHigh; ++i) {
+ for (i = 0; i <= indexHighA; ++i) {
for (j = 0; j < n; ++j) {
if ((x = obj1.streamGetChar()) == EOF) {
error(-1, "Bad Indexed color space (lookup table stream too short)");
@@ -793,12 +808,12 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
}
obj1.streamClose();
} else if (obj1.isString()) {
- if (obj1.getString()->getLength() < (indexHigh + 1) * n) {
+ if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
error(-1, "Bad Indexed color space (lookup table string too short)");
goto err3;
}
s = obj1.getString()->getCString();
- for (i = 0; i <= indexHigh; ++i) {
+ for (i = 0; i <= indexHighA; ++i) {
for (j = 0; j < n; ++j) {
cs->lookup[i*n + j] = (Guchar)*s++;
}
@@ -868,12 +883,12 @@ void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
// GfxSeparationColorSpace
//------------------------------------------------------------------------
-GfxSeparationColorSpace::GfxSeparationColorSpace(GString *name,
- GfxColorSpace *alt,
- Function *func) {
- this->name = name;
- this->alt = alt;
- this->func = func;
+GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
+ GfxColorSpace *altA,
+ Function *funcA) {
+ name = nameA;
+ alt = altA;
+ func = funcA;
}
GfxSeparationColorSpace::~GfxSeparationColorSpace() {
@@ -889,9 +904,9 @@ GfxColorSpace *GfxSeparationColorSpace::copy() {
//~ handle the 'All' and 'None' colorants
GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
GfxSeparationColorSpace *cs;
- GString *name;
- GfxColorSpace *alt;
- Function *func;
+ GString *nameA;
+ GfxColorSpace *altA;
+ Function *funcA;
Object obj1;
if (arr->getLength() != 4) {
@@ -902,27 +917,26 @@ GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
error(-1, "Bad Separation color space (name)");
goto err2;
}
- name = new GString(obj1.getName());
+ nameA = new GString(obj1.getName());
obj1.free();
arr->get(2, &obj1);
- if (!(alt = GfxColorSpace::parse(&obj1))) {
+ if (!(altA = GfxColorSpace::parse(&obj1))) {
error(-1, "Bad Separation color space (alternate color space)");
goto err3;
}
obj1.free();
- func = Function::parse(arr->get(3, &obj1));
- obj1.free();
- if (!func->isOk()) {
+ arr->get(3, &obj1);
+ if (!(funcA = Function::parse(&obj1))) {
goto err4;
}
- cs = new GfxSeparationColorSpace(name, alt, func);
+ obj1.free();
+ cs = new GfxSeparationColorSpace(nameA, altA, funcA);
return cs;
err4:
- delete func;
- delete alt;
+ delete altA;
err3:
- delete name;
+ delete nameA;
err2:
obj1.free();
err1:
@@ -954,12 +968,12 @@ void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
// GfxDeviceNColorSpace
//------------------------------------------------------------------------
-GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nComps,
- GfxColorSpace *alt,
- Function *func) {
- this->nComps = nComps;
- this->alt = alt;
- this->func = func;
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
+ GfxColorSpace *altA,
+ Function *funcA) {
+ nComps = nCompsA;
+ alt = altA;
+ func = funcA;
}
GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
@@ -986,10 +1000,10 @@ GfxColorSpace *GfxDeviceNColorSpace::copy() {
//~ handle the 'None' colorant
GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
GfxDeviceNColorSpace *cs;
- int nComps;
- GString *names[gfxColorMaxComps];
- GfxColorSpace *alt;
- Function *func;
+ int nCompsA;
+ GString *namesA[gfxColorMaxComps];
+ GfxColorSpace *altA;
+ Function *funcA;
Object obj1, obj2;
int i;
@@ -1001,40 +1015,39 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
error(-1, "Bad DeviceN color space (names)");
goto err2;
}
- nComps = obj1.arrayGetLength();
- for (i = 0; i < nComps; ++i) {
+ nCompsA = obj1.arrayGetLength();
+ for (i = 0; i < nCompsA; ++i) {
if (!obj1.arrayGet(i, &obj2)->isName()) {
error(-1, "Bad DeviceN color space (names)");
obj2.free();
goto err2;
}
- names[i] = new GString(obj2.getName());
+ namesA[i] = new GString(obj2.getName());
obj2.free();
}
obj1.free();
arr->get(2, &obj1);
- if (!(alt = GfxColorSpace::parse(&obj1))) {
+ if (!(altA = GfxColorSpace::parse(&obj1))) {
error(-1, "Bad DeviceN color space (alternate color space)");
goto err3;
}
obj1.free();
- func = Function::parse(arr->get(3, &obj1));
- obj1.free();
- if (!func->isOk()) {
+ arr->get(3, &obj1);
+ if (!(funcA = Function::parse(&obj1))) {
goto err4;
}
- cs = new GfxDeviceNColorSpace(nComps, alt, func);
- for (i = 0; i < nComps; ++i) {
- cs->names[i] = names[i];
+ obj1.free();
+ cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
+ for (i = 0; i < nCompsA; ++i) {
+ cs->names[i] = namesA[i];
}
return cs;
err4:
- delete func;
- delete alt;
+ delete altA;
err3:
- for (i = 0; i < nComps; ++i) {
- delete names[i];
+ for (i = 0; i < nCompsA; ++i) {
+ delete namesA[i];
}
err2:
obj1.free();
@@ -1067,8 +1080,8 @@ void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
// GfxPatternColorSpace
//------------------------------------------------------------------------
-GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *under) {
- this->under = under;
+GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) {
+ under = underA;
}
GfxPatternColorSpace::~GfxPatternColorSpace() {
@@ -1084,24 +1097,24 @@ GfxColorSpace *GfxPatternColorSpace::copy() {
GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
GfxPatternColorSpace *cs;
- GfxColorSpace *under;
+ GfxColorSpace *underA;
Object obj1;
if (arr->getLength() != 1 && arr->getLength() != 2) {
error(-1, "Bad Pattern color space");
return NULL;
}
- under = NULL;
+ underA = NULL;
if (arr->getLength() == 2) {
arr->get(1, &obj1);
- if (!(under = GfxColorSpace::parse(&obj1))) {
+ if (!(underA = GfxColorSpace::parse(&obj1))) {
error(-1, "Bad Pattern color space (underlying color space)");
obj1.free();
return NULL;
}
obj1.free();
}
- cs = new GfxPatternColorSpace(under);
+ cs = new GfxPatternColorSpace(underA);
return cs;
}
@@ -1122,8 +1135,8 @@ void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
// Pattern
//------------------------------------------------------------------------
-GfxPattern::GfxPattern(int type) {
- this->type = type;
+GfxPattern::GfxPattern(int typeA) {
+ type = typeA;
}
GfxPattern::~GfxPattern() {
@@ -1237,480 +1250,375 @@ GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
}
//------------------------------------------------------------------------
-// Function
+// GfxShading
//------------------------------------------------------------------------
-Function::Function() {
-}
-
-Function::~Function() {
+GfxShading::GfxShading() {
}
-Function *Function::parse(Object *funcObj) {
- Function *func;
- Dict *dict;
- int funcType;
- Object obj1;
-
- if (funcObj->isStream()) {
- dict = funcObj->streamGetDict();
- } else if (funcObj->isDict()) {
- dict = funcObj->getDict();
- } else {
- error(-1, "Expected function dictionary or stream");
- return NULL;
- }
-
- if (!dict->lookup("FunctionType", &obj1)->isInt()) {
- error(-1, "Function type is missing or wrong type");
- obj1.free();
- return NULL;
- }
- funcType = obj1.getInt();
- obj1.free();
-
- if (funcType == 0) {
- func = new SampledFunction(funcObj, dict);
- } else if (funcType == 2) {
- func = new ExponentialFunction(funcObj, dict);
- } else {
- error(-1, "Unimplemented function type");
- return NULL;
- }
- if (!func->isOk()) {
- delete func;
- return NULL;
- }
-
- return func;
+GfxShading::~GfxShading() {
+ delete colorSpace;
}
-GBool Function::init(Dict *dict) {
+GfxShading *GfxShading::parse(Object *obj) {
+ GfxShading *shading;
+ int typeA;
+ GfxColorSpace *colorSpaceA;
+ GfxColor backgroundA;
+ GBool hasBackgroundA;
+ double xMinA, yMinA, xMaxA, yMaxA;
+ GBool hasBBoxA;
Object obj1, obj2;
int i;
- //----- Domain
- if (!dict->lookup("Domain", &obj1)->isArray()) {
- error(-1, "Function is missing domain");
- goto err2;
- }
- m = obj1.arrayGetLength() / 2;
- if (m > funcMaxInputs) {
- error(-1, "Functions with more than %d inputs are unsupported",
- funcMaxInputs);
- goto err2;
- }
- for (i = 0; i < m; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function domain array");
+ shading = NULL;
+ if (obj->isDict()) {
+
+ if (!obj->dictLookup("ShadingType", &obj1)->isInt()) {
+ error(-1, "Invalid ShadingType in shading dictionary");
+ obj1.free();
goto err1;
}
- domain[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function domain array");
+ typeA = obj1.getInt();
+ obj1.free();
+
+ obj->dictLookup("ColorSpace", &obj1);
+ if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad color space in shading dictionary");
+ obj1.free();
goto err1;
}
- domain[i][1] = obj2.getNum();
- obj2.free();
- }
- obj1.free();
+ obj1.free();
- //----- Range
- hasRange = gFalse;
- n = 0;
- if (dict->lookup("Range", &obj1)->isArray()) {
- hasRange = gTrue;
- n = obj1.arrayGetLength() / 2;
- if (n > funcMaxOutputs) {
- error(-1, "Functions with more than %d outputs are unsupported",
- funcMaxOutputs);
- goto err2;
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ backgroundA.c[i] = 0;
}
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
- goto err1;
+ hasBackgroundA = gFalse;
+ if (obj->dictLookup("Background", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() == colorSpaceA->getNComps()) {
+ hasBackgroundA = gTrue;
+ for (i = 0; i < colorSpaceA->getNComps(); ++i) {
+ backgroundA.c[i] = obj1.arrayGet(i, &obj2)->getNum();
+ obj2.free();
+ }
+ } else {
+ error(-1, "Bad Background in shading dictionary");
}
- range[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
- goto err1;
+ }
+ obj1.free();
+
+ xMinA = yMinA = xMaxA = yMaxA = 0;
+ hasBBoxA = gFalse;
+ if (obj->dictLookup("BBox", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() == 4) {
+ hasBBoxA = gTrue;
+ xMinA = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ yMinA = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ xMaxA = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ yMaxA = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ } else {
+ error(-1, "Bad BBox in shading dictionary");
}
- range[i][1] = obj2.getNum();
- obj2.free();
}
obj1.free();
+
+ switch (typeA) {
+ case 2:
+ shading = GfxAxialShading::parse(obj->getDict());
+ break;
+ case 3:
+ shading = GfxRadialShading::parse(obj->getDict());
+ break;
+ default:
+ error(-1, "Unimplemented shading type %d", typeA);
+ goto err1;
+ }
+
+ if (shading) {
+ shading->type = typeA;
+ shading->colorSpace = colorSpaceA;
+ shading->background = backgroundA;
+ shading->hasBackground = hasBackgroundA;
+ shading->xMin = xMinA;
+ shading->yMin = yMinA;
+ shading->xMax = xMaxA;
+ shading->yMax = yMaxA;
+ shading->hasBBox = hasBBoxA;
+ } else {
+ delete colorSpaceA;
+ }
}
- return gTrue;
+ return shading;
err1:
- obj2.free();
- err2:
- obj1.free();
- return gFalse;
+ return NULL;
}
//------------------------------------------------------------------------
-// SampledFunction
+// GfxAxialShading
//------------------------------------------------------------------------
-SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
- Stream *str;
- int nSamples, sampleBits;
- double sampleMul;
- Object obj1, obj2;
- Guint buf, bitMask;
- int bits;
- int s;
+GfxAxialShading::GfxAxialShading(double x0A, double y0A,
+ double x1A, double y1A,
+ double t0A, double t1A,
+ Function **funcsA, int nFuncsA,
+ GBool extend0A, GBool extend1A) {
int i;
- samples = NULL;
- ok = gFalse;
-
- //----- initialize the generic stuff
- if (!init(dict)) {
- goto err1;
- }
- if (!hasRange) {
- error(-1, "Type 0 function is missing range");
- goto err1;
+ x0 = x0A;
+ y0 = y0A;
+ x1 = x1A;
+ y1 = y1A;
+ t0 = t0A;
+ t1 = t1A;
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
}
+ extend0 = extend0A;
+ extend1 = extend1A;
+}
- //----- get the stream
- if (!funcObj->isStream()) {
- error(-1, "Type 0 function isn't a stream");
- goto err1;
- }
- str = funcObj->getStream();
+GfxAxialShading::~GfxAxialShading() {
+ int i;
- //----- Size
- if (!dict->lookup("Size", &obj1)->isArray() ||
- obj1.arrayGetLength() != m) {
- error(-1, "Function has missing or invalid size array");
- goto err2;
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
}
- for (i = 0; i < m; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!obj2.isInt()) {
- error(-1, "Illegal value in function size array");
- goto err3;
- }
- sampleSize[i] = obj2.getInt();
+}
+
+GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
+ double x0A, y0A, x1A, y1A;
+ double t0A, t1A;
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ GBool extend0A, extend1A;
+ Object obj1, obj2;
+ int i;
+
+ x0A = y0A = x1A = y1A = 0;
+ if (dict->lookup("Coords", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 4) {
+ x0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ y0A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ x1A = obj1.arrayGet(2, &obj2)->getNum();
obj2.free();
+ y1A = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ } else {
+ error(-1, "Missing or invalid Coords in shading dictionary");
+ goto err1;
}
obj1.free();
- //----- BitsPerSample
- if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
- error(-1, "Function has missing or invalid BitsPerSample");
- goto err2;
+ t0A = 0;
+ t1A = 1;
+ if (dict->lookup("Domain", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ t0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ t1A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
}
- sampleBits = obj1.getInt();
- sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
obj1.free();
- //----- Encode
- if (dict->lookup("Encode", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2*m) {
- for (i = 0; i < m; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function encode array");
- goto err3;
- }
- encode[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function encode array");
- goto err3;
+ dict->lookup("Function", &obj1);
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ for (i = 0; i < nFuncsA; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ obj1.free();
+ obj2.free();
+ goto err1;
}
- encode[i][1] = obj2.getNum();
obj2.free();
}
} else {
- for (i = 0; i < m; ++i) {
- encode[i][0] = 0;
- encode[i][1] = sampleSize[i] - 1;
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ obj1.free();
+ goto err1;
}
}
obj1.free();
- //----- Decode
- if (dict->lookup("Decode", &obj1)->isArray() &&
- obj1.arrayGetLength() == 2*n) {
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function decode array");
- goto err3;
- }
- decode[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function decode array");
- goto err3;
- }
- decode[i][1] = obj2.getNum();
- obj2.free();
- }
- } else {
- for (i = 0; i < n; ++i) {
- decode[i][0] = range[i][0];
- decode[i][1] = range[i][1];
- }
+ extend0A = extend1A = gFalse;
+ if (dict->lookup("Extend", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ extend0A = obj1.arrayGet(0, &obj2)->getBool();
+ obj2.free();
+ extend1A = obj1.arrayGet(1, &obj2)->getBool();
+ obj2.free();
}
obj1.free();
- //----- samples
- nSamples = n;
- for (i = 0; i < m; ++i)
- nSamples *= sampleSize[i];
- samples = (double *)gmalloc(nSamples * sizeof(double));
- buf = 0;
- bits = 0;
- bitMask = (1 << sampleBits) - 1;
- str->reset();
- for (i = 0; i < nSamples; ++i) {
- if (sampleBits == 8) {
- s = str->getChar();
- } else if (sampleBits == 16) {
- s = str->getChar();
- s = (s << 8) + str->getChar();
- } else if (sampleBits == 32) {
- s = str->getChar();
- s = (s << 8) + str->getChar();
- s = (s << 8) + str->getChar();
- s = (s << 8) + str->getChar();
- } else {
- while (bits < sampleBits) {
- buf = (buf << 8) | (str->getChar() & 0xff);
- bits += 8;
- }
- s = (buf >> (bits - sampleBits)) & bitMask;
- bits -= sampleBits;
- }
- samples[i] = (double)s * sampleMul;
- }
- str->close();
+ return new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
+ funcsA, nFuncsA, extend0A, extend1A);
- ok = gTrue;
- return;
-
- err3:
- obj2.free();
- err2:
- obj1.free();
err1:
- return;
+ return NULL;
}
-SampledFunction::~SampledFunction() {
- if (samples) {
- gfree(samples);
+void GfxAxialShading::getColor(double t, GfxColor *color) {
+ int i;
+
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i]->transform(&t, &color->c[i]);
}
}
-SampledFunction::SampledFunction(SampledFunction *func) {
- int nSamples, i;
+//------------------------------------------------------------------------
+// GfxRadialShading
+//------------------------------------------------------------------------
- memcpy(this, func, sizeof(SampledFunction));
+GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A,
+ double x1A, double y1A, double r1A,
+ double t0A, double t1A,
+ Function **funcsA, int nFuncsA,
+ GBool extend0A, GBool extend1A) {
+ int i;
- nSamples = n;
- for (i = 0; i < m; ++i) {
- nSamples *= sampleSize[i];
+ x0 = x0A;
+ y0 = y0A;
+ r0 = r0A;
+ x1 = x1A;
+ y1 = y1A;
+ r1 = r1A;
+ t0 = t0A;
+ t1 = t1A;
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
}
- samples = (double *)gmalloc(nSamples * sizeof(double));
- memcpy(samples, func->samples, nSamples * sizeof(double));
+ extend0 = extend0A;
+ extend1 = extend1A;
}
-void SampledFunction::transform(double *in, double *out) {
- double e[4];
- double s;
- double x0, x1;
- int e0, e1;
- double efrac;
+GfxRadialShading::~GfxRadialShading() {
int i;
- // map input values into sample array
- for (i = 0; i < m; ++i) {
- e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
- (encode[i][1] - encode[i][0]) + encode[i][0];
- if (e[i] < 0) {
- e[i] = 0;
- } else if (e[i] > sampleSize[i] - 1) {
- e[i] = sampleSize[i] - 1;
- }
- }
-
- for (i = 0; i < n; ++i) {
-
- // m-linear interpolation
- // (only m=1 is currently supported)
- e0 = (int)floor(e[0]);
- e1 = (int)ceil(e[0]);
- efrac = e[0] - e0;
- x0 = samples[e0 * n + i];
- x1 = samples[e1 * n + i];
- s = (1 - efrac) * x0 + efrac * x1;
-
- // map output values to range
- out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
- if (out[i] < range[i][0]) {
- out[i] = range[i][0];
- } else if (out[i] > range[i][1]) {
- out[i] = range[i][1];
- }
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
}
}
-//------------------------------------------------------------------------
-// ExponentialFunction
-//------------------------------------------------------------------------
-
-ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
+GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
+ double x0A, y0A, r0A, x1A, y1A, r1A;
+ double t0A, t1A;
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ GBool extend0A, extend1A;
Object obj1, obj2;
- GBool hasN;
int i;
- ok = gFalse;
- hasN = gFalse;
-
- //----- initialize the generic stuff
- if (!init(dict)) {
- goto err1;
- }
- if (m != 1) {
- error(-1, "Exponential function with more than one input");
+ x0A = y0A = r0A = x1A = y1A = r1A = 0;
+ if (dict->lookup("Coords", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ x0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ y0A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ r0A = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ x1A = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ y1A = obj1.arrayGet(4, &obj2)->getNum();
+ obj2.free();
+ r1A = obj1.arrayGet(5, &obj2)->getNum();
+ obj2.free();
+ } else {
+ error(-1, "Missing or invalid Coords in shading dictionary");
goto err1;
}
+ obj1.free();
- //----- default values
- for (i = 0; i < funcMaxOutputs; ++i) {
- c0[i] = 0;
- c1[i] = 1;
+ t0A = 0;
+ t1A = 1;
+ if (dict->lookup("Domain", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ t0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ t1A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
}
+ obj1.free();
- //----- C0
- if (dict->lookup("C0", &obj1)->isArray()) {
- if (!hasN) {
- n = obj1.arrayGetLength();
- } else if (obj1.arrayGetLength() != n) {
- error(-1, "Function's C0 array is wrong length");
- goto err2;
- }
- for (i = 0; i < n; ++i) {
+ dict->lookup("Function", &obj1);
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ for (i = 0; i < nFuncsA; ++i) {
obj1.arrayGet(i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function C0 array");
- goto err3;
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ obj1.free();
+ obj2.free();
+ goto err1;
}
- c0[i] = obj2.getNum();
obj2.free();
}
- obj1.free();
- }
-
- //----- C1
- if (dict->lookup("C1", &obj1)->isArray()) {
- if (!hasN) {
- n = obj1.arrayGetLength();
- } else if (obj1.arrayGetLength() != n) {
- error(-1, "Function's C1 array is wrong length");
- goto err2;
- }
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function C1 array");
- goto err3;
- }
- c1[i] = obj2.getNum();
- obj2.free();
+ } else {
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ obj1.free();
+ goto err1;
}
- obj1.free();
}
+ obj1.free();
- //----- N (exponent)
- if (!dict->lookup("N", &obj1)->isNum()) {
- error(-1, "Function has missing or invalid N");
- goto err2;
+ extend0A = extend1A = gFalse;
+ if (dict->lookup("Extend", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ extend0A = obj1.arrayGet(0, &obj2)->getBool();
+ obj2.free();
+ extend1A = obj1.arrayGet(1, &obj2)->getBool();
+ obj2.free();
}
- e = obj1.getNum();
obj1.free();
- ok = gTrue;
- return;
+ return new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
+ funcsA, nFuncsA, extend0A, extend1A);
- err3:
- obj2.free();
- err2:
- obj1.free();
err1:
- return;
-}
-
-ExponentialFunction::~ExponentialFunction() {
-}
-
-ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
- memcpy(this, func, sizeof(ExponentialFunction));
+ return NULL;
}
-void ExponentialFunction::transform(double *in, double *out) {
- double x;
+void GfxRadialShading::getColor(double t, GfxColor *color) {
int i;
- if (in[0] < domain[0][0]) {
- x = domain[0][0];
- } else if (in[0] > domain[0][1]) {
- x = domain[0][1];
- } else {
- x = in[0];
- }
- for (i = 0; i < n; ++i) {
- out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
- if (hasRange) {
- if (out[i] < range[i][0]) {
- out[i] = range[i][0];
- } else if (out[i] > range[i][1]) {
- out[i] = range[i][1];
- }
- }
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i]->transform(&t, &color->c[i]);
}
- return;
}
//------------------------------------------------------------------------
// GfxImageColorMap
//------------------------------------------------------------------------
-GfxImageColorMap::GfxImageColorMap(int bits, Object *decode,
- GfxColorSpace *colorSpace) {
+GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
+ GfxColorSpace *colorSpaceA) {
GfxIndexedColorSpace *indexedCS;
GfxSeparationColorSpace *sepCS;
int maxPixel, indexHigh;
Guchar *lookup2;
Function *sepFunc;
Object obj;
- double x;
+ double x[gfxColorMaxComps];
double y[gfxColorMaxComps];
int i, j, k;
ok = gTrue;
// bits per component and color space
- this->bits = bits;
+ bits = bitsA;
maxPixel = (1 << bits) - 1;
- this->colorSpace = colorSpace;
+ colorSpace = colorSpaceA;
// get decode map
if (decode->isNull()) {
@@ -1739,18 +1647,6 @@ GfxImageColorMap::GfxImageColorMap(int bits, Object *decode,
goto err1;
}
-#if 0 //~
- // handle the case where fewer than 2^n palette entries of an n-bit
- // indexed color space are populated (this happens, e.g., in files
- // optimized by Distiller)
- if (colorSpace->getMode() == csIndexed) {
- i = ((GfxIndexedColorSpace *)colorSpace)->getIndexHigh();
- if (i < maxPixel) {
- maxPixel = i;
- }
- }
-#endif
-
// Construct a lookup table -- this stores pre-computed decoded
// values for each component, i.e., the result of applying the
// decode mapping to each possible image pixel component value.
@@ -1783,8 +1679,8 @@ GfxImageColorMap::GfxImageColorMap(int bits, Object *decode,
lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
sepFunc = sepCS->getFunc();
for (i = 0; i <= maxPixel; ++i) {
- x = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
- sepFunc->transform(&x, y);
+ x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
+ sepFunc->transform(x, y);
for (k = 0; k < nComps2; ++k) {
lookup[i*nComps2 + k] = y[k];
}
@@ -2009,19 +1905,34 @@ void GfxPath::curveTo(double x1, double y1, double x2, double y2,
subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
}
+void GfxPath::close() {
+ // this is necessary to handle the pathological case of
+ // moveto/closepath/clip, which defines an empty clipping region
+ if (justMoved) {
+ if (n >= size) {
+ size += 16;
+ subpaths = (GfxSubpath **)
+ grealloc(subpaths, size * sizeof(GfxSubpath *));
+ }
+ subpaths[n] = new GfxSubpath(firstX, firstY);
+ ++n;
+ justMoved = gFalse;
+ }
+ subpaths[n-1]->close();
+}
//------------------------------------------------------------------------
// GfxState
//------------------------------------------------------------------------
-GfxState::GfxState(double dpi, double px1a, double py1a,
- double px2a, double py2a, int rotate, GBool upsideDown) {
+GfxState::GfxState(double dpi, PDFRectangle *pageBox, int rotate,
+ GBool upsideDown) {
double k;
- px1 = px1a;
- py1 = py1a;
- px2 = px2a;
- py2 = py2a;
+ px1 = pageBox->x1;
+ py1 = pageBox->y1;
+ px2 = pageBox->x2;
+ py2 = pageBox->y2;
k = dpi / 72.0;
if (rotate == 90) {
ctm[0] = 0;
@@ -2095,6 +2006,11 @@ GfxState::GfxState(double dpi, double px1a, double py1a,
curX = curY = 0;
lineX = lineY = 0;
+ clipXMin = 0;
+ clipYMin = 0;
+ clipXMax = pageWidth;
+ clipYMax = pageHeight;
+
saved = NULL;
}
@@ -2112,7 +2028,10 @@ GfxState::~GfxState() {
delete strokePattern;
}
gfree(lineDash);
- delete path;
+ if (path) {
+ // this gets set to NULL by restore()
+ delete path;
+ }
if (saved) {
delete saved;
}
@@ -2137,10 +2056,70 @@ GfxState::GfxState(GfxState *state) {
lineDash = (double *)gmalloc(lineDashLength * sizeof(double));
memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
}
- path = state->path->copy();
saved = NULL;
}
+void GfxState::getUserClipBBox(double *xMin, double *yMin,
+ double *xMax, double *yMax) {
+ double ictm[6];
+ double xMin1, yMin1, xMax1, yMax1, det, tx, ty;
+
+ // invert the CTM
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+
+ // transform all four corners of the clip bbox; find the min and max
+ // x and y values
+ xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4];
+ yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5];
+ tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4];
+ ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+ tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4];
+ ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+ tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4];
+ ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+
+ *xMin = xMin1;
+ *yMin = yMin1;
+ *xMax = xMax1;
+ *yMax = yMax1;
+}
+
double GfxState::transformWidth(double w) {
double x, y;
@@ -2169,12 +2148,23 @@ void GfxState::getFontTransMat(double *m11, double *m12,
void GfxState::setCTM(double a, double b, double c,
double d, double e, double f) {
+ int i;
+
ctm[0] = a;
ctm[1] = b;
ctm[2] = c;
ctm[3] = d;
ctm[4] = e;
ctm[5] = f;
+
+ // avoid FP exceptions on badly messed up PDF files
+ for (i = 0; i < 6; ++i) {
+ if (ctm[i] > 1e10) {
+ ctm[i] = 1e10;
+ } else if (ctm[i] < -1e10) {
+ ctm[i] = -1e10;
+ }
+ }
}
void GfxState::concatCTM(double a, double b, double c,
@@ -2183,6 +2173,7 @@ void GfxState::concatCTM(double a, double b, double c,
double b1 = ctm[1];
double c1 = ctm[2];
double d1 = ctm[3];
+ int i;
ctm[0] = a * a1 + b * c1;
ctm[1] = a * b1 + b * d1;
@@ -2190,6 +2181,15 @@ void GfxState::concatCTM(double a, double b, double c,
ctm[3] = c * b1 + d * d1;
ctm[4] = e * a1 + f * c1 + ctm[4];
ctm[5] = e * b1 + f * d1 + ctm[5];
+
+ // avoid FP exceptions on badly messed up PDF files
+ for (i = 0; i < 6; ++i) {
+ if (ctm[i] > 1e10) {
+ ctm[i] = 1e10;
+ } else if (ctm[i] < -1e10) {
+ ctm[i] = -1e10;
+ }
+ }
}
void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
@@ -2233,12 +2233,45 @@ void GfxState::clearPath() {
path = new GfxPath();
}
-void GfxState::textShift(double tx) {
- double dx, dy;
-
- textTransformDelta(tx, 0, &dx, &dy);
- curX += dx;
- curY += dy;
+void GfxState::clip() {
+ double xMin, yMin, xMax, yMax, x, y;
+ GfxSubpath *subpath;
+ int i, j;
+
+ xMin = xMax = yMin = yMax = 0; // make gcc happy
+ for (i = 0; i < path->getNumSubpaths(); ++i) {
+ subpath = path->getSubpath(i);
+ for (j = 0; j < subpath->getNumPoints(); ++j) {
+ transform(subpath->getX(j), subpath->getY(j), &x, &y);
+ if (i == 0 && j == 0) {
+ xMin = xMax = x;
+ yMin = yMax = y;
+ } else {
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ }
+ }
+ }
+ if (xMin > clipXMin) {
+ clipXMin = xMin;
+ }
+ if (yMin > clipYMin) {
+ clipYMin = yMin;
+ }
+ if (xMax < clipXMax) {
+ clipXMax = xMax;
+ }
+ if (yMax < clipYMax) {
+ clipYMax = yMax;
+ }
}
void GfxState::textShift(double tx, double ty) {
@@ -2249,6 +2282,11 @@ void GfxState::textShift(double tx, double ty) {
curY += dy;
}
+void GfxState::shift(double dx, double dy) {
+ curX += dx;
+ curY += dy;
+}
+
GfxState *GfxState::save() {
GfxState *newState;
@@ -2262,10 +2300,21 @@ GfxState *GfxState::restore() {
if (saved) {
oldState = saved;
+
+ // these attributes aren't saved/restored by the q/Q operators
+ oldState->path = path;
+ oldState->curX = curX;
+ oldState->curY = curY;
+ oldState->lineX = lineX;
+ oldState->lineY = lineY;
+
+ path = NULL;
saved = NULL;
delete this;
+
} else {
oldState = this;
}
+
return oldState;
}