+ }
+ }
+}
+
+void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
+ GfxCalGrayColorSpace *calGrayCS;
+ GfxCalRGBColorSpace *calRGBCS;
+ GfxLabColorSpace *labCS;
+ GfxIndexedColorSpace *indexedCS;
+ GfxSeparationColorSpace *separationCS;
+ GfxColorSpace *baseCS;
+ Guchar *lookup, *p;
+ double x[gfxColorMaxComps], y[gfxColorMaxComps];
+ GfxColor color;
+ GfxCMYK cmyk;
+ Function *func;
+ int n, numComps, numAltComps;
+ int byte;
+ int i, j, k;
+
+ switch (colorSpace->getMode()) {
+
+ case csDeviceGray:
+ writePS("/DeviceGray");
+ processColors |= psProcessBlack;
+ break;
+
+ case csCalGray:
+ calGrayCS = (GfxCalGrayColorSpace *)colorSpace;
+ writePS("[/CIEBasedA <<\n");
+ writePSFmt(" /DecodeA {%g exp} bind\n", calGrayCS->getGamma());
+ writePSFmt(" /MatrixA [%g %g %g]\n",
+ calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+ calGrayCS->getWhiteZ());
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+ calGrayCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ calGrayCS->getBlackX(), calGrayCS->getBlackY(),
+ calGrayCS->getBlackZ());
+ writePS(">>]");
+ processColors |= psProcessBlack;
+ break;
+
+ case csDeviceRGB:
+ writePS("/DeviceRGB");
+ processColors |= psProcessCMYK;
+ break;
+
+ case csCalRGB:
+ calRGBCS = (GfxCalRGBColorSpace *)colorSpace;
+ writePS("[/CIEBasedABC <<\n");
+ writePSFmt(" /DecodeABC [{%g exp} bind {%g exp} bind {%g exp} bind]\n",
+ calRGBCS->getGammaR(), calRGBCS->getGammaG(),
+ calRGBCS->getGammaB());
+ writePSFmt(" /MatrixABC [%g %g %g %g %g %g %g %g %g]\n",
+ calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1],
+ calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3],
+ calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5],
+ calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7],
+ calRGBCS->getMatrix()[8]);
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ calRGBCS->getWhiteX(), calRGBCS->getWhiteY(),
+ calRGBCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ calRGBCS->getBlackX(), calRGBCS->getBlackY(),
+ calRGBCS->getBlackZ());
+ writePS(">>]");
+ processColors |= psProcessCMYK;
+ break;
+
+ case csDeviceCMYK:
+ writePS("/DeviceCMYK");
+ processColors |= psProcessCMYK;
+ break;
+
+ case csLab:
+ labCS = (GfxLabColorSpace *)colorSpace;
+ writePS("[/CIEBasedABC <<\n");
+ writePSFmt(" /RangeABC [0 100 %g %g %g %g]\n",
+ labCS->getAMin(), labCS->getAMax(),
+ labCS->getBMin(), labCS->getBMax());
+ writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
+ writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
+ writePS(" /DecodeLMN\n");
+ writePS(" [{dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+ labCS->getWhiteX());
+ writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+ labCS->getWhiteY());
+ writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
+ labCS->getWhiteZ());
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
+ writePS(">>]");
+ processColors |= psProcessCMYK;
+ break;
+
+ case csICCBased:
+ dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt());
+ break;
+
+ case csIndexed:
+ indexedCS = (GfxIndexedColorSpace *)colorSpace;
+ baseCS = indexedCS->getBase();
+ writePS("[/Indexed ");
+ dumpColorSpaceL2(baseCS);
+ n = indexedCS->getIndexHigh();
+ numComps = baseCS->getNComps();
+ lookup = indexedCS->getLookup();
+ writePSFmt(" %d <\n", n);
+ if (baseCS->getMode() == csDeviceN) {
+ func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc();
+ numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps();
+ p = lookup;
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ x[k] = *p++ / 255.0;
+ }
+ func->transform(x, y);
+ for (k = 0; k < numAltComps; ++k) {
+ byte = (int)(y[k] * 255 + 0.5);
+ if (byte < 0) {
+ byte = 0;
+ } else if (byte > 255) {
+ byte = 255;
+ }
+ writePSFmt("%02x", byte);
+ }
+ color.c[0] = j;
+ indexedCS->getCMYK(&color, &cmyk);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ }
+ writePS("\n");
+ }
+ } else {
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ writePSFmt("%02x", lookup[j * numComps + k]);
+ }
+ color.c[0] = j;
+ indexedCS->getCMYK(&color, &cmyk);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ }
+ writePS("\n");
+ }
+ }
+ writePS(">]");
+ break;
+
+ case csSeparation:
+ //~ this is a kludge -- the correct thing would to ouput a
+ //~ separation color space, with the specified alternate color
+ //~ space and tint transform
+ separationCS = (GfxSeparationColorSpace *)colorSpace;
+ writePS("[/Indexed ");
+ dumpColorSpaceL2(separationCS->getAlt());
+ writePS(" 255 <\n");
+ numComps = separationCS->getAlt()->getNComps();
+ for (i = 0; i <= 255; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= 255; ++j) {
+ x[0] = (double)j / 255.0;
+ separationCS->getFunc()->transform(x, y);
+ for (k = 0; k < numComps; ++k) {
+ writePSFmt("%02x", (int)(255 * y[k] + 0.5));
+ }
+ }
+ writePS("\n");
+ }
+ writePS(">]");
+ addCustomColor(separationCS);
+ break;
+
+ case csDeviceN:
+ // DeviceN color spaces are a Level 3 PostScript feature.
+ dumpColorSpaceL2(((GfxDeviceNColorSpace *)colorSpace)->getAlt());
+ break;
+
+ case csPattern:
+ //~ unimplemented
+ break;
+
+ }
+}
+
+#if OPI_SUPPORT
+void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) {
+ Object dict;
+
+ if (globalParams->getPSOPI()) {
+ opiDict->lookup("2.0", &dict);
+ if (dict.isDict()) {
+ opiBegin20(state, dict.getDict());
+ dict.free();
+ } else {
+ dict.free();
+ opiDict->lookup("1.3", &dict);
+ if (dict.isDict()) {
+ opiBegin13(state, dict.getDict());
+ }
+ dict.free();
+ }
+ }
+}
+
+void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) {
+ Object obj1, obj2, obj3, obj4;
+ double width, height, left, right, top, bottom;
+ int w, h;
+ int i;
+
+ writePS("%%BeginOPI: 2.0\n");
+ writePS("%%Distilled\n");
+
+ dict->lookup("F", &obj1);
+ if (getFileSpec(&obj1, &obj2)) {
+ writePSFmt("%%%%ImageFileName: %s\n",
+ obj2.getString()->getCString());
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("MainImage", &obj1);
+ if (obj1.isString()) {
+ writePSFmt("%%%%MainImage: %s\n", obj1.getString()->getCString());
+ }
+ obj1.free();
+
+ //~ ignoring 'Tags' entry
+ //~ need to use writePSString() and deal with >255-char lines
+
+ dict->lookup("Size", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ width = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ height = obj2.getNum();
+ obj2.free();
+ writePSFmt("%%%%ImageDimensions: %g %g\n", width, height);
+ }
+ obj1.free();
+
+ dict->lookup("CropRect", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 4) {
+ obj1.arrayGet(0, &obj2);
+ left = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ top = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ right = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ bottom = obj2.getNum();
+ obj2.free();
+ writePSFmt("%%%%ImageCropRect: %g %g %g %g\n", left, top, right, bottom);
+ }
+ obj1.free();
+
+ dict->lookup("Overprint", &obj1);
+ if (obj1.isBool()) {
+ writePSFmt("%%%%ImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
+ }
+ obj1.free();
+
+ dict->lookup("Inks", &obj1);
+ if (obj1.isName()) {
+ writePSFmt("%%%%ImageInks: %s\n", obj1.getName());
+ } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) {
+ obj1.arrayGet(0, &obj2);
+ if (obj2.isName()) {
+ writePSFmt("%%%%ImageInks: %s %d",
+ obj2.getName(), (obj1.arrayGetLength() - 1) / 2);
+ for (i = 1; i+1 < obj1.arrayGetLength(); i += 2) {
+ obj1.arrayGet(i, &obj3);
+ obj1.arrayGet(i+1, &obj4);
+ if (obj3.isString() && obj4.isNum()) {
+ writePS(" ");
+ writePSString(obj3.getString());
+ writePSFmt(" %g", obj4.getNum());
+ }
+ obj3.free();
+ obj4.free();
+ }
+ writePS("\n");
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ writePS("gsave\n");
+
+ writePS("%%BeginIncludedImage\n");
+
+ dict->lookup("IncludedImageDimensions", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ w = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ h = obj2.getInt();
+ obj2.free();
+ writePSFmt("%%%%IncludedImageDimensions: %d %d\n", w, h);
+ }
+ obj1.free();
+
+ dict->lookup("IncludedImageQuality", &obj1);
+ if (obj1.isNum()) {
+ writePSFmt("%%%%IncludedImageQuality: %g\n", obj1.getNum());
+ }
+ obj1.free();
+
+ ++opi20Nest;
+}
+
+void PSOutputDev::opiBegin13(GfxState *state, Dict *dict) {
+ Object obj1, obj2;
+ int left, right, top, bottom, samples, bits, width, height;
+ double c, m, y, k;
+ double llx, lly, ulx, uly, urx, ury, lrx, lry;
+ double tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry;
+ double horiz, vert;
+ int i, j;
+
+ writePS("save\n");
+ writePS("/opiMatrix2 matrix currentmatrix def\n");
+ writePS("opiMatrix setmatrix\n");
+
+ dict->lookup("F", &obj1);
+ if (getFileSpec(&obj1, &obj2)) {
+ writePSFmt("%%ALDImageFileName: %s\n",
+ obj2.getString()->getCString());
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("CropRect", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 4) {
+ obj1.arrayGet(0, &obj2);
+ left = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ top = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ right = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ bottom = obj2.getInt();
+ obj2.free();
+ writePSFmt("%%ALDImageCropRect: %d %d %d %d\n", left, top, right, bottom);
+ }
+ obj1.free();
+
+ dict->lookup("Color", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 5) {
+ obj1.arrayGet(0, &obj2);
+ c = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ m = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ y = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ k = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(4, &obj2);
+ if (obj2.isString()) {
+ writePSFmt("%%ALDImageColor: %g %g %g %g ", c, m, y, k);
+ writePSString(obj2.getString());
+ writePS("\n");
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("ColorType", &obj1);
+ if (obj1.isName()) {
+ writePSFmt("%%ALDImageColorType: %s\n", obj1.getName());
+ }
+ obj1.free();
+
+ //~ ignores 'Comments' entry
+ //~ need to handle multiple lines
+
+ dict->lookup("CropFixed", &obj1);
+ if (obj1.isArray()) {
+ obj1.arrayGet(0, &obj2);
+ ulx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ uly = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ lrx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ lry = obj2.getNum();
+ obj2.free();
+ writePSFmt("%%ALDImageCropFixed: %g %g %g %g\n", ulx, uly, lrx, lry);
+ }
+ obj1.free();
+
+ dict->lookup("GrayMap", &obj1);
+ if (obj1.isArray()) {
+ writePS("%ALDImageGrayMap:");
+ for (i = 0; i < obj1.arrayGetLength(); i += 16) {
+ if (i > 0) {
+ writePS("\n%%+");
+ }
+ for (j = 0; j < 16 && i+j < obj1.arrayGetLength(); ++j) {
+ obj1.arrayGet(i+j, &obj2);
+ writePSFmt(" %d", obj2.getInt());
+ obj2.free();
+ }
+ }
+ writePS("\n");
+ }
+ obj1.free();
+
+ dict->lookup("ID", &obj1);
+ if (obj1.isString()) {
+ writePSFmt("%%ALDImageID: %s\n", obj1.getString()->getCString());
+ }
+ obj1.free();
+
+ dict->lookup("ImageType", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ samples = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ bits = obj2.getInt();
+ obj2.free();
+ writePSFmt("%%ALDImageType: %d %d\n", samples, bits);
+ }
+ obj1.free();
+
+ dict->lookup("Overprint", &obj1);
+ if (obj1.isBool()) {
+ writePSFmt("%%ALDImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
+ }
+ obj1.free();
+
+ dict->lookup("Position", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 8) {
+ obj1.arrayGet(0, &obj2);
+ llx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ lly = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ ulx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ uly = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(4, &obj2);
+ urx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(5, &obj2);
+ ury = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(6, &obj2);
+ lrx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(7, &obj2);
+ lry = obj2.getNum();
+ obj2.free();
+ opiTransform(state, llx, lly, &tllx, &tlly);
+ opiTransform(state, ulx, uly, &tulx, &tuly);
+ opiTransform(state, urx, ury, &turx, &tury);
+ opiTransform(state, lrx, lry, &tlrx, &tlry);
+ writePSFmt("%%ALDImagePosition: %g %g %g %g %g %g %g %g\n",
+ tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry);
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("Resolution", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ horiz = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ vert = obj2.getNum();
+ obj2.free();
+ writePSFmt("%%ALDImageResoution: %g %g\n", horiz, vert);
+ obj2.free();