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 20:32:18 (GMT)
committer Martin Kretzschmar <mkretzschmar@src.gnome.org>2002-09-18 20:32:18 (GMT)
commit7aac8dc8533347e21311b15186e0af82f1b22fd6 (patch)
tree02650bb02c8a1d8468c22f50ff151885d233016b /pdf/xpdf/GfxState.cc
parentd99fb4f4acd14fcdbda968abd907547dcc7af40c (diff)
Synched with Xpdf 0.92
this adds "decryption" support testing this code after six weeks immediately gives me segfaults (image drawing) :-O must have fixed that later without knowing :-O
Diffstat (limited to 'pdf/xpdf/GfxState.cc')
-rw-r--r--pdf/xpdf/GfxState.cc1960
1 files changed, 1631 insertions, 329 deletions
diff --git a/pdf/xpdf/GfxState.cc b/pdf/xpdf/GfxState.cc
index c1b6090..1abf9a5 100644
--- a/pdf/xpdf/GfxState.cc
+++ b/pdf/xpdf/GfxState.cc
@@ -16,269 +16,1288 @@
#include "gmem.h"
#include "Error.h"
#include "Object.h"
+#include "Array.h"
#include "GfxState.h"
//------------------------------------------------------------------------
-// GfxColor
-//------------------------------------------------------------------------
-void GfxColor::setCMYK(double c, double m, double y, double k) {
- if ((r = 1 - (c + k)) < 0)
- r = 0;
- if ((g = 1 - (m + k)) < 0)
- g = 0;
- if ((b = 1 - (y + k)) < 0)
- b = 0;
+static inline double clip01(double x) {
+ return (x < 0) ? 0 : ((x > 1) ? 1 : x);
}
//------------------------------------------------------------------------
// GfxColorSpace
//------------------------------------------------------------------------
-GfxColorSpace::GfxColorSpace(Object *colorSpace) {
- Object csObj;
- Object obj, obj2;
- char *s;
- int x;
- int i, j;
+GfxColorSpace::GfxColorSpace() {
+}
- ok = gTrue;
- lookup = NULL;
-
- // check for Separation, DeviceN, and Pattern colorspaces
- colorSpace->copy(&csObj);
- sepFunc = NULL;
- if (colorSpace->isArray()) {
- colorSpace->arrayGet(0, &obj);
- if (obj.isName("Separation") || obj.isName("DeviceN")) {
- csObj.free();
- colorSpace->arrayGet(2, &csObj);
- sepFunc = new Function(colorSpace->arrayGet(3, &obj2));
- obj2.free();
- if (!sepFunc->isOk()) {
- delete sepFunc;
- sepFunc = NULL;
- }
- } else if (obj.isName("Pattern")) {
- csObj.free();
- colorSpace->arrayGet(1, &csObj);
- }
- obj.free();
- }
-
- // get mode
- indexed = gFalse;
- if (csObj.isName()) {
- setMode(&csObj);
- } else if (csObj.isArray()) {
- csObj.arrayGet(0, &obj);
- if (obj.isName("Indexed") || obj.isName("I")) {
- indexed = gTrue;
- setMode(csObj.arrayGet(1, &obj2));
- obj2.free();
+GfxColorSpace::~GfxColorSpace() {
+}
+
+GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
+ GfxColorSpace *cs;
+ Object obj1;
+
+ cs = NULL;
+ if (csObj->isName()) {
+ if (csObj->isName("DeviceGray") || csObj->isName("G")) {
+ cs = new GfxDeviceGrayColorSpace();
+ } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
+ cs = new GfxDeviceRGBColorSpace();
+ } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
+ cs = new GfxDeviceCMYKColorSpace();
+ } else if (csObj->isName("Pattern")) {
+ cs = new GfxPatternColorSpace(NULL);
} else {
- setMode(&csObj);
+ error(-1, "Bad color space '%s'", csObj->getName());
}
- obj.free();
+ } else if (csObj->isArray()) {
+ csObj->arrayGet(0, &obj1);
+ if (obj1.isName("DeviceGray") || obj1.isName("G")) {
+ cs = new GfxDeviceGrayColorSpace();
+ } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
+ cs = new GfxDeviceRGBColorSpace();
+ } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
+ cs = new GfxDeviceCMYKColorSpace();
+ } else if (obj1.isName("CalGray")) {
+ cs = GfxCalGrayColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("CalRGB")) {
+ cs = GfxCalRGBColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Lab")) {
+ cs = GfxLabColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("ICCBased")) {
+ cs = GfxICCBasedColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Indexed") || obj1.isName("I")) {
+ cs = GfxIndexedColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Separation")) {
+ cs = GfxSeparationColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("DeviceN")) {
+ cs = GfxDeviceNColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Pattern")) {
+ cs = GfxPatternColorSpace::parse(csObj->getArray());
+ } else {
+ error(-1, "Bad color space '%s'", csObj->getName());
+ }
+ obj1.free();
} else {
- goto err1;
+ error(-1, "Bad color space - expected name or array");
}
- if (!ok) {
- goto err1;
+ return cs;
+}
+
+void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel) {
+ int i;
+
+ for (i = 0; i < getNComps(); ++i) {
+ decodeLow[i] = 0;
+ decodeRange[i] = 1;
}
+}
- // get lookup table for indexed colorspace
- if (indexed) {
- csObj.arrayGet(2, &obj);
- if (!obj.isInt())
- goto err2;
- indexHigh = obj.getInt();
- obj.free();
- lookup = (Guchar (*)[4])gmalloc((indexHigh + 1) * 4 * sizeof(Guchar));
- csObj.arrayGet(3, &obj);
- if (obj.isStream()) {
- obj.streamReset();
- for (i = 0; i <= indexHigh; ++i) {
- for (j = 0; j < numComps; ++j) {
- if ((x = obj.streamGetChar()) == EOF)
- goto err2;
- lookup[i][j] = (Guchar)x;
- }
- }
- } else if (obj.isString()) {
- s = obj.getString()->getCString();
- for (i = 0; i <= indexHigh; ++i)
- for (j = 0; j < numComps; ++j)
- lookup[i][j] = (Guchar)*s++;
- } else {
- goto err2;
- }
- obj.free();
+//------------------------------------------------------------------------
+// GfxDeviceGrayColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
+}
+
+GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceGrayColorSpace::copy() {
+ return new GfxDeviceGrayColorSpace();
+}
+
+void GfxDeviceGrayColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(color->c[0]);
+}
+
+void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
+}
+
+void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = clip01(1 - color->c[0]);
+}
+
+//------------------------------------------------------------------------
+// GfxCalGrayColorSpace
+//------------------------------------------------------------------------
+
+GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
+ whiteX = whiteY = whiteZ = 1;
+ blackX = blackY = blackZ = 0;
+ gamma = 1;
+}
+
+GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
+}
+
+GfxColorSpace *GfxCalGrayColorSpace::copy() {
+ GfxCalGrayColorSpace *cs;
+
+ cs = new GfxCalGrayColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->gamma = gamma;
+ return cs;
+}
+
+GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
+ GfxCalGrayColorSpace *cs;
+ Object obj1, obj2, obj3;
+
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad CalGray color space");
+ obj1.free();
+ return NULL;
}
+ cs = new GfxCalGrayColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Gamma", &obj2)->isNum()) {
+ cs->gamma = obj2.getNum();
+ }
+ obj2.free();
+ obj1.free();
+ return cs;
+}
- csObj.free();
- return;
+void GfxCalGrayColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(color->c[0]);
+}
- err2:
- obj.free();
- err1:
- csObj.free();
- ok = gFalse;
+void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
+}
+
+void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = clip01(1 - color->c[0]);
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceRGBColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
+}
+
+GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceRGBColorSpace::copy() {
+ return new GfxDeviceRGBColorSpace();
+}
+
+void GfxDeviceRGBColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(0.299 * color->c[0] +
+ 0.587 * color->c[1] +
+ 0.114 * color->c[2]);
}
-GfxColorSpace::GfxColorSpace(GfxColorMode mode1) {
- sepFunc = NULL;
- mode = mode1;
- indexed = gFalse;
- switch (mode) {
- case colorGray: numComps = 1; break;
- case colorCMYK: numComps = 4; break;
- case colorRGB: numComps = 3; break;
+void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = clip01(color->c[0]);
+ rgb->g = clip01(color->c[1]);
+ rgb->b = clip01(color->c[2]);
+}
+
+void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ double c, m, y, k;
+
+ c = clip01(1 - color->c[0]);
+ m = clip01(1 - color->c[1]);
+ y = clip01(1 - color->c[2]);
+ k = c;
+ if (m < k) {
+ k = m;
}
- lookup = NULL;
- ok = gTrue;
+ if (y < k) {
+ k = y;
+ }
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
}
-GfxColorSpace::~GfxColorSpace() {
- if (sepFunc)
- delete sepFunc;
- gfree(lookup);
+//------------------------------------------------------------------------
+// GfxCalRGBColorSpace
+//------------------------------------------------------------------------
+
+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;
}
-GfxColorSpace::GfxColorSpace(GfxColorSpace *colorSpace) {
- int size;
-
- if (colorSpace->sepFunc)
- sepFunc = colorSpace->sepFunc->copy();
- else
- sepFunc = NULL;
- mode = colorSpace->mode;
- indexed = colorSpace->indexed;
- numComps = colorSpace->numComps;
- indexHigh = colorSpace->indexHigh;
- if (indexed) {
- size = (indexHigh + 1) * 4 * sizeof(Guchar);
- lookup = (Guchar (*)[4])gmalloc(size);
- memcpy(lookup, colorSpace->lookup, size);
- } else {
- lookup = NULL;
+GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
+}
+
+GfxColorSpace *GfxCalRGBColorSpace::copy() {
+ GfxCalRGBColorSpace *cs;
+ int i;
+
+ cs = new GfxCalRGBColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->gammaR = gammaR;
+ cs->gammaG = gammaG;
+ cs->gammaB = gammaB;
+ for (i = 0; i < 9; ++i) {
+ cs->m[i] = m[i];
}
- ok = gTrue;
+ return cs;
}
-void GfxColorSpace::setMode(Object *colorSpace) {
- Object obj;
+GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
+ GfxCalRGBColorSpace *cs;
+ Object obj1, obj2, obj3;
+ int i;
- if (colorSpace->isName("DeviceGray") || colorSpace->isName("G")) {
- mode = colorGray;
- numComps = 1;
- } else if (colorSpace->isName("DeviceRGB") || colorSpace->isName("RGB")) {
- mode = colorRGB;
- numComps = 3;
- } else if (colorSpace->isName("DeviceCMYK") || colorSpace->isName("CMYK")) {
- mode = colorCMYK;
- numComps = 4;
- } else if (colorSpace->isArray()) {
- colorSpace->arrayGet(0, &obj);
- if (obj.isName("CalGray")) {
- mode = colorGray;
- numComps = 1;
- } else if (obj.isName("CalRGB")) {
- mode = colorRGB;
- numComps = 3;
- } else if (obj.isName("CalCMYK")) {
- mode = colorCMYK;
- numComps = 4;
- } else {
- ok = gFalse;
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad CalRGB color space");
+ obj1.free();
+ return NULL;
+ }
+ cs = new GfxCalRGBColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->gammaR = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->gammaG = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->gammaB = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 9) {
+ for (i = 0; i < 9; ++i) {
+ obj2.arrayGet(i, &obj3);
+ cs->m[i] = obj3.getNum();
+ obj3.free();
}
- obj.free();
+ }
+ obj2.free();
+ obj1.free();
+ return cs;
+}
+
+void GfxCalRGBColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(0.299 * color->c[0] +
+ 0.587 * color->c[1] +
+ 0.114 * color->c[2]);
+}
+
+void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = clip01(color->c[0]);
+ rgb->g = clip01(color->c[1]);
+ rgb->b = clip01(color->c[2]);
+}
+
+void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ double c, m, y, k;
+
+ c = clip01(1 - color->c[0]);
+ m = clip01(1 - color->c[1]);
+ y = clip01(1 - color->c[2]);
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceCMYKColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
+}
+
+GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceCMYKColorSpace::copy() {
+ return new GfxDeviceCMYKColorSpace();
+}
+
+void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(1 - color->c[3]
+ - 0.299 * color->c[0]
+ - 0.587 * color->c[1]
+ - 0.114 * color->c[2]);
+}
+
+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]));
+}
+
+void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = clip01(color->c[0]);
+ cmyk->m = clip01(color->c[1]);
+ cmyk->y = clip01(color->c[2]);
+ cmyk->k = clip01(color->c[3]);
+}
+
+//------------------------------------------------------------------------
+// GfxLabColorSpace
+//------------------------------------------------------------------------
+
+// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
+// Language Reference, Third Edition.
+static double xyzrgb[3][3] = {
+ { 3.240449, -1.537136, -0.498531 },
+ { -0.969265, 1.876011, 0.041556 },
+ { 0.055643, -0.204026, 1.057229 }
+};
+
+GfxLabColorSpace::GfxLabColorSpace() {
+ whiteX = whiteY = whiteZ = 1;
+ blackX = blackY = blackZ = 0;
+ aMin = bMin = -100;
+ aMax = bMax = 100;
+}
+
+GfxLabColorSpace::~GfxLabColorSpace() {
+}
+
+GfxColorSpace *GfxLabColorSpace::copy() {
+ GfxLabColorSpace *cs;
+
+ cs = new GfxLabColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->aMin = aMin;
+ cs->aMax = aMax;
+ cs->bMin = bMin;
+ cs->bMax = bMax;
+ cs->kr = kr;
+ cs->kg = kg;
+ cs->kb = kb;
+ return cs;
+}
+
+GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
+ GfxLabColorSpace *cs;
+ Object obj1, obj2, obj3;
+
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad Lab color space");
+ obj1.free();
+ return NULL;
+ }
+ cs = new GfxLabColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Range", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 4) {
+ obj2.arrayGet(0, &obj3);
+ cs->aMin = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->aMax = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->bMin = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(3, &obj3);
+ cs->bMax = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ obj1.free();
+
+ cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
+ xyzrgb[0][1] * cs->whiteY +
+ xyzrgb[0][2] * cs->whiteZ);
+ cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
+ xyzrgb[1][1] * cs->whiteY +
+ xyzrgb[1][2] * cs->whiteZ);
+ cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
+ xyzrgb[2][1] * cs->whiteY +
+ xyzrgb[2][2] * cs->whiteZ);
+
+ return cs;
+}
+
+void GfxLabColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxRGB rgb;
+
+ getRGB(color, &rgb);
+ *gray = clip01(0.299 * rgb.r +
+ 0.587 * rgb.g +
+ 0.114 * rgb.b);
+}
+
+void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ double X, Y, Z;
+ double t1, t2;
+ double r, g, b;
+
+ // convert L*a*b* to CIE 1931 XYZ color space
+ t1 = (color->c[0] + 16) / 116;
+ t2 = t1 + color->c[1] / 500;
+ if (t2 >= (6.0 / 29.0)) {
+ X = t2 * t2 * t2;
+ } else {
+ X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
+ }
+ X *= whiteX;
+ if (t1 >= (6.0 / 29.0)) {
+ Y = t1 * t1 * t1;
+ } else {
+ Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
+ }
+ Y *= whiteY;
+ t2 = t1 - color->c[2] / 200;
+ if (t2 >= (6.0 / 29.0)) {
+ Z = t2 * t2 * t2;
} else {
- ok = gFalse;
+ Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
}
+ Z *= whiteZ;
+
+ // convert XYZ to RGB, including gamut mapping and gamma correction
+ r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
+ g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
+ b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
+ rgb->r = pow(clip01(r * kr), 0.5);
+ rgb->g = pow(clip01(g * kg), 0.5);
+ rgb->b = pow(clip01(b * kb), 0.5);
}
-void GfxColorSpace::getColor(double x[4], GfxColor *color) {
- double y[4];
- Guchar *p;
+void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxRGB rgb;
+ double c, m, y, k;
+
+ getRGB(color, &rgb);
+ c = clip01(1 - rgb.r);
+ m = clip01(1 - rgb.g);
+ y = clip01(1 - rgb.b);
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
+}
- if (sepFunc) {
- sepFunc->transform(x, y);
+void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel) {
+ decodeLow[0] = 0;
+ decodeRange[0] = 100;
+ decodeLow[1] = aMin;
+ decodeRange[1] = aMax - aMin;
+ decodeLow[2] = bMin;
+ decodeRange[2] = bMax - bMin;
+}
+
+//------------------------------------------------------------------------
+// GfxICCBasedColorSpace
+//------------------------------------------------------------------------
+
+GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nComps, GfxColorSpace *alt,
+ Ref *iccProfileStream) {
+ this->nComps = nComps;
+ this->alt = alt;
+ this->iccProfileStream = *iccProfileStream;
+ rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
+ rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
+}
+
+GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
+ delete alt;
+}
+
+GfxColorSpace *GfxICCBasedColorSpace::copy() {
+ GfxICCBasedColorSpace *cs;
+ int i;
+
+ cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
+ for (i = 0; i < 4; ++i) {
+ cs->rangeMin[i] = rangeMin[i];
+ cs->rangeMax[i] = rangeMax[i];
+ }
+ return cs;
+}
+
+GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
+ GfxICCBasedColorSpace *cs;
+ Ref iccProfileStream;
+ int nComps;
+ GfxColorSpace *alt;
+ Dict *dict;
+ Object obj1, obj2, obj3;
+ int i;
+
+ arr->getNF(1, &obj1);
+ if (obj1.isRef()) {
+ iccProfileStream = obj1.getRef();
} else {
- y[0] = x[0];
- y[1] = x[1];
- y[2] = x[2];
- y[3] = x[3];
- }
- if (indexed) {
- p = lookup[(int)(y[0] + 0.5)];
- switch (mode) {
- case colorGray:
- color->setGray(p[0] / 255.0);
+ iccProfileStream.num = 0;
+ iccProfileStream.gen = 0;
+ }
+ obj1.free();
+ arr->get(1, &obj1);
+ if (!obj1.isStream()) {
+ error(-1, "Bad ICCBased color space (stream)");
+ obj1.free();
+ return NULL;
+ }
+ dict = obj1.streamGetDict();
+ if (!dict->lookup("N", &obj2)->isInt()) {
+ error(-1, "Bad ICCBased color space (N)");
+ obj2.free();
+ obj1.free();
+ return NULL;
+ }
+ nComps = obj2.getInt();
+ obj2.free();
+ if (dict->lookup("Alternate", &obj2)->isNull() ||
+ !(alt = GfxColorSpace::parse(&obj2))) {
+ switch (nComps) {
+ case 1:
+ alt = new GfxDeviceGrayColorSpace();
break;
- case colorCMYK:
- color->setCMYK(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, p[3] / 255.0);
+ case 3:
+ alt = new GfxDeviceRGBColorSpace();
break;
- case colorRGB:
- color->setRGB(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0);
+ case 4:
+ alt = new GfxDeviceCMYKColorSpace();
break;
+ default:
+ error(-1, "Bad ICCBased color space - invalid N");
+ obj2.free();
+ obj1.free();
+ return NULL;
+ }
+ }
+ obj2.free();
+ cs = new GfxICCBasedColorSpace(nComps, alt, &iccProfileStream);
+ if (dict->lookup("Range", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 2 * nComps) {
+ for (i = 0; i < nComps; ++i) {
+ obj2.arrayGet(2*i, &obj3);
+ cs->rangeMin[i] = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2*i+1, &obj3);
+ cs->rangeMax[i] = obj3.getNum();
+ obj3.free();
+ }
+ }
+ obj2.free();
+ obj1.free();
+ return cs;
+}
+
+void GfxICCBasedColorSpace::getGray(GfxColor *color, double *gray) {
+ alt->getGray(color, gray);
+}
+
+void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ alt->getRGB(color, rgb);
+}
+
+void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ alt->getCMYK(color, cmyk);
+}
+
+void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
+ double *decodeRange,
+ int maxImgPixel) {
+ int i;
+
+ for (i = 0; i < nComps; ++i) {
+ decodeLow[i] = rangeMin[i];
+ decodeRange[i] = rangeMax[i] - rangeMin[i];
+ }
+}
+
+//------------------------------------------------------------------------
+// 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() {
+ delete base;
+ gfree(lookup);
+}
+
+GfxColorSpace *GfxIndexedColorSpace::copy() {
+ GfxIndexedColorSpace *cs;
+
+ cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
+ memcpy(cs->lookup, lookup,
+ (indexHigh + 1) * base->getNComps() * sizeof(Guchar));
+ return cs;
+}
+
+GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
+ GfxIndexedColorSpace *cs;
+ GfxColorSpace *base;
+ int indexHigh;
+ Object obj1;
+ int x;
+ char *s;
+ int n, i, j;
+
+ if (arr->getLength() != 4) {
+ error(-1, "Bad Indexed color space");
+ goto err1;
+ }
+ arr->get(1, &obj1);
+ if (!(base = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad Indexed color space (base color space)");
+ goto err2;
+ }
+ obj1.free();
+ if (!arr->get(2, &obj1)->isInt()) {
+ error(-1, "Bad Indexed color space (hival)");
+ goto err2;
+ }
+ indexHigh = obj1.getInt();
+ obj1.free();
+ cs = new GfxIndexedColorSpace(base, indexHigh);
+ arr->get(3, &obj1);
+ n = base->getNComps();
+ if (obj1.isStream()) {
+ obj1.streamReset();
+ for (i = 0; i <= indexHigh; ++i) {
+ for (j = 0; j < n; ++j) {
+ if ((x = obj1.streamGetChar()) == EOF) {
+ error(-1, "Bad Indexed color space (lookup table stream too short)");
+ goto err3;
+ }
+ cs->lookup[i*n + j] = (Guchar)x;
+ }
+ }
+ obj1.streamClose();
+ } else if (obj1.isString()) {
+ if (obj1.getString()->getLength() < (indexHigh + 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 (j = 0; j < n; ++j) {
+ cs->lookup[i*n + j] = (Guchar)*s++;
+ }
}
} else {
- switch (mode) {
- case colorGray:
- color->setGray(y[0]);
- break;
- case colorCMYK:
- color->setCMYK(y[0], y[1], y[2], y[3]);
- break;
- case colorRGB:
- color->setRGB(y[0], y[1], y[2]);
- break;
+ error(-1, "Bad Indexed color space (lookup table)");
+ goto err3;
+ }
+ obj1.free();
+ return cs;
+
+ err3:
+ delete cs;
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+void GfxIndexedColorSpace::getGray(GfxColor *color, double *gray) {
+ Guchar *p;
+ GfxColor color2;
+ int n, i;
+
+ n = base->getNComps();
+ p = &lookup[(int)(color->c[0] + 0.5) * n];
+ for (i = 0; i < n; ++i) {
+ color2.c[i] = p[i] / 255.0;
+ }
+ base->getGray(&color2, gray);
+}
+
+void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ Guchar *p;
+ GfxColor color2;
+ int n, i;
+
+ n = base->getNComps();
+ p = &lookup[(int)(color->c[0] + 0.5) * n];
+ for (i = 0; i < n; ++i) {
+ color2.c[i] = p[i] / 255.0;
+ }
+ base->getRGB(&color2, rgb);
+}
+
+void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ Guchar *p;
+ GfxColor color2;
+ int n, i;
+
+ n = base->getNComps();
+ p = &lookup[(int)(color->c[0] + 0.5) * n];
+ for (i = 0; i < n; ++i) {
+ color2.c[i] = p[i] / 255.0;
+ }
+ base->getCMYK(&color2, cmyk);
+}
+
+void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
+ double *decodeRange,
+ int maxImgPixel) {
+ decodeLow[0] = 0;
+ decodeRange[0] = maxImgPixel;
+}
+
+//------------------------------------------------------------------------
+// GfxSeparationColorSpace
+//------------------------------------------------------------------------
+
+GfxSeparationColorSpace::GfxSeparationColorSpace(GString *name,
+ GfxColorSpace *alt,
+ Function *func) {
+ this->name = name;
+ this->alt = alt;
+ this->func = func;
+}
+
+GfxSeparationColorSpace::~GfxSeparationColorSpace() {
+ delete name;
+ delete alt;
+ delete func;
+}
+
+GfxColorSpace *GfxSeparationColorSpace::copy() {
+ return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
+}
+
+//~ handle the 'All' and 'None' colorants
+GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
+ GfxSeparationColorSpace *cs;
+ GString *name;
+ GfxColorSpace *alt;
+ Function *func;
+ Object obj1;
+
+ if (arr->getLength() != 4) {
+ error(-1, "Bad Separation color space");
+ goto err1;
+ }
+ if (!arr->get(1, &obj1)->isName()) {
+ error(-1, "Bad Separation color space (name)");
+ goto err2;
+ }
+ name = new GString(obj1.getName());
+ obj1.free();
+ arr->get(2, &obj1);
+ if (!(alt = 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()) {
+ goto err4;
+ }
+ cs = new GfxSeparationColorSpace(name, alt, func);
+ return cs;
+
+ err4:
+ delete func;
+ delete alt;
+ err3:
+ delete name;
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+void GfxSeparationColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getGray(&color2, gray);
+}
+
+void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getRGB(&color2, rgb);
+}
+
+void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getCMYK(&color2, cmyk);
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceNColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nComps,
+ GfxColorSpace *alt,
+ Function *func) {
+ this->nComps = nComps;
+ this->alt = alt;
+ this->func = func;
+}
+
+GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
+ int i;
+
+ for (i = 0; i < nComps; ++i) {
+ delete names[i];
+ }
+ delete alt;
+ delete func;
+}
+
+GfxColorSpace *GfxDeviceNColorSpace::copy() {
+ GfxDeviceNColorSpace *cs;
+ int i;
+
+ cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
+ for (i = 0; i < nComps; ++i) {
+ cs->names[i] = names[i]->copy();
+ }
+ return cs;
+}
+
+//~ handle the 'None' colorant
+GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
+ GfxDeviceNColorSpace *cs;
+ int nComps;
+ GString *names[gfxColorMaxComps];
+ GfxColorSpace *alt;
+ Function *func;
+ Object obj1, obj2;
+ int i;
+
+ if (arr->getLength() != 4 && arr->getLength() != 5) {
+ error(-1, "Bad DeviceN color space");
+ goto err1;
+ }
+ if (!arr->get(1, &obj1)->isArray()) {
+ error(-1, "Bad DeviceN color space (names)");
+ goto err2;
+ }
+ nComps = obj1.arrayGetLength();
+ for (i = 0; i < nComps; ++i) {
+ if (!obj1.arrayGet(i, &obj2)->isName()) {
+ error(-1, "Bad DeviceN color space (names)");
+ obj2.free();
+ goto err2;
}
+ names[i] = new GString(obj2.getName());
+ obj2.free();
}
+ obj1.free();
+ arr->get(2, &obj1);
+ if (!(alt = 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()) {
+ goto err4;
+ }
+ cs = new GfxDeviceNColorSpace(nComps, alt, func);
+ for (i = 0; i < nComps; ++i) {
+ cs->names[i] = names[i];
+ }
+ return cs;
+
+ err4:
+ delete func;
+ delete alt;
+ err3:
+ for (i = 0; i < nComps; ++i) {
+ delete names[i];
+ }
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+void GfxDeviceNColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getGray(&color2, gray);
+}
+
+void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getRGB(&color2, rgb);
+}
+
+void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getCMYK(&color2, cmyk);
}
//------------------------------------------------------------------------
-// Function
+// GfxPatternColorSpace
//------------------------------------------------------------------------
-Function::Function(Object *funcObj) {
- Stream *str;
+GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *under) {
+ this->under = under;
+}
+
+GfxPatternColorSpace::~GfxPatternColorSpace() {
+ if (under) {
+ delete under;
+ }
+}
+
+GfxColorSpace *GfxPatternColorSpace::copy() {
+ return new GfxPatternColorSpace(under ? under->copy() :
+ (GfxColorSpace *)NULL);
+}
+
+GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
+ GfxPatternColorSpace *cs;
+ GfxColorSpace *under;
+ Object obj1;
+
+ if (arr->getLength() != 1 && arr->getLength() != 2) {
+ error(-1, "Bad Pattern color space");
+ return NULL;
+ }
+ under = NULL;
+ if (arr->getLength() == 2) {
+ arr->get(1, &obj1);
+ if (!(under = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad Pattern color space (underlying color space)");
+ obj1.free();
+ return NULL;
+ }
+ obj1.free();
+ }
+ cs = new GfxPatternColorSpace(under);
+ return cs;
+}
+
+void GfxPatternColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = 0;
+}
+
+void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = 0;
+}
+
+void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = 1;
+}
+
+//------------------------------------------------------------------------
+// Pattern
+//------------------------------------------------------------------------
+
+GfxPattern::GfxPattern(int type) {
+ this->type = type;
+}
+
+GfxPattern::~GfxPattern() {
+}
+
+GfxPattern *GfxPattern::parse(Object *obj) {
+ GfxPattern *pattern;
Dict *dict;
- int nSamples, sampleBits;
- double sampleMul;
+ Object obj1;
+
+ pattern = NULL;
+ if (obj->isStream()) {
+ dict = obj->streamGetDict();
+ dict->lookup("PatternType", &obj1);
+ if (obj1.isInt() && obj1.getInt() == 1) {
+ pattern = new GfxTilingPattern(dict, obj);
+ }
+ obj1.free();
+ }
+ return pattern;
+}
+
+//------------------------------------------------------------------------
+// GfxTilingPattern
+//------------------------------------------------------------------------
+
+GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
+ GfxPattern(1)
+{
Object obj1, obj2;
- Guint buf, bitMask;
- int bits;
- int s;
int i;
- ok = gFalse;
- samples = NULL;
+ if (streamDict->lookup("PaintType", &obj1)->isInt()) {
+ paintType = obj1.getInt();
+ } else {
+ paintType = 1;
+ error(-1, "Invalid or missing PaintType in pattern");
+ }
+ obj1.free();
+ if (streamDict->lookup("TilingType", &obj1)->isInt()) {
+ tilingType = obj1.getInt();
+ } else {
+ tilingType = 1;
+ error(-1, "Invalid or missing TilingType in pattern");
+ }
+ obj1.free();
+ bbox[0] = bbox[1] = 0;
+ bbox[2] = bbox[3] = 1;
+ if (streamDict->lookup("BBox", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 4) {
+ for (i = 0; i < 4; ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ bbox[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ } else {
+ error(-1, "Invalid or missing BBox in pattern");
+ }
+ obj1.free();
+ if (streamDict->lookup("XStep", &obj1)->isNum()) {
+ xStep = obj1.getNum();
+ } else {
+ xStep = 1;
+ error(-1, "Invalid or missing XStep in pattern");
+ }
+ obj1.free();
+ if (streamDict->lookup("YStep", &obj1)->isNum()) {
+ yStep = obj1.getNum();
+ } else {
+ yStep = 1;
+ error(-1, "Invalid or missing YStep in pattern");
+ }
+ obj1.free();
+ if (!streamDict->lookup("Resources", &resDict)->isDict()) {
+ resDict.free();
+ resDict.initNull();
+ error(-1, "Invalid or missing Resources in pattern");
+ }
+ matrix[0] = 1; matrix[1] = 0;
+ matrix[2] = 0; matrix[3] = 1;
+ matrix[4] = 0; matrix[5] = 0;
+ if (streamDict->lookup("Matrix", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ for (i = 0; i < 6; ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ matrix[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+ stream->copy(&contentStream);
+}
- if (!funcObj->isStream()) {
- error(-1, "Expected function dictionary");
- goto err3;
+GfxTilingPattern::~GfxTilingPattern() {
+ resDict.free();
+ contentStream.free();
+}
+
+GfxPattern *GfxTilingPattern::copy() {
+ return new GfxTilingPattern(this);
+}
+
+GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
+ GfxPattern(1)
+{
+ memcpy(this, pat, sizeof(GfxTilingPattern));
+ pat->resDict.copy(&resDict);
+ pat->contentStream.copy(&contentStream);
+}
+
+//------------------------------------------------------------------------
+// Function
+//------------------------------------------------------------------------
+
+Function::Function() {
+}
+
+Function::~Function() {
+}
+
+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;
}
- str = funcObj->getStream();
- dict = str->getDict();
- //----- FunctionType
- if (!dict->lookup("FunctionType", &obj1)->isInt() ||
- obj1.getInt() != 0) {
- error(-1, "Unknown function type");
- goto err2;
+ 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;
+}
+
+GBool Function::init(Dict *dict) {
+ 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 > 4) {
- error(-1, "Functions with more than 1 input are unsupported");
+ if (m > funcMaxInputs) {
+ error(-1, "Functions with more than %d inputs are unsupported",
+ funcMaxInputs);
goto err2;
}
for (i = 0; i < m; ++i) {
@@ -300,32 +1319,76 @@ Function::Function(Object *funcObj) {
obj1.free();
//----- Range
- if (!dict->lookup("Range", &obj1)->isArray()) {
- error(-1, "Function is missing range");
- goto err2;
- }
- n = obj1.arrayGetLength() / 2;
- if (n > 4) {
- error(-1, "Functions with more than 4 outputs are unsupported");
- goto err2;
- }
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
- goto err1;
+ 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;
}
- 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;
+ for (i = 0; i < n; ++i) {
+ obj1.arrayGet(2*i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function range array");
+ goto err1;
+ }
+ 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;
+ }
+ range[i][1] = obj2.getNum();
+ obj2.free();
}
- range[i][1] = obj2.getNum();
- obj2.free();
+ obj1.free();
}
+
+ return gTrue;
+
+ err1:
+ obj2.free();
+ err2:
obj1.free();
+ return gFalse;
+}
+
+//------------------------------------------------------------------------
+// SampledFunction
+//------------------------------------------------------------------------
+
+SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
+ Stream *str;
+ int nSamples, sampleBits;
+ double sampleMul;
+ Object obj1, obj2;
+ Guint buf, bitMask;
+ int bits;
+ int s;
+ 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;
+ }
+
+ //----- get the stream
+ if (!funcObj->isStream()) {
+ error(-1, "Type 0 function isn't a stream");
+ goto err1;
+ }
+ str = funcObj->getStream();
//----- Size
if (!dict->lookup("Size", &obj1)->isArray() ||
@@ -337,7 +1400,7 @@ Function::Function(Object *funcObj) {
obj1.arrayGet(i, &obj2);
if (!obj2.isInt()) {
error(-1, "Illegal value in function size array");
- goto err1;
+ goto err3;
}
sampleSize[i] = obj2.getInt();
obj2.free();
@@ -360,14 +1423,14 @@ Function::Function(Object *funcObj) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function encode array");
- goto err1;
+ 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 err1;
+ goto err3;
}
encode[i][1] = obj2.getNum();
obj2.free();
@@ -387,14 +1450,14 @@ Function::Function(Object *funcObj) {
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function decode array");
- goto err1;
+ 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 err1;
+ goto err3;
}
decode[i][1] = obj2.getNum();
obj2.free();
@@ -437,44 +1500,39 @@ Function::Function(Object *funcObj) {
}
samples[i] = (double)s * sampleMul;
}
+ str->close();
ok = gTrue;
return;
- err1:
+ err3:
obj2.free();
err2:
obj1.free();
- err3:
+ err1:
return;
}
-Function::Function(Function *func) {
+SampledFunction::~SampledFunction() {
+ if (samples) {
+ gfree(samples);
+ }
+}
+
+SampledFunction::SampledFunction(SampledFunction *func) {
int nSamples, i;
- m = func->m;
- n = func->n;
- memcpy(domain, func->domain, sizeof(domain));
- memcpy(range, func->range, sizeof(range));
- memcpy(sampleSize, func->sampleSize, sizeof(sampleSize));
- memcpy(encode, func->encode, sizeof(encode));
- memcpy(decode, func->decode, sizeof(decode));
+ memcpy(this, func, sizeof(SampledFunction));
nSamples = n;
- for (i = 0; i < m; ++i)
+ for (i = 0; i < m; ++i) {
nSamples *= sampleSize[i];
+ }
samples = (double *)gmalloc(nSamples * sizeof(double));
memcpy(samples, func->samples, nSamples * sizeof(double));
-
- ok = gTrue;
-}
-
-Function::~Function() {
- if (samples)
- gfree(samples);
}
-void Function::transform(double *in, double *out) {
+void SampledFunction::transform(double *in, double *out) {
double e[4];
double s;
double x0, x1;
@@ -486,10 +1544,11 @@ void Function::transform(double *in, double *out) {
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)
+ if (e[i] < 0) {
e[i] = 0;
- else if (e[i] > sampleSize[i] - 1)
+ } else if (e[i] > sampleSize[i] - 1) {
e[i] = sampleSize[i] - 1;
+ }
}
for (i = 0; i < n; ++i) {
@@ -505,67 +1564,174 @@ void Function::transform(double *in, double *out) {
// map output values to range
out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
- if (out[i] < range[i][0])
+ if (out[i] < range[i][0]) {
out[i] = range[i][0];
- else if (out[i] > range[i][1])
+ } else if (out[i] > range[i][1]) {
out[i] = range[i][1];
+ }
}
}
//------------------------------------------------------------------------
+// ExponentialFunction
+//------------------------------------------------------------------------
+
+ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
+ 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");
+ goto err1;
+ }
+
+ //----- default values
+ for (i = 0; i < funcMaxOutputs; ++i) {
+ c0[i] = 0;
+ c1[i] = 1;
+ }
+
+ //----- 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) {
+ obj1.arrayGet(i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function C0 array");
+ goto err3;
+ }
+ 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();
+ }
+ obj1.free();
+ }
+
+ //----- N (exponent)
+ if (!dict->lookup("N", &obj1)->isNum()) {
+ error(-1, "Function has missing or invalid N");
+ goto err2;
+ }
+ e = obj1.getNum();
+ obj1.free();
+
+ ok = gTrue;
+ return;
+
+ err3:
+ obj2.free();
+ err2:
+ obj1.free();
+ err1:
+ return;
+}
+
+ExponentialFunction::~ExponentialFunction() {
+}
+
+ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
+ memcpy(this, func, sizeof(ExponentialFunction));
+}
+
+void ExponentialFunction::transform(double *in, double *out) {
+ double x;
+ 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];
+ }
+ }
+ }
+ return;
+}
+
+//------------------------------------------------------------------------
// GfxImageColorMap
//------------------------------------------------------------------------
-GfxImageColorMap::GfxImageColorMap(int bits1, Object *decode,
- GfxColorSpace *colorSpace1) {
- GfxColor color;
- double x[4];
- int maxPixel;
+GfxImageColorMap::GfxImageColorMap(int bits, Object *decode,
+ GfxColorSpace *colorSpace) {
+ GfxIndexedColorSpace *indexedCS;
+ GfxSeparationColorSpace *sepCS;
+ int maxPixel, indexHigh;
+ Guchar *lookup2;
+ Function *sepFunc;
Object obj;
- int i, j;
+ double x;
+ double y[gfxColorMaxComps];
+ int i, j, k;
ok = gTrue;
- // bits per component and colorspace
- bits = bits1;
+ // bits per component and color space
+ this->bits = bits;
maxPixel = (1 << bits) - 1;
- colorSpace = colorSpace1;
- mode = colorSpace->getMode();
-
- // work around a bug in Distiller (?)
- if (colorSpace->isIndexed() && maxPixel > colorSpace->getIndexHigh()) {
- maxPixel = colorSpace->getIndexHigh();
- }
+ this->colorSpace = colorSpace;
// get decode map
if (decode->isNull()) {
- if (colorSpace->isIndexed()) {
- indexed = gTrue;
- numComps = 1;
- decodeLow[0] = 0;
- decodeRange[0] = maxPixel;
- } else {
- indexed = gFalse;
- numComps = colorSpace->getNumPixelComps();
- for (i = 0; i < numComps; ++i) {
- decodeLow[i] = 0;
- decodeRange[i] = 1;
- }
- }
+ nComps = colorSpace->getNComps();
+ colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
} else if (decode->isArray()) {
- numComps = decode->arrayGetLength() / 2;
- if (numComps != colorSpace->getNumPixelComps())
+ nComps = decode->arrayGetLength() / 2;
+ if (nComps != colorSpace->getNComps()) {
goto err1;
- indexed = colorSpace->isIndexed();
- for (i = 0; i < numComps; ++i) {
+ }
+ for (i = 0; i < nComps; ++i) {
decode->arrayGet(2*i, &obj);
- if (!obj.isNum())
+ if (!obj.isNum()) {
goto err2;
+ }
decodeLow[i] = obj.getNum();
obj.free();
decode->arrayGet(2*i+1, &obj);
- if (!obj.isNum())
+ if (!obj.isNum()) {
goto err2;
+ }
decodeRange[i] = obj.getNum() - decodeLow[i];
obj.free();
}
@@ -573,20 +1739,64 @@ GfxImageColorMap::GfxImageColorMap(int bits1, Object *decode,
goto err1;
}
- // construct lookup table
- lookup = (double (*)[4])gmalloc((maxPixel + 1) * 4 * sizeof(double));
- if (indexed) {
+#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.
+ //
+ // Optimization: for Indexed and Separation color spaces (which have
+ // only one component), we store color values in the lookup table
+ // rather than component values.
+ colorSpace2 = NULL;
+ nComps2 = 0;
+ if (colorSpace->getMode() == csIndexed) {
+ // Note that indexHigh may not be the same as maxPixel --
+ // Distiller will remove unused palette entries, resulting in
+ // indexHigh < maxPixel.
+ indexedCS = (GfxIndexedColorSpace *)colorSpace;
+ colorSpace2 = indexedCS->getBase();
+ indexHigh = indexedCS->getIndexHigh();
+ nComps2 = colorSpace2->getNComps();
+ lookup = (double *)gmalloc((indexHigh + 1) * nComps2 * sizeof(double));
+ lookup2 = indexedCS->getLookup();
+ for (i = 0; i <= indexHigh; ++i) {
+ j = (int)(decodeLow[0] +(i * decodeRange[0]) / maxPixel + 0.5);
+ for (k = 0; k < nComps2; ++k) {
+ lookup[i*nComps2 + k] = lookup2[i*nComps2 + k] / 255.0;
+ }
+ }
+ } else if (colorSpace->getMode() == csSeparation) {
+ sepCS = (GfxSeparationColorSpace *)colorSpace;
+ colorSpace2 = sepCS->getAlt();
+ nComps2 = colorSpace2->getNComps();
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
+ sepFunc = sepCS->getFunc();
for (i = 0; i <= maxPixel; ++i) {
- x[0] = (double)i;
- colorSpace->getColor(x, &color);
- lookup[i][0] = color.getR();
- lookup[i][1] = color.getG();
- lookup[i][2] = color.getB();
+ x = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
+ sepFunc->transform(&x, y);
+ for (k = 0; k < nComps2; ++k) {
+ lookup[i*nComps2 + k] = y[k];
+ }
}
} else {
- for (i = 0; i <= maxPixel; ++i)
- for (j = 0; j < numComps; ++j)
- lookup[i][j] = decodeLow[j] + (i * decodeRange[j]) / maxPixel;
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps * sizeof(double));
+ for (i = 0; i <= maxPixel; ++i) {
+ for (k = 0; k < nComps; ++k) {
+ lookup[i*nComps + k] = decodeLow[k] +
+ (i * decodeRange[k]) / maxPixel;
+ }
+ }
}
return;
@@ -602,25 +1812,60 @@ GfxImageColorMap::~GfxImageColorMap() {
gfree(lookup);
}
-void GfxImageColorMap::getColor(Guchar x[4], GfxColor *color) {
+void GfxImageColorMap::getGray(Guchar *x, double *gray) {
+ GfxColor color;
double *p;
+ int i;
- if (indexed) {
- p = lookup[x[0]];
- color->setRGB(p[0], p[1], p[2]);
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
+ }
+ colorSpace2->getGray(&color, gray);
} else {
- switch (mode) {
- case colorGray:
- color->setGray(lookup[x[0]][0]);
- break;
- case colorCMYK:
- color->setCMYK(lookup[x[0]][0], lookup[x[1]][1],
- lookup[x[2]][2], lookup[x[3]][3]);
- break;
- case colorRGB:
- color->setRGB(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2]);
- break;
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getGray(&color, gray);
+ }
+}
+
+void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
+ GfxColor color;
+ double *p;
+ int i;
+
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
}
+ colorSpace2->getRGB(&color, rgb);
+ } else {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getRGB(&color, rgb);
+ }
+}
+
+void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
+ GfxColor color;
+ double *p;
+ int i;
+
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
+ }
+ colorSpace2->getCMYK(&color, cmyk);
+ } else {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getCMYK(&color, cmyk);
}
}
@@ -637,6 +1882,7 @@ GfxSubpath::GfxSubpath(double x1, double y1) {
x[0] = x1;
y[0] = y1;
curve[0] = gFalse;
+ closed = gFalse;
}
GfxSubpath::~GfxSubpath() {
@@ -655,6 +1901,7 @@ GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
memcpy(x, subpath->x, n * sizeof(double));
memcpy(y, subpath->y, n * sizeof(double));
memcpy(curve, subpath->curve, n * sizeof(GBool));
+ closed = subpath->closed;
}
void GfxSubpath::lineTo(double x1, double y1) {
@@ -689,10 +1936,18 @@ void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
n += 3;
}
+void GfxSubpath::close() {
+ if (x[n-1] != x[0] || y[n-1] != y[0]) {
+ lineTo(x[0], y[0]);
+ }
+ closed = gTrue;
+}
+
GfxPath::GfxPath() {
justMoved = gFalse;
size = 16;
n = 0;
+ firstX = firstY = 0;
subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
}
@@ -759,15 +2014,15 @@ void GfxPath::curveTo(double x1, double y1, double x2, double y2,
// GfxState
//------------------------------------------------------------------------
-GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
- int rotate, GBool upsideDown) {
+GfxState::GfxState(double dpi, double px1a, double py1a,
+ double px2a, double py2a, int rotate, GBool upsideDown) {
double k;
px1 = px1a;
py1 = py1a;
px2 = px2a;
py2 = py2a;
- k = (double)dpi / 72.0;
+ k = dpi / 72.0;
if (rotate == 90) {
ctm[0] = 0;
ctm[1] = upsideDown ? k : -k;
@@ -775,8 +2030,8 @@ GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
ctm[3] = 0;
ctm[4] = -k * py1;
ctm[5] = k * (upsideDown ? -px1 : px2);
- pageWidth = (int)(k * (py2 - py1));
- pageHeight = (int)(k * (px2 - px1));
+ pageWidth = k * (py2 - py1);
+ pageHeight = k * (px2 - px1);
} else if (rotate == 180) {
ctm[0] = -k;
ctm[1] = 0;
@@ -784,8 +2039,8 @@ GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
ctm[3] = upsideDown ? k : -k;
ctm[4] = k * px2;
ctm[5] = k * (upsideDown ? -py1 : py2);
- pageWidth = (int)(k * (px2 - px1));
- pageHeight = (int)(k * (py2 - py1));
+ pageWidth = k * (px2 - px1);
+ pageHeight = k * (py2 - py1);
} else if (rotate == 270) {
ctm[0] = 0;
ctm[1] = upsideDown ? -k : k;
@@ -793,8 +2048,8 @@ GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
ctm[3] = 0;
ctm[4] = k * py2;
ctm[5] = k * (upsideDown ? px2 : -px1);
- pageWidth = (int)(k * (py2 - py1));
- pageHeight = (int)(k * (px2 - px1));
+ pageWidth = k * (py2 - py1);
+ pageHeight = k * (px2 - px1);
} else {
ctm[0] = k;
ctm[1] = 0;
@@ -802,14 +2057,18 @@ GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
ctm[3] = upsideDown ? -k : k;
ctm[4] = -k * px1;
ctm[5] = k * (upsideDown ? py2 : -py1);
- pageWidth = (int)(k * (px2 - px1));
- pageHeight = (int)(k * (py2 - py1));
+ pageWidth = k * (px2 - px1);
+ pageHeight = k * (py2 - py1);
}
- fillColorSpace = new GfxColorSpace(colorGray);
- strokeColorSpace = new GfxColorSpace(colorGray);
- fillColor.setGray(0);
- strokeColor.setGray(0);
+ fillColorSpace = new GfxDeviceGrayColorSpace();
+ strokeColorSpace = new GfxDeviceGrayColorSpace();
+ fillColor.c[0] = 0;
+ strokeColor.c[0] = 0;
+ fillPattern = NULL;
+ strokePattern = NULL;
+ fillOpacity = 1;
+ strokeOpacity = 1;
lineWidth = 1;
lineDash = NULL;
@@ -840,23 +2099,40 @@ GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
}
GfxState::~GfxState() {
- if (fillColorSpace)
+ if (fillColorSpace) {
delete fillColorSpace;
- if (strokeColorSpace)
+ }
+ if (strokeColorSpace) {
delete strokeColorSpace;
+ }
+ if (fillPattern) {
+ delete fillPattern;
+ }
+ if (strokePattern) {
+ delete strokePattern;
+ }
gfree(lineDash);
delete path;
- if (saved)
+ if (saved) {
delete saved;
+ }
}
// Used for copy();
GfxState::GfxState(GfxState *state) {
memcpy(this, state, sizeof(GfxState));
- if (fillColorSpace)
+ if (fillColorSpace) {
fillColorSpace = state->fillColorSpace->copy();
- if (strokeColorSpace)
+ }
+ if (strokeColorSpace) {
strokeColorSpace = state->strokeColorSpace->copy();
+ }
+ if (fillPattern) {
+ fillPattern = state->fillPattern->copy();
+ }
+ if (strokePattern) {
+ strokePattern = state->strokePattern->copy();
+ }
if (lineDashLength > 0) {
lineDash = (double *)gmalloc(lineDashLength * sizeof(double));
memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
@@ -891,6 +2167,16 @@ void GfxState::getFontTransMat(double *m11, double *m12,
*m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
}
+void GfxState::setCTM(double a, double b, double c,
+ double d, double e, double f) {
+ ctm[0] = a;
+ ctm[1] = b;
+ ctm[2] = c;
+ ctm[3] = d;
+ ctm[4] = e;
+ ctm[5] = f;
+}
+
void GfxState::concatCTM(double a, double b, double c,
double d, double e, double f) {
double a1 = ctm[0];
@@ -907,17 +2193,33 @@ void GfxState::concatCTM(double a, double b, double c,
}
void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
- if (fillColorSpace)
+ if (fillColorSpace) {
delete fillColorSpace;
+ }
fillColorSpace = colorSpace;
}
void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
- if (strokeColorSpace)
+ if (strokeColorSpace) {
delete strokeColorSpace;
+ }
strokeColorSpace = colorSpace;
}
+void GfxState::setFillPattern(GfxPattern *pattern) {
+ if (fillPattern) {
+ delete fillPattern;
+ }
+ fillPattern = pattern;
+}
+
+void GfxState::setStrokePattern(GfxPattern *pattern) {
+ if (strokePattern) {
+ delete strokePattern;
+ }
+ strokePattern = pattern;
+}
+
void GfxState::setLineDash(double *dash, int length, double start) {
if (lineDash)
gfree(lineDash);