[poppler] OutputIntents in PDF (was Re: poppler/Gfx.cc poppler/Gfx.h poppler/GfxState.cc poppler/GfxState.h poppler/Page.cc)

Leonard Rosenthol lrosenth at adobe.com
Wed Oct 2 15:00:36 PDT 2013


Remember that you ONLY do this for files that comply with one of the
subset standards (PDF/X, PDF/A, etc.).  An OutputIntent containe in a
"regular" PDF is to be ignored!

Leonard

On 10/2/13 5:36 PM, "Albert Astals Cid" <aacid at kemper.freedesktop.org>
wrote:

> poppler/Gfx.cc      |  114 ++++++++++---
> poppler/Gfx.h       |    8
> poppler/GfxState.cc |  429
>+++++++++++++++++++++++++++++++++++++++++-----------
> poppler/GfxState.h  |   72 ++++++--
> poppler/Page.cc     |    2
> 5 files changed, 490 insertions(+), 135 deletions(-)
>
>New commits:
>commit bd49b3c0c6f2adccc5bda561edbaf9f00ed2917a
>Author: Thomas Freitag <Thomas.Freitag at alfa.de>
>Date:   Wed Oct 2 23:32:09 2013 +0200
>
>    Use icc profile in OutputIntents
>
>    Bug #34053
>
>diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
>index f2971d6..90bf41e 100644
>--- a/poppler/Gfx.cc
>+++ b/poppler/Gfx.cc
>@@ -460,7 +460,7 @@ void GfxResources::lookupColorSpace(const char *name,
>Object *obj) {
>   obj->initNull();
> }
>
>-GfxPattern *GfxResources::lookupPattern(char *name, OutputDev *out) {
>+GfxPattern *GfxResources::lookupPattern(char *name, OutputDev *out,
>GfxState *state) {
>   GfxResources *resPtr;
>   GfxPattern *pattern;
>   Object obj;
>@@ -468,7 +468,7 @@ GfxPattern *GfxResources::lookupPattern(char *name,
>OutputDev *out) {
>   for (resPtr = this; resPtr; resPtr = resPtr->next) {
>     if (resPtr->patternDict.isDict()) {
>       if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) {
>-      pattern = GfxPattern::parse(&obj, out);
>+      pattern = GfxPattern::parse(&obj, out, state);
>       obj.free();
>       return pattern;
>       }
>@@ -479,7 +479,7 @@ GfxPattern *GfxResources::lookupPattern(char *name,
>OutputDev *out) {
>   return NULL;
> }
>
>-GfxShading *GfxResources::lookupShading(char *name, OutputDev *out) {
>+GfxShading *GfxResources::lookupShading(char *name, OutputDev *out,
>GfxState *state) {
>   GfxResources *resPtr;
>   GfxShading *shading;
>   Object obj;
>@@ -487,7 +487,7 @@ GfxShading *GfxResources::lookupShading(char *name,
>OutputDev *out) {
>   for (resPtr = this; resPtr; resPtr = resPtr->next) {
>     if (resPtr->shadingDict.isDict()) {
>       if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) {
>-      shading = GfxShading::parse(&obj, out);
>+      shading = GfxShading::parse(&obj, out, state);
>       obj.free();
>       return shading;
>       }
>@@ -584,6 +584,9 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum,
>Dict *resDict,
>     out->clip(state);
>     state->clearPath();
>   }
>+#ifdef USE_CMS
>+  initDisplayProfile();
>+#endif
> }
>
> Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict,
>@@ -633,8 +636,55 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict
>*resDict,
>     out->clip(state);
>     state->clearPath();
>   }
>+#ifdef USE_CMS
>+  initDisplayProfile();
>+#endif
> }
>
>+#ifdef USE_CMS
>+
>+#ifdef USE_LCMS1
>+#include <lcms.h>
>+#else
>+#include <lcms2.h>
>+#define LCMS_FLAGS cmsFLAGS_NOOPTIMIZE
>+#endif
>+
>+void Gfx::initDisplayProfile() {
>+   Object catDict;
>+   xref->getCatalog(&catDict);
>+   if (catDict.isDict()) {
>+     Object outputIntents;
>+     catDict.dictLookup("OutputIntents", &outputIntents);
>+     if (outputIntents.isArray() && outputIntents.arrayGetLength() == 1)
>{
>+          Object firstElement;
>+          outputIntents.arrayGet(0, &firstElement);
>+          if (firstElement.isDict()) {
>+              Object profile;
>+              firstElement.dictLookup("DestOutputProfile", &profile);
>+              if (profile.isStream()) {
>+                Stream *iccStream = profile.getStream();
>+                int length = 0;
>+                Guchar *profBuf = iccStream->toUnsignedChars(&length,
>65536, 65536);
>+                cmsHPROFILE hp = cmsOpenProfileFromMem(profBuf,length);
>+                if (hp == 0) {
>+                  error(errSyntaxWarning, -1, "read ICCBased color space
>profile error");
>+                } else {
>+                  state->setDisplayProfile(hp);
>+                }
>+                gfree(profBuf);
>+              }
>+              profile.free();
>+          }
>+          firstElement.free();
>+     }
>+     outputIntents.free();
>+   }
>+   catDict.free();
>+}
>+
>+#endif
>+
> Gfx::~Gfx() {
>   while (stateGuards.size()) {
>     popStateGuard();
>@@ -1183,7 +1233,7 @@ void Gfx::opSetExtGState(Object args[], int
>numArgs) {
>         blendingColorSpace = NULL;
>         isolated = knockout = gFalse;
>         if (!obj4.dictLookup("CS", &obj5)->isNull()) {
>-          blendingColorSpace = GfxColorSpace::parse(&obj5, out);
>+          blendingColorSpace = GfxColorSpace::parse(&obj5, out, state);
>         }
>         obj5.free();
>         if (obj4.dictLookup("I", &obj5)->isBool()) {
>@@ -1371,6 +1421,7 @@ void Gfx::doSoftMask(Object *str, GBool alpha,
> }
>
> void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
>+  state->setRenderingIntent(args[0].getName());
> }
>
>
>//------------------------------------------------------------------------
>@@ -1385,7 +1436,7 @@ void Gfx::opSetFillGray(Object args[], int numArgs)
>{
>   state->setFillPattern(NULL);
>   res->lookupColorSpace("DefaultGray", &obj);
>   if (!obj.isNull()) {
>-    colorSpace = GfxColorSpace::parse(&obj, out);
>+    colorSpace = GfxColorSpace::parse(&obj, out, state);
>   }
>   if (colorSpace == NULL) {
>     colorSpace = new GfxDeviceGrayColorSpace();
>@@ -1406,7 +1457,7 @@ void Gfx::opSetStrokeGray(Object args[], int
>numArgs) {
>   state->setStrokePattern(NULL);
>   res->lookupColorSpace("DefaultGray", &obj);
>   if (!obj.isNull()) {
>-    colorSpace = GfxColorSpace::parse(&obj, out);
>+    colorSpace = GfxColorSpace::parse(&obj, out, state);
>   }
>   if (colorSpace == NULL) {
>     colorSpace = new GfxDeviceGrayColorSpace();
>@@ -1427,7 +1478,7 @@ void Gfx::opSetFillCMYKColor(Object args[], int
>numArgs) {
>
>   res->lookupColorSpace("DefaultCMYK", &obj);
>   if (!obj.isNull()) {
>-    colorSpace = GfxColorSpace::parse(&obj, out);
>+    colorSpace = GfxColorSpace::parse(&obj, out, state);
>   }
>   if (colorSpace == NULL) {
>     colorSpace = new GfxDeviceCMYKColorSpace();
>@@ -1452,7 +1503,7 @@ void Gfx::opSetStrokeCMYKColor(Object args[], int
>numArgs) {
>   state->setStrokePattern(NULL);
>   res->lookupColorSpace("DefaultCMYK", &obj);
>   if (!obj.isNull()) {
>-    colorSpace = GfxColorSpace::parse(&obj, out);
>+    colorSpace = GfxColorSpace::parse(&obj, out, state);
>   }
>   if (colorSpace == NULL) {
>     colorSpace = new GfxDeviceCMYKColorSpace();
>@@ -1476,7 +1527,7 @@ void Gfx::opSetFillRGBColor(Object args[], int
>numArgs) {
>   state->setFillPattern(NULL);
>   res->lookupColorSpace("DefaultRGB", &obj);
>   if (!obj.isNull()) {
>-    colorSpace = GfxColorSpace::parse(&obj, out);
>+    colorSpace = GfxColorSpace::parse(&obj, out, state);
>   }
>   if (colorSpace == NULL) {
>     colorSpace = new GfxDeviceRGBColorSpace();
>@@ -1500,7 +1551,7 @@ void Gfx::opSetStrokeRGBColor(Object args[], int
>numArgs) {
>   state->setStrokePattern(NULL);
>   res->lookupColorSpace("DefaultRGB", &obj);
>   if (!obj.isNull()) {
>-    colorSpace = GfxColorSpace::parse(&obj, out);
>+    colorSpace = GfxColorSpace::parse(&obj, out, state);
>   }
>   if (colorSpace == NULL) {
>     colorSpace = new GfxDeviceRGBColorSpace();
>@@ -1522,9 +1573,9 @@ void Gfx::opSetFillColorSpace(Object args[], int
>numArgs) {
>
>   res->lookupColorSpace(args[0].getName(), &obj);
>   if (obj.isNull()) {
>-    colorSpace = GfxColorSpace::parse(&args[0], out);
>+    colorSpace = GfxColorSpace::parse(&args[0], out, state);
>   } else {
>-    colorSpace = GfxColorSpace::parse(&obj, out);
>+    colorSpace = GfxColorSpace::parse(&obj, out, state);
>   }
>   obj.free();
>   if (colorSpace) {
>@@ -1547,9 +1598,9 @@ void Gfx::opSetStrokeColorSpace(Object args[], int
>numArgs) {
>   state->setStrokePattern(NULL);
>   res->lookupColorSpace(args[0].getName(), &obj);
>   if (obj.isNull()) {
>-    colorSpace = GfxColorSpace::parse(&args[0], out);
>+    colorSpace = GfxColorSpace::parse(&args[0], out, state);
>   } else {
>-    colorSpace = GfxColorSpace::parse(&obj, out);
>+    colorSpace = GfxColorSpace::parse(&obj, out, state);
>   }
>   obj.free();
>   if (colorSpace) {
>@@ -1620,7 +1671,7 @@ void Gfx::opSetFillColorN(Object args[], int
>numArgs) {
>     }
>     if (numArgs > 0) {
>       if (args[numArgs-1].isName() &&
>-        (pattern = res->lookupPattern(args[numArgs-1].getName(), out))) {
>+        (pattern = res->lookupPattern(args[numArgs-1].getName(), out,
>state))) {
>         state->setFillPattern(pattern);
>       }
>     }
>@@ -1672,7 +1723,7 @@ void Gfx::opSetStrokeColorN(Object args[], int
>numArgs) {
>       return;
>     }
>     if (args[numArgs-1].isName() &&
>-      (pattern = res->lookupPattern(args[numArgs-1].getName(), out))) {
>+      (pattern = res->lookupPattern(args[numArgs-1].getName(), out, state))) {
>       state->setStrokePattern(pattern);
>     }
>
>@@ -2382,7 +2433,7 @@ void Gfx::opShFill(Object args[], int numArgs) {
>     return;
>   }
>
>-  if (!(shading = res->lookupShading(args[0].getName(), out))) {
>+  if (!(shading = res->lookupShading(args[0].getName(), out, state))) {
>     return;
>   }
>
>@@ -4339,14 +4390,29 @@ void Gfx::doImage(Object *ref, Stream *str, GBool
>inlineImg) {
>       }
>     }
>     if (!obj1.isNull()) {
>-      colorSpace = GfxColorSpace::parse(&obj1, out);
>+      Object objIntent;
>+      char *tempIntent = NULL;
>+      dict->lookup("Intent", &objIntent);
>+      if (objIntent.isName()) {
>+        tempIntent = state->getRenderingIntent();
>+        if (tempIntent != NULL) {
>+          tempIntent = strdup(tempIntent);
>+        }
>+        state->setRenderingIntent(objIntent.getName());
>+      }
>+      colorSpace = GfxColorSpace::parse(&obj1, out, state);
>+      if (objIntent.isName()) {
>+        state->setRenderingIntent(tempIntent);
>+        free(tempIntent);
>+      }
>+      objIntent.free();
>     } else if (csMode == streamCSDeviceGray) {
>       Object objCS;
>       res->lookupColorSpace("DefaultGray", &objCS);
>       if (objCS.isNull()) {
>         colorSpace = new GfxDeviceGrayColorSpace();
>       } else {
>-        colorSpace = GfxColorSpace::parse(&objCS, out);
>+        colorSpace = GfxColorSpace::parse(&objCS, out, state);
>       }
>       objCS.free();
>     } else if (csMode == streamCSDeviceRGB) {
>@@ -4355,7 +4421,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool
>inlineImg) {
>       if (objCS.isNull()) {
>         colorSpace = new GfxDeviceRGBColorSpace();
>       } else {
>-        colorSpace = GfxColorSpace::parse(&objCS, out);
>+        colorSpace = GfxColorSpace::parse(&objCS, out, state);
>       }
>       objCS.free();
>     } else if (csMode == streamCSDeviceCMYK) {
>@@ -4364,7 +4430,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool
>inlineImg) {
>       if (objCS.isNull()) {
>         colorSpace = new GfxDeviceCMYKColorSpace();
>       } else {
>-        colorSpace = GfxColorSpace::parse(&objCS, out);
>+        colorSpace = GfxColorSpace::parse(&objCS, out, state);
>       }
>       objCS.free();
>     } else {
>@@ -4459,7 +4525,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool
>inlineImg) {
>         obj2.free();
>       }
>       }
>-      maskColorSpace = GfxColorSpace::parse(&obj1, out);
>+      maskColorSpace = GfxColorSpace::parse(&obj1, out, state);
>       obj1.free();
>       if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) {
>       goto err1;
>@@ -4755,7 +4821,7 @@ void Gfx::doForm(Object *str) {
>   if (dict->lookup("Group", &obj1)->isDict()) {
>     if (obj1.dictLookup("S", &obj2)->isName("Transparency")) {
>       if (!obj1.dictLookup("CS", &obj3)->isNull()) {
>-      blendingColorSpace = GfxColorSpace::parse(&obj3, out);
>+      blendingColorSpace = GfxColorSpace::parse(&obj3, out, state);
>       }
>       obj3.free();
>       if (obj1.dictLookup("I", &obj3)->isBool()) {
>diff --git a/poppler/Gfx.h b/poppler/Gfx.h
>index aba3b7e..a82f9f4 100644
>--- a/poppler/Gfx.h
>+++ b/poppler/Gfx.h
>@@ -117,8 +117,8 @@ public:
>   GBool lookupXObjectNF(char *name, Object *obj);
>   GBool lookupMarkedContentNF(char *name, Object *obj);
>   void lookupColorSpace(const char *name, Object *obj);
>-  GfxPattern *lookupPattern(char *name, OutputDev *out);
>-  GfxShading *lookupShading(char *name, OutputDev *out);
>+  GfxPattern *lookupPattern(char *name, OutputDev *out, GfxState *state);
>+  GfxShading *lookupShading(char *name, OutputDev *out, GfxState *state);
>   GBool lookupGState(char *name, Object *obj);
>   GBool lookupGStateNF(char *name, Object *obj);
>
>@@ -156,7 +156,9 @@ public:
>       PDFRectangle *box, PDFRectangle *cropBox,
>       GBool (*abortCheckCbkA)(void *data) = NULL,
>       void *abortCheckCbkDataA = NULL, XRef *xrefA = NULL);
>-
>+#ifdef USE_CMS
>+  void initDisplayProfile();
>+#endif
>   ~Gfx();
>
>   XRef *getXRef() { return xref; }
>diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
>index 11540ad..8a53ee4 100644
>--- a/poppler/GfxState.cc
>+++ b/poppler/GfxState.cc
>@@ -201,9 +201,11 @@ void GfxColorTransform::doTransform(void *in, void
>*out, unsigned int size) {
> }
>
> // transformA should be a cmsHTRANSFORM
>-GfxColorTransform::GfxColorTransform(void *transformA) {
>+GfxColorTransform::GfxColorTransform(void *transformA, int cmsIntentA,
>unsigned int transformPixelTypeA) {
>   transform = transformA;
>   refCount = 1;
>+  cmsIntent = cmsIntentA;
>+  transformPixelType = transformPixelTypeA;
> }
>
> GfxColorTransform::~GfxColorTransform() {
>@@ -231,6 +233,25 @@ static cmsHPROFILE loadColorProfile(const char
>*fileName);
>
> void GfxColorSpace::setDisplayProfile(void *displayProfileA) {
>   displayProfile = displayProfileA;
>+  if (displayProfile != NULL) {
>+    cmsHTRANSFORM transform;
>+    unsigned int nChannels;
>+
>+    displayPixelType =
>getCMSColorSpaceType(cmsGetColorSpace(displayProfile));
>+    nChannels = getCMSNChannels(cmsGetColorSpace(displayProfile));
>+    // create transform from XYZ
>+    cmsHPROFILE XYZProfile = cmsCreateXYZProfile();
>+    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
>+         displayProfile,
>+         COLORSPACE_SH(displayPixelType) |
>+           CHANNELS_SH(nChannels) | BYTES_SH(1),
>+        INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == 0) {
>+      error(errSyntaxWarning, -1, "Can't create Lab transform");
>+    } else {
>+      XYZ2DisplayTransform = new GfxColorTransform(transform,
>INTENT_RELATIVE_COLORIMETRIC, displayPixelType);
>+    }
>+    cmsCloseProfile(XYZProfile);
>+  }
> }
>
> void GfxColorSpace::setDisplayProfileName(GooString *name) {
>@@ -259,7 +280,7 @@ GfxColorSpace::GfxColorSpace() {
> GfxColorSpace::~GfxColorSpace() {
> }
>
>-GfxColorSpace *GfxColorSpace::parse(Object *csObj, OutputDev *out, int
>recursion) {
>+GfxColorSpace *GfxColorSpace::parse(Object *csObj, OutputDev *out,
>GfxState *state, int recursion) {
>   GfxColorSpace *cs;
>   Object obj1;
>
>@@ -290,21 +311,21 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj,
>OutputDev *out, int recursion
>     } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
>       cs = new GfxDeviceCMYKColorSpace();
>     } else if (obj1.isName("CalGray")) {
>-      cs = GfxCalGrayColorSpace::parse(csObj->getArray());
>+      cs = GfxCalGrayColorSpace::parse(csObj->getArray(), state);
>     } else if (obj1.isName("CalRGB")) {
>-      cs = GfxCalRGBColorSpace::parse(csObj->getArray());
>+      cs = GfxCalRGBColorSpace::parse(csObj->getArray(), state);
>     } else if (obj1.isName("Lab")) {
>-      cs = GfxLabColorSpace::parse(csObj->getArray());
>+      cs = GfxLabColorSpace::parse(csObj->getArray(), state);
>     } else if (obj1.isName("ICCBased")) {
>-      cs = GfxICCBasedColorSpace::parse(csObj->getArray(), out,
>recursion);
>+      cs = GfxICCBasedColorSpace::parse(csObj->getArray(), out, state,
>recursion);
>     } else if (obj1.isName("Indexed") || obj1.isName("I")) {
>-      cs = GfxIndexedColorSpace::parse(csObj->getArray(), out,
>recursion);
>+      cs = GfxIndexedColorSpace::parse(csObj->getArray(), out, state,
>recursion);
>     } else if (obj1.isName("Separation")) {
>-      cs = GfxSeparationColorSpace::parse(csObj->getArray(), out,
>recursion);
>+      cs = GfxSeparationColorSpace::parse(csObj->getArray(), out, state,
>recursion);
>     } else if (obj1.isName("DeviceN")) {
>-      cs = GfxDeviceNColorSpace::parse(csObj->getArray(), out,
>recursion);
>+      cs = GfxDeviceNColorSpace::parse(csObj->getArray(), out, state,
>recursion);
>     } else if (obj1.isName("Pattern")) {
>-      cs = GfxPatternColorSpace::parse(csObj->getArray(), out,
>recursion);
>+      cs = GfxPatternColorSpace::parse(csObj->getArray(), out, state,
>recursion);
>     } else {
>       error(errSyntaxWarning, -1, "Bad color space");
>     }
>@@ -423,13 +444,13 @@ int GfxColorSpace::setupColorProfiles()
>     // create transform from XYZ
>     cmsHPROFILE XYZProfile = cmsCreateXYZProfile();
>     if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
>-         displayProfile,
>+         displayProfile,
>          COLORSPACE_SH(displayPixelType) |
>            CHANNELS_SH(nChannels) | BYTES_SH(1),
>         INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == 0) {
>       error(errSyntaxWarning, -1, "Can't create Lab transform");
>     } else {
>-      XYZ2DisplayTransform = new GfxColorTransform(transform);
>+      XYZ2DisplayTransform = new GfxColorTransform(transform,
>INTENT_RELATIVE_COLORIMETRIC, displayPixelType);
>     }
>     cmsCloseProfile(XYZProfile);
>   }
>@@ -651,6 +672,11 @@ GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
> }
>
> GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
>+#ifdef USE_CMS
>+  if (transform != NULL) {
>+    if (transform->unref() == 0) delete transform;
>+  }
>+#endif
> }
>
> GfxColorSpace *GfxCalGrayColorSpace::copy() {
>@@ -664,6 +690,10 @@ GfxColorSpace *GfxCalGrayColorSpace::copy() {
>   cs->blackY = blackY;
>   cs->blackZ = blackZ;
>   cs->gamma = gamma;
>+#ifdef USE_CMS
>+  cs->transform = transform;
>+  if (transform != NULL) transform->ref();
>+#endif
>   return cs;
> }
>
>@@ -675,7 +705,7 @@ static const double xyzrgb[3][3] = {
>   {  0.055643, -0.204026,  1.057229 }
> };
>
>-GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
>+GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr, GfxState *state) {
>   GfxCalGrayColorSpace *cs;
>   Object obj1, obj2, obj3;
>
>@@ -733,7 +763,10 @@ GfxColorSpace *GfxCalGrayColorSpace::parse(Array
>*arr) {
>   cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
>               xyzrgb[2][1] * cs->whiteY +
>               xyzrgb[2][2] * cs->whiteZ);
>-
>+#ifdef USE_CMS
>+  cs->transform = (state != NULL) ? state->getXYZ2DisplayTransform() :
>XYZ2DisplayTransform;
>+  if (cs->transform != NULL) cs->transform->ref();
>+#endif
>   return cs;
> }
>
>@@ -752,7 +785,7 @@ void GfxCalGrayColorSpace::getGray(GfxColor *color,
>GfxGray *gray) {
>   GfxRGB rgb;
>
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_GRAY) {
>+  if (transform != NULL && transform->getTransformPixelType() ==
>PT_GRAY) {
>     Guchar out[gfxColorMaxComps];
>     double in[gfxColorMaxComps];
>     double X, Y, Z;
>@@ -761,7 +794,7 @@ void GfxCalGrayColorSpace::getGray(GfxColor *color,
>GfxGray *gray) {
>     in[0] = clip01(X);
>     in[1] = clip01(Y);
>     in[2] = clip01(Z);
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     *gray = byteToCol(out[0]);
>     return;
>   }
>@@ -778,14 +811,14 @@ void GfxCalGrayColorSpace::getRGB(GfxColor *color,
>GfxRGB *rgb) {
>
>   getXYZ(color,&X,&Y,&Z);
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_RGB) {
>+  if (transform != NULL && transform->getTransformPixelType() == PT_RGB)
>{
>     Guchar out[gfxColorMaxComps];
>     double in[gfxColorMaxComps];
>
>     in[0] = clip01(X);
>     in[1] = clip01(Y);
>     in[2] = clip01(Z);
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     rgb->r = byteToCol(out[0]);
>     rgb->g = byteToCol(out[1]);
>     rgb->b = byteToCol(out[2]);
>@@ -809,7 +842,7 @@ void GfxCalGrayColorSpace::getCMYK(GfxColor *color,
>GfxCMYK *cmyk) {
>   GfxColorComp c, m, y, k;
>
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_CMYK) {
>+  if (transform != NULL && transform->getTransformPixelType() ==
>PT_CMYK) {
>     double in[gfxColorMaxComps];
>     Guchar out[gfxColorMaxComps];
>     double X, Y, Z;
>@@ -819,7 +852,7 @@ void GfxCalGrayColorSpace::getCMYK(GfxColor *color,
>GfxCMYK *cmyk) {
>     in[1] = clip01(Y);
>     in[2] = clip01(Z);
>
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     cmyk->c = byteToCol(out[0]);
>     cmyk->m = byteToCol(out[1]);
>     cmyk->y = byteToCol(out[2]);
>@@ -1017,6 +1050,11 @@ GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
> }
>
> GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
>+#ifdef USE_CMS
>+  if (transform != NULL) {
>+    if (transform->unref() == 0) delete transform;
>+  }
>+#endif
> }
>
> GfxColorSpace *GfxCalRGBColorSpace::copy() {
>@@ -1036,10 +1074,14 @@ GfxColorSpace *GfxCalRGBColorSpace::copy() {
>   for (i = 0; i < 9; ++i) {
>     cs->mat[i] = mat[i];
>   }
>+#ifdef USE_CMS
>+  cs->transform = transform;
>+  if (transform != NULL) transform->ref();
>+#endif
>   return cs;
> }
>
>-GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
>+GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr, GfxState *state) {
>   GfxCalRGBColorSpace *cs;
>   Object obj1, obj2, obj3;
>   int i;
>@@ -1121,6 +1163,10 @@ GfxColorSpace *GfxCalRGBColorSpace::parse(Array
>*arr) {
>               xyzrgb[2][1] * cs->whiteY +
>               xyzrgb[2][2] * cs->whiteZ);
>
>+#ifdef USE_CMS
>+  cs->transform = (state != NULL) ? state->getXYZ2DisplayTransform() :
>XYZ2DisplayTransform;
>+  if (cs->transform != NULL) cs->transform->ref();
>+#endif
>   return cs;
> }
>
>@@ -1141,7 +1187,7 @@ void GfxCalRGBColorSpace::getGray(GfxColor *color,
>GfxGray *gray) {
>   GfxRGB rgb;
>
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_GRAY) {
>+  if (transform != NULL && transform->getTransformPixelType() ==
>PT_GRAY) {
>     Guchar out[gfxColorMaxComps];
>     double in[gfxColorMaxComps];
>     double X, Y, Z;
>@@ -1150,7 +1196,7 @@ void GfxCalRGBColorSpace::getGray(GfxColor *color,
>GfxGray *gray) {
>     in[0] = clip01(X);
>     in[1] = clip01(Y);
>     in[2] = clip01(Z);
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     *gray = byteToCol(out[0]);
>     return;
>   }
>@@ -1167,14 +1213,14 @@ void GfxCalRGBColorSpace::getRGB(GfxColor *color,
>GfxRGB *rgb) {
>
>   getXYZ(color,&X,&Y,&Z);
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_RGB) {
>+  if (transform != NULL && transform->getTransformPixelType() == PT_RGB)
>{
>     Guchar out[gfxColorMaxComps];
>     double in[gfxColorMaxComps];
>
>     in[0] = clip01(X/whiteX);
>     in[1] = clip01(Y/whiteY);
>     in[2] = clip01(Z/whiteZ);
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     rgb->r = byteToCol(out[0]);
>     rgb->g = byteToCol(out[1]);
>     rgb->b = byteToCol(out[2]);
>@@ -1195,7 +1241,7 @@ void GfxCalRGBColorSpace::getCMYK(GfxColor *color,
>GfxCMYK *cmyk) {
>   GfxColorComp c, m, y, k;
>
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_CMYK) {
>+  if (transform != NULL && transform->getTransformPixelType() ==
>PT_CMYK) {
>     double in[gfxColorMaxComps];
>     Guchar out[gfxColorMaxComps];
>     double X, Y, Z;
>@@ -1204,7 +1250,7 @@ void GfxCalRGBColorSpace::getCMYK(GfxColor *color,
>GfxCMYK *cmyk) {
>     in[0] = clip01(X);
>     in[1] = clip01(Y);
>     in[2] = clip01(Z);
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     cmyk->c = byteToCol(out[0]);
>     cmyk->m = byteToCol(out[1]);
>     cmyk->y = byteToCol(out[2]);
>@@ -1391,6 +1437,11 @@ GfxLabColorSpace::GfxLabColorSpace() {
> }
>
> GfxLabColorSpace::~GfxLabColorSpace() {
>+#ifdef USE_CMS
>+  if (transform != NULL) {
>+    if (transform->unref() == 0) delete transform;
>+  }
>+#endif
> }
>
> GfxColorSpace *GfxLabColorSpace::copy() {
>@@ -1410,10 +1461,14 @@ GfxColorSpace *GfxLabColorSpace::copy() {
>   cs->kr = kr;
>   cs->kg = kg;
>   cs->kb = kb;
>+#ifdef USE_CMS
>+  cs->transform = transform;
>+  if (transform != NULL) transform->ref();
>+#endif
>   return cs;
> }
>
>-GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
>+GfxColorSpace *GfxLabColorSpace::parse(Array *arr, GfxState *state) {
>   GfxLabColorSpace *cs;
>   Object obj1, obj2, obj3;
>
>@@ -1478,6 +1533,10 @@ GfxColorSpace *GfxLabColorSpace::parse(Array *arr)
>{
>               xyzrgb[2][1] * cs->whiteY +
>               xyzrgb[2][2] * cs->whiteZ);
>
>+#ifdef USE_CMS
>+  cs->transform = (state != NULL) ? state->getXYZ2DisplayTransform() :
>XYZ2DisplayTransform;
>+  if (cs->transform != NULL) cs->transform->ref();
>+#endif
>   return cs;
> }
>
>@@ -1485,12 +1544,12 @@ void GfxLabColorSpace::getGray(GfxColor *color,
>GfxGray *gray) {
>   GfxRGB rgb;
>
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_GRAY) {
>+  if (transform != NULL && transform->getTransformPixelType() ==
>PT_GRAY) {
>     Guchar out[gfxColorMaxComps];
>     double in[gfxColorMaxComps];
>
>     getXYZ(color, &in[0], &in[1], &in[2]);
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     *gray = byteToCol(out[0]);
>     return;
>   }
>@@ -1537,18 +1596,40 @@ void GfxLabColorSpace::getRGB(GfxColor *color,
>GfxRGB *rgb) {
>
>   getXYZ(color, &X, &Y, &Z);
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_RGB) {
>+  if (transform != NULL && transform->getTransformPixelType() == PT_RGB)
>{
>     Guchar out[gfxColorMaxComps];
>     double in[gfxColorMaxComps];
>
>     in[0] = clip01(X);
>     in[1] = clip01(Y);
>     in[2] = clip01(Z);
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     rgb->r = byteToCol(out[0]);
>     rgb->g = byteToCol(out[1]);
>     rgb->b = byteToCol(out[2]);
>     return;
>+  } else if (transform != NULL && transform->getTransformPixelType() ==
>PT_CMYK) {
>+    Guchar out[gfxColorMaxComps];
>+    double in[gfxColorMaxComps];
>+    double c, m, y, k, c1, m1, y1, k1, r, g, b;
>+
>+    in[0] = clip01(X);
>+    in[1] = clip01(Y);
>+    in[2] = clip01(Z);
>+    transform->doTransform(in,out,1);
>+    c = byteToDbl(out[0]);
>+    m = byteToDbl(out[1]);
>+    y = byteToDbl(out[2]);
>+    k = byteToDbl(out[3]);
>+    c1 = 1 - c;
>+    m1 = 1 - m;
>+    y1 = 1 - y;
>+    k1 = 1 - k;
>+    cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b);
>+    rgb->r = clip01(dblToCol(r));
>+    rgb->g = clip01(dblToCol(g));
>+    rgb->b = clip01(dblToCol(b));
>+    return;
>   }
> #endif
>   X *= whiteX;
>@@ -1568,12 +1649,12 @@ void GfxLabColorSpace::getCMYK(GfxColor *color,
>GfxCMYK *cmyk) {
>   GfxColorComp c, m, y, k;
>
> #ifdef USE_CMS
>-  if (XYZ2DisplayTransform != NULL && displayPixelType == PT_CMYK) {
>+  if (transform != NULL && transform->getTransformPixelType() ==
>PT_CMYK) {
>     double in[gfxColorMaxComps];
>     Guchar out[gfxColorMaxComps];
>
>     getXYZ(color, &in[0], &in[1], &in[2]);
>-    XYZ2DisplayTransform->doTransform(in,out,1);
>+    transform->doTransform(in,out,1);
>     cmyk->c = byteToCol(out[0]);
>     cmyk->m = byteToCol(out[1]);
>     cmyk->y = byteToCol(out[2]);
>@@ -1716,7 +1797,7 @@ GfxColorSpace *GfxICCBasedColorSpace::copy() {
>   return cs;
> }
>
>-GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out,
>int recursion) {
>+GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out,
>GfxState *state, int recursion) {
>   GfxICCBasedColorSpace *cs;
>   Ref iccProfileStreamA;
>   int nCompsA;
>@@ -1745,7 +1826,24 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array
>*arr, OutputDev *out, int recu
>     if (item != NULL)
>     {
>       cs = static_cast<GfxICCBasedColorSpace*>(item->cs->copy());
>-      return cs;
>+      int transformIntent = cs->getIntent();
>+      int cmsIntent = INTENT_RELATIVE_COLORIMETRIC;
>+      if (state != NULL) {
>+        const char *intent = state->getRenderingIntent();
>+        if (intent != NULL) {
>+          if (strcmp(intent, "AbsoluteColorimetric") == 0) {
>+            cmsIntent = INTENT_ABSOLUTE_COLORIMETRIC;
>+          } else if (strcmp(intent, "Saturation") == 0) {
>+            cmsIntent = INTENT_SATURATION;
>+          } else if (strcmp(intent, "Perceptual") == 0) {
>+            cmsIntent = INTENT_PERCEPTUAL;
>+          }
>+        }
>+      }
>+      if (transformIntent == cmsIntent) {
>+        return cs;
>+      }
>+      delete cs;
>     }
>   }
> #endif
>@@ -1771,7 +1869,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array
>*arr, OutputDev *out, int recu
>     nCompsA = 4;
>   }
>   if (dict->lookup("Alternate", &obj2)->isNull() ||
>-      !(altA = GfxColorSpace::parse(&obj2, out, recursion + 1))) {
>+      !(altA = GfxColorSpace::parse(&obj2, out, state, recursion + 1))) {
>     switch (nCompsA) {
>     case 1:
>       altA = new GfxDeviceGrayColorSpace();
>@@ -1821,32 +1919,46 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array
>*arr, OutputDev *out, int recu
>   if (hp == 0) {
>     error(errSyntaxWarning, -1, "read ICCBased color space profile
>error");
>   } else {
>-    cmsHPROFILE dhp = displayProfile;
>+    cmsHPROFILE dhp = (state != NULL && state->getDisplayProfile() !=
>NULL) ? state->getDisplayProfile() : displayProfile;
>     if (dhp == NULL) dhp = RGBProfile;
>     unsigned int cst = getCMSColorSpaceType(cmsGetColorSpace(hp));
>     unsigned int dNChannels = getCMSNChannels(cmsGetColorSpace(dhp));
>     unsigned int dcst = getCMSColorSpaceType(cmsGetColorSpace(dhp));
>     cmsHTRANSFORM transform;
>+
>+    int cmsIntent = INTENT_RELATIVE_COLORIMETRIC;
>+    if (state != NULL) {
>+      const char *intent = state->getRenderingIntent();
>+      if (intent != NULL) {
>+        if (strcmp(intent, "AbsoluteColorimetric") == 0) {
>+          cmsIntent = INTENT_ABSOLUTE_COLORIMETRIC;
>+        } else if (strcmp(intent, "Saturation") == 0) {
>+          cmsIntent = INTENT_SATURATION;
>+        } else if (strcmp(intent, "Perceptual") == 0) {
>+          cmsIntent = INTENT_PERCEPTUAL;
>+        }
>+      }
>+    }
>     if ((transform = cmsCreateTransform(hp,
>          COLORSPACE_SH(cst) |CHANNELS_SH(nCompsA) | BYTES_SH(1),
>          dhp,
>          COLORSPACE_SH(dcst) |
>            CHANNELS_SH(dNChannels) | BYTES_SH(1),
>-        INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == 0) {
>+         cmsIntent, LCMS_FLAGS)) == 0) {
>       error(errSyntaxWarning, -1, "Can't create transform");
>       cs->transform = NULL;
>     } else {
>-      cs->transform = new GfxColorTransform(transform);
>+      cs->transform = new GfxColorTransform(transform, cmsIntent, dcst);
>     }
>-    if (dcst == PT_RGB) {
>+    if (dcst == PT_RGB || dcst == PT_CMYK) {
>        // create line transform only when the display is RGB type color
>space
>       if ((transform = cmsCreateTransform(hp,
>           CHANNELS_SH(nCompsA) | BYTES_SH(1),dhp,
>-          TYPE_RGB_8,INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == 0) {
>+          (dcst == PT_RGB) ? TYPE_RGB_8 : TYPE_CMYK_8, cmsIntent,
>LCMS_FLAGS)) == 0) {
>       error(errSyntaxWarning, -1, "Can't create transform");
>       cs->lineTransform = NULL;
>       } else {
>-      cs->lineTransform = new GfxColorTransform(transform);
>+      cs->lineTransform = new GfxColorTransform(transform, cmsIntent, dcst);
>       }
>     }
>     cmsCloseProfile(hp);
>@@ -1864,7 +1976,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array
>*arr, OutputDev *out, int recu
>
> void GfxICCBasedColorSpace::getGray(GfxColor *color, GfxGray *gray) {
> #ifdef USE_CMS
>-  if (transform != 0 && displayPixelType == PT_GRAY) {
>+  if (transform != 0 && transform->getTransformPixelType() == PT_GRAY) {
>     Guchar in[gfxColorMaxComps];
>     Guchar out[gfxColorMaxComps];
>
>@@ -1907,8 +2019,7 @@ void GfxICCBasedColorSpace::getGray(GfxColor
>*color, GfxGray *gray) {
>
> void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
> #ifdef USE_CMS
>-  if (transform != 0
>-       && (displayProfile == NULL || displayPixelType == PT_RGB)) {
>+  if (transform != 0 && transform->getTransformPixelType() == PT_RGB) {
>     Guchar in[gfxColorMaxComps];
>     Guchar out[gfxColorMaxComps];
>
>@@ -1941,11 +2052,10 @@ void GfxICCBasedColorSpace::getRGB(GfxColor
>*color, GfxRGB *rgb) {
>       unsigned int value = (out[0] << 16) + (out[1] << 8) + out[2];
>       cmsCache.insert(std::pair<unsigned int, unsigned int>(key, value));
>     }
>-  } else if (transform != 0
>-       && (displayProfile == NULL || displayPixelType == PT_CMYK)) {
>+  } else if (transform != NULL && transform->getTransformPixelType() ==
>PT_CMYK) {
>     Guchar in[gfxColorMaxComps];
>     Guchar out[gfxColorMaxComps];
>-    double c, m, y, k, c1, m1, y1, k1, r, g, b;
>+    double c, m, y, k, c1, m1, y1, k1, r, g, b;
>
>     for (int i = 0;i < nComps;i++) {
>       in[i] = colToByte(color->c[i]);
>@@ -1996,7 +2106,7 @@ void GfxICCBasedColorSpace::getRGB(GfxColor *color,
>GfxRGB *rgb) {
> void GfxICCBasedColorSpace::getRGBLine(Guchar *in, unsigned int *out,
>                                      int length) {
> #ifdef USE_CMS
>-  if (lineTransform != 0) {
>+  if (lineTransform != 0 && lineTransform->getTransformPixelType() ==
>PT_RGB) {
>     Guchar* tmp = (Guchar *)gmallocn(3 * length, sizeof(Guchar));
>     lineTransform->doTransform(in, tmp, length);
>     for (int i = 0; i < length; ++i) {
>@@ -2014,7 +2124,7 @@ void GfxICCBasedColorSpace::getRGBLine(Guchar *in,
>unsigned int *out,
>
> void GfxICCBasedColorSpace::getRGBLine(Guchar *in, Guchar *out, int
>length) {
> #ifdef USE_CMS
>-  if (lineTransform != 0) {
>+  if (lineTransform != 0 && lineTransform->getTransformPixelType() ==
>PT_RGB) {
>     Guchar* tmp = (Guchar *)gmallocn(3 * length, sizeof(Guchar));
>     lineTransform->doTransform(in, tmp, length);
>     Guchar *current = tmp;
>@@ -2024,6 +2134,26 @@ void GfxICCBasedColorSpace::getRGBLine(Guchar *in,
>Guchar *out, int length) {
>         *out++ = *current++;
>     }
>     gfree(tmp);
>+  } else if (lineTransform != NULL &&
>lineTransform->getTransformPixelType() == PT_CMYK) {
>+    Guchar* tmp = (Guchar *)gmallocn(4 * length, sizeof(Guchar));
>+    lineTransform->doTransform(in, tmp, length);
>+    Guchar *current = tmp;
>+    double c, m, y, k, c1, m1, y1, k1, r, g, b;
>+    for (int i = 0; i < length; ++i) {
>+      c = byteToDbl(*current++);
>+      m = byteToDbl(*current++);
>+      y = byteToDbl(*current++);
>+      k = byteToDbl(*current++);
>+      c1 = 1 - c;
>+      m1 = 1 - m;
>+      y1 = 1 - y;
>+      k1 = 1 - k;
>+      cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b);
>+      *out++ = dblToByte(r);
>+      *out++ = dblToByte(g);
>+      *out++ = dblToByte(b);
>+    }
>+    gfree(tmp);
>   } else {
>     alt->getRGBLine(in, out, length);
>   }
>@@ -2034,7 +2164,7 @@ void GfxICCBasedColorSpace::getRGBLine(Guchar *in,
>Guchar *out, int length) {
>
> void GfxICCBasedColorSpace::getRGBXLine(Guchar *in, Guchar *out, int
>length) {
> #ifdef USE_CMS
>-  if (lineTransform != 0) {
>+  if (lineTransform != 0 && lineTransform->getTransformPixelType() ==
>PT_RGB) {
>     Guchar* tmp = (Guchar *)gmallocn(3 * length, sizeof(Guchar));
>     lineTransform->doTransform(in, tmp, length);
>     Guchar *current = tmp;
>@@ -2055,7 +2185,7 @@ void GfxICCBasedColorSpace::getRGBXLine(Guchar *in,
>Guchar *out, int length) {
>
> void GfxICCBasedColorSpace::getCMYKLine(Guchar *in, Guchar *out, int
>length) {
> #ifdef USE_CMS
>-  if (lineTransform != NULL && displayPixelType == PT_CMYK) {
>+  if (lineTransform != NULL && lineTransform->getTransformPixelType() ==
>PT_CMYK) {
>     transform->doTransform(in,out,length);
>   } else if (lineTransform != NULL) {
>     GfxColorComp c, m, y, k;
>@@ -2089,7 +2219,7 @@ void GfxICCBasedColorSpace::getCMYKLine(Guchar *in,
>Guchar *out, int length) {
>
> void GfxICCBasedColorSpace::getDeviceNLine(Guchar *in, Guchar *out, int
>length) {
> #ifdef USE_CMS
>-  if (lineTransform != NULL && displayPixelType == PT_CMYK) {
>+  if (lineTransform != NULL && lineTransform->getTransformPixelType() ==
>PT_CMYK) {
>     Guchar* tmp = (Guchar *)gmallocn(4 * length, sizeof(Guchar));
>     transform->doTransform(in,tmp,length);
>     Guchar *p = tmp;
>@@ -2135,7 +2265,7 @@ void GfxICCBasedColorSpace::getDeviceNLine(Guchar
>*in, Guchar *out, int length)
>
> void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
> #ifdef USE_CMS
>-  if (transform != NULL && displayPixelType == PT_CMYK) {
>+  if (transform != NULL && transform->getTransformPixelType() ==
>PT_CMYK) {
>     Guchar in[gfxColorMaxComps];
>     Guchar out[gfxColorMaxComps];
>
>@@ -2288,7 +2418,7 @@ GfxColorSpace *GfxIndexedColorSpace::copy() {
>   return cs;
> }
>
>-GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, OutputDev *out,
>int recursion) {
>+GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, OutputDev *out,
>GfxState *state, int recursion) {
>   GfxIndexedColorSpace *cs;
>   GfxColorSpace *baseA;
>   int indexHighA;
>@@ -2301,7 +2431,7 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array
>*arr, OutputDev *out, int recur
>     goto err1;
>   }
>   arr->get(1, &obj1);
>-  if (!(baseA = GfxColorSpace::parse(&obj1, out, recursion + 1))) {
>+  if (!(baseA = GfxColorSpace::parse(&obj1, out, state, recursion + 1)))
>{
>     error(errSyntaxWarning, -1, "Bad Indexed color space (base color
>space)");
>     goto err2;
>   }
>@@ -2553,7 +2683,7 @@ GfxColorSpace *GfxSeparationColorSpace::copy() {
> }
>
> //~ handle the 'All' and 'None' colorants
>-GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, OutputDev
>*out, int recursion) {
>+GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, OutputDev
>*out, GfxState *state, int recursion) {
>   GfxSeparationColorSpace *cs;
>   GooString *nameA;
>   GfxColorSpace *altA;
>@@ -2571,7 +2701,7 @@ GfxColorSpace *GfxSeparationColorSpace::parse(Array
>*arr, OutputDev *out, int re
>   nameA = new GooString(obj1.getName());
>   obj1.free();
>   arr->get(2, &obj1);
>-  if (!(altA = GfxColorSpace::parse(&obj1, out, recursion + 1))) {
>+  if (!(altA = GfxColorSpace::parse(&obj1, out, state, recursion + 1))) {
>     error(errSyntaxWarning, -1, "Bad Separation color space (alternate
>color space)");
>     goto err3;
>   }
>@@ -2802,7 +2932,7 @@ GfxColorSpace *GfxDeviceNColorSpace::copy() {
> }
>
> //~ handle the 'None' colorant
>-GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, OutputDev *out,
>int recursion) {
>+GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, OutputDev *out,
>GfxState *state, int recursion) {
>   GfxDeviceNColorSpace *cs;
>   int nCompsA;
>   GooString *namesA[gfxColorMaxComps];
>@@ -2837,7 +2967,7 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array
>*arr, OutputDev *out, int recur
>   }
>   obj1.free();
>   arr->get(2, &obj1);
>-  if (!(altA = GfxColorSpace::parse(&obj1, out, recursion + 1))) {
>+  if (!(altA = GfxColorSpace::parse(&obj1, out, state, recursion + 1))) {
>     error(errSyntaxWarning, -1, "Bad DeviceN color space (alternate
>color space)");
>     goto err3;
>   }
>@@ -2860,7 +2990,7 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array
>*arr, OutputDev *out, int recur
>         Object obj3;
>         colorants->getVal(i, &obj3);
>         if (obj3.isArray()) {
>-
>separationList->append(GfxSeparationColorSpace::parse(obj3.getArray(),
>out, recursion));
>+
>separationList->append(GfxSeparationColorSpace::parse(obj3.getArray(),
>out, state, recursion));
>         } else {
>           obj3.free();
>           obj2.free();
>@@ -3068,7 +3198,7 @@ GfxColorSpace *GfxPatternColorSpace::copy() {
>                                         (GfxColorSpace *)NULL);
> }
>
>-GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, OutputDev *out,
>int recursion) {
>+GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, OutputDev *out,
>GfxState *state, int recursion) {
>   GfxPatternColorSpace *cs;
>   GfxColorSpace *underA;
>   Object obj1;
>@@ -3080,7 +3210,7 @@ GfxColorSpace *GfxPatternColorSpace::parse(Array
>*arr, OutputDev *out, int recur
>   underA = NULL;
>   if (arr->getLength() == 2) {
>     arr->get(1, &obj1);
>-    if (!(underA = GfxColorSpace::parse(&obj1, out, recursion + 1))) {
>+    if (!(underA = GfxColorSpace::parse(&obj1, out, state, recursion +
>1))) {
>       error(errSyntaxWarning, -1, "Bad Pattern color space (underlying
>color space)");
>       obj1.free();
>       return NULL;
>@@ -3125,7 +3255,7 @@ GfxPattern::GfxPattern(int typeA) {
> GfxPattern::~GfxPattern() {
> }
>
>-GfxPattern *GfxPattern::parse(Object *obj, OutputDev *out) {
>+GfxPattern *GfxPattern::parse(Object *obj, OutputDev *out, GfxState
>*state) {
>   GfxPattern *pattern;
>   Object obj1;
>
>@@ -3140,7 +3270,7 @@ GfxPattern *GfxPattern::parse(Object *obj,
>OutputDev *out) {
>   if (obj1.isInt() && obj1.getInt() == 1) {
>     pattern = GfxTilingPattern::parse(obj);
>   } else if (obj1.isInt() && obj1.getInt() == 2) {
>-    pattern = GfxShadingPattern::parse(obj, out);
>+    pattern = GfxShadingPattern::parse(obj, out, state);
>   }
>   obj1.free();
>   return pattern;
>@@ -3268,7 +3398,7 @@ GfxPattern *GfxTilingPattern::copy() {
> // GfxShadingPattern
>
>//------------------------------------------------------------------------
>
>-GfxShadingPattern *GfxShadingPattern::parse(Object *patObj, OutputDev
>*out) {
>+GfxShadingPattern *GfxShadingPattern::parse(Object *patObj, OutputDev
>*out, GfxState *state) {
>   Dict *dict;
>   GfxShading *shadingA;
>   double matrixA[6];
>@@ -3281,7 +3411,7 @@ GfxShadingPattern *GfxShadingPattern::parse(Object
>*patObj, OutputDev *out) {
>   dict = patObj->getDict();
>
>   dict->lookup("Shading", &obj1);
>-  shadingA = GfxShading::parse(&obj1, out);
>+  shadingA = GfxShading::parse(&obj1, out, state);
>   obj1.free();
>   if (!shadingA) {
>     return NULL;
>@@ -3354,7 +3484,7 @@ GfxShading::~GfxShading() {
>   }
> }
>
>-GfxShading *GfxShading::parse(Object *obj, OutputDev *out) {
>+GfxShading *GfxShading::parse(Object *obj, OutputDev *out, GfxState
>*state) {
>   GfxShading *shading;
>   Dict *dict;
>   int typeA;
>@@ -3378,17 +3508,17 @@ GfxShading *GfxShading::parse(Object *obj,
>OutputDev *out) {
>
>   switch (typeA) {
>   case 1:
>-    shading = GfxFunctionShading::parse(dict, out);
>+    shading = GfxFunctionShading::parse(dict, out, state);
>     break;
>   case 2:
>-    shading = GfxAxialShading::parse(dict, out);
>+    shading = GfxAxialShading::parse(dict, out, state);
>     break;
>   case 3:
>-    shading = GfxRadialShading::parse(dict, out);
>+    shading = GfxRadialShading::parse(dict, out, state);
>     break;
>   case 4:
>     if (obj->isStream()) {
>-      shading = GfxGouraudTriangleShading::parse(4, dict,
>obj->getStream(), out);
>+      shading = GfxGouraudTriangleShading::parse(4, dict,
>obj->getStream(), out, state);
>     } else {
>       error(errSyntaxWarning, -1, "Invalid Type 4 shading object");
>       goto err1;
>@@ -3396,7 +3526,7 @@ GfxShading *GfxShading::parse(Object *obj,
>OutputDev *out) {
>     break;
>   case 5:
>     if (obj->isStream()) {
>-      shading = GfxGouraudTriangleShading::parse(5, dict,
>obj->getStream(), out);
>+      shading = GfxGouraudTriangleShading::parse(5, dict,
>obj->getStream(), out, state);
>     } else {
>       error(errSyntaxWarning, -1, "Invalid Type 5 shading object");
>       goto err1;
>@@ -3404,7 +3534,7 @@ GfxShading *GfxShading::parse(Object *obj,
>OutputDev *out) {
>     break;
>   case 6:
>     if (obj->isStream()) {
>-      shading = GfxPatchMeshShading::parse(6, dict, obj->getStream(),
>out);
>+      shading = GfxPatchMeshShading::parse(6, dict, obj->getStream(),
>out, state);
>     } else {
>       error(errSyntaxWarning, -1, "Invalid Type 6 shading object");
>       goto err1;
>@@ -3412,7 +3542,7 @@ GfxShading *GfxShading::parse(Object *obj,
>OutputDev *out) {
>     break;
>   case 7:
>     if (obj->isStream()) {
>-      shading = GfxPatchMeshShading::parse(7, dict, obj->getStream(),
>out);
>+      shading = GfxPatchMeshShading::parse(7, dict, obj->getStream(),
>out, state);
>     } else {
>       error(errSyntaxWarning, -1, "Invalid Type 7 shading object");
>       goto err1;
>@@ -3429,12 +3559,12 @@ GfxShading *GfxShading::parse(Object *obj,
>OutputDev *out) {
>   return NULL;
> }
>
>-GBool GfxShading::init(Dict *dict, OutputDev *out) {
>+GBool GfxShading::init(Dict *dict, OutputDev *out, GfxState *state) {
>   Object obj1, obj2;
>   int i;
>
>   dict->lookup("ColorSpace", &obj1);
>-  if (!(colorSpace = GfxColorSpace::parse(&obj1, out))) {
>+  if (!(colorSpace = GfxColorSpace::parse(&obj1, out, state))) {
>     error(errSyntaxWarning, -1, "Bad color space in shading dictionary");
>     obj1.free();
>     return gFalse;
>@@ -3541,7 +3671,7 @@ GfxFunctionShading::~GfxFunctionShading() {
>   }
> }
>
>-GfxFunctionShading *GfxFunctionShading::parse(Dict *dict, OutputDev
>*out) {
>+GfxFunctionShading *GfxFunctionShading::parse(Dict *dict, OutputDev
>*out, GfxState *state) {
>   GfxFunctionShading *shading;
>   double x0A, y0A, x1A, y1A;
>   double matrixA[6];
>@@ -3609,7 +3739,7 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict
>*dict, OutputDev *out) {
>
>   shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA,
>                                  funcsA, nFuncsA);
>-  if (!shading->init(dict, out)) {
>+  if (!shading->init(dict, out, state)) {
>     delete shading;
>     return NULL;
>   }
>@@ -3860,7 +3990,7 @@ GfxAxialShading::GfxAxialShading(GfxAxialShading
>*shading):
> GfxAxialShading::~GfxAxialShading() {
> }
>
>-GfxAxialShading *GfxAxialShading::parse(Dict *dict, OutputDev *out) {
>+GfxAxialShading *GfxAxialShading::parse(Dict *dict, OutputDev *out,
>GfxState *state) {
>   GfxAxialShading *shading;
>   double x0A, y0A, x1A, y1A;
>   double t0A, t1A;
>@@ -3957,7 +4087,7 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict,
>OutputDev *out) {
>
>   shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
>                               funcsA, nFuncsA, extend0A, extend1A);
>-  if (!shading->init(dict, out)) {
>+  if (!shading->init(dict, out, state)) {
>     delete shading;
>     return NULL;
>   }
>@@ -4068,7 +4198,7 @@ GfxRadialShading::GfxRadialShading(GfxRadialShading
>*shading):
> GfxRadialShading::~GfxRadialShading() {
> }
>
>-GfxRadialShading *GfxRadialShading::parse(Dict *dict, OutputDev *out) {
>+GfxRadialShading *GfxRadialShading::parse(Dict *dict, OutputDev *out,
>GfxState *state) {
>   GfxRadialShading *shading;
>   double x0A, y0A, r0A, x1A, y1A, r1A;
>   double t0A, t1A;
>@@ -4147,7 +4277,7 @@ GfxRadialShading *GfxRadialShading::parse(Dict
>*dict, OutputDev *out) {
>
>   shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
>                                funcsA, nFuncsA, extend0A, extend1A);
>-  if (!shading->init(dict, out)) {
>+  if (!shading->init(dict, out, state)) {
>     delete shading;
>     return NULL;
>   }
>@@ -4591,7 +4721,7 @@
>GfxGouraudTriangleShading::~GfxGouraudTriangleShading() {
> GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
>                                                           Dict *dict,
>                                                           Stream *str,
>-                                                          OutputDev *out) {
>+                                                          OutputDev *out, GfxState *gfxState) {
>   GfxGouraudTriangleShading *shading;
>   Function *funcsA[gfxColorMaxComps];
>   int nFuncsA;
>@@ -4787,7 +4917,7 @@ GfxGouraudTriangleShading
>*GfxGouraudTriangleShading::parse(int typeA,
>   shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA,
>                                         trianglesA, nTrianglesA,
>                                         funcsA, nFuncsA);
>-  if (!shading->init(dict, out)) {
>+  if (!shading->init(dict, out, gfxState)) {
>     delete shading;
>     return NULL;
>   }
>@@ -4934,7 +5064,7 @@ GfxPatchMeshShading::~GfxPatchMeshShading() {
> }
>
> GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
>-                                              Stream *str, OutputDev *out) {
>+                                              Stream *str, OutputDev *out, GfxState *state) {
>   GfxPatchMeshShading *shading;
>   Function *funcsA[gfxColorMaxComps];
>   int nFuncsA;
>@@ -5458,7 +5588,7 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int
>typeA, Dict *dict,
>
>   shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA,
>                                   funcsA, nFuncsA);
>-  if (!shading->init(dict, out)) {
>+  if (!shading->init(dict, out, state)) {
>     delete shading;
>     return NULL;
>   }
>@@ -6394,9 +6524,17 @@ GfxState::GfxState(double hDPIA, double vDPIA,
>PDFRectangle *pageBox,
>   clipXMax = pageWidth;
>   clipYMax = pageHeight;
>
>+  renderingIntent[0] = 0;
>+
>   saved = NULL;
> #ifdef USE_CMS
>   GfxColorSpace::setupColorProfiles();
>+  XYZ2DisplayTransformRelCol = NULL;
>+  XYZ2DisplayTransformAbsCol = NULL;
>+  XYZ2DisplayTransformSat = NULL;
>+  XYZ2DisplayTransformPerc = NULL;
>+  localDisplayProfile = NULL;
>+  displayProfileRef = 0;
> #endif
> }
>
>@@ -6428,6 +6566,27 @@ GfxState::~GfxState() {
>   if (font) {
>     font->decRefCnt();
>   }
>+#ifdef USE_CMS
>+  if (XYZ2DisplayTransformRelCol) {
>+    if (XYZ2DisplayTransformRelCol->unref() == 0)
>+      delete XYZ2DisplayTransformRelCol;
>+  }
>+  if (XYZ2DisplayTransformAbsCol) {
>+    if (XYZ2DisplayTransformAbsCol->unref() == 0)
>+      delete XYZ2DisplayTransformAbsCol;
>+  }
>+  if (XYZ2DisplayTransformSat) {
>+    if (XYZ2DisplayTransformSat->unref() == 0)
>+      delete XYZ2DisplayTransformSat;
>+  }
>+  if (XYZ2DisplayTransformPerc) {
>+    if (XYZ2DisplayTransformPerc->unref() == 0)
>+      delete XYZ2DisplayTransformPerc;
>+  }
>+  if (--displayProfileRef == 0 && localDisplayProfile != NULL) {
>+    cmsCloseProfile(localDisplayProfile);
>+  }
>+#endif
> }
>
> // Used for copy();
>@@ -6463,8 +6622,102 @@ GfxState::GfxState(GfxState *state, GBool
>copyPath) {
>     path = state->path->copy();
>   }
>   saved = NULL;
>+#ifdef USE_CMS
>+  if (XYZ2DisplayTransformRelCol) {
>+    XYZ2DisplayTransformRelCol->ref();
>+  }
>+  if (XYZ2DisplayTransformAbsCol) {
>+    XYZ2DisplayTransformAbsCol->ref();
>+  }
>+  if (XYZ2DisplayTransformSat) {
>+    XYZ2DisplayTransformSat->ref();
>+  }
>+  if (XYZ2DisplayTransformPerc) {
>+    XYZ2DisplayTransformPerc->ref();
>+  }
>+  if (localDisplayProfile) {
>+    displayProfileRef++;
>+  }
>+#endif
>+}
>+
>+#ifdef USE_CMS
>+void GfxState::setDisplayProfile(cmsHPROFILE localDisplayProfileA) {
>+  if (localDisplayProfile != NULL) {
>+    cmsCloseProfile(localDisplayProfile);
>+  }
>+  localDisplayProfile = localDisplayProfileA;
>+  if (localDisplayProfileA != NULL) {
>+    cmsHTRANSFORM transform;
>+    unsigned int nChannels;
>+    unsigned int localDisplayPixelType;
>+
>+    localDisplayPixelType =
>getCMSColorSpaceType(cmsGetColorSpace(localDisplayProfile));
>+    nChannels = getCMSNChannels(cmsGetColorSpace(localDisplayProfile));
>+    displayProfileRef = 1;
>+    // create transform from XYZ
>+    cmsHPROFILE XYZProfile = cmsCreateXYZProfile();
>+    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
>+         localDisplayProfile,
>+         COLORSPACE_SH(localDisplayPixelType) |
>+           CHANNELS_SH(nChannels) | BYTES_SH(1),
>+        INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == 0) {
>+      error(errSyntaxWarning, -1, "Can't create Lab transform");
>+    } else {
>+      XYZ2DisplayTransformRelCol = new GfxColorTransform(transform,
>INTENT_RELATIVE_COLORIMETRIC, localDisplayPixelType);
>+    }
>+    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
>+         localDisplayProfile,
>+         COLORSPACE_SH(localDisplayPixelType) |
>+           CHANNELS_SH(nChannels) | BYTES_SH(1),
>+        INTENT_ABSOLUTE_COLORIMETRIC,LCMS_FLAGS)) == 0) {
>+      error(errSyntaxWarning, -1, "Can't create Lab transform");
>+    } else {
>+      XYZ2DisplayTransformAbsCol = new GfxColorTransform(transform,
>INTENT_ABSOLUTE_COLORIMETRIC, localDisplayPixelType);
>+    }
>+    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
>+         localDisplayProfile,
>+         COLORSPACE_SH(localDisplayPixelType) |
>+           CHANNELS_SH(nChannels) | BYTES_SH(1),
>+        INTENT_SATURATION,LCMS_FLAGS)) == 0) {
>+      error(errSyntaxWarning, -1, "Can't create Lab transform");
>+    } else {
>+      XYZ2DisplayTransformSat = new GfxColorTransform(transform,
>INTENT_SATURATION, localDisplayPixelType);
>+    }
>+    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
>+         localDisplayProfile,
>+         COLORSPACE_SH(localDisplayPixelType) |
>+           CHANNELS_SH(nChannels) | BYTES_SH(1),
>+        INTENT_PERCEPTUAL,LCMS_FLAGS)) == 0) {
>+      error(errSyntaxWarning, -1, "Can't create Lab transform");
>+    } else {
>+      XYZ2DisplayTransformPerc = new GfxColorTransform(transform,
>INTENT_PERCEPTUAL, localDisplayPixelType);
>+    }
>+    cmsCloseProfile(XYZProfile);
>+  }
> }
>
>+GfxColorTransform *GfxState::getXYZ2DisplayTransform() {
>+  GfxColorTransform *transform;
>+
>+  transform = XYZ2DisplayTransformRelCol;
>+  if (renderingIntent != NULL) {
>+    if (strcmp(renderingIntent, "AbsoluteColorimetric") == 0) {
>+      transform = XYZ2DisplayTransformAbsCol;
>+    } else if (strcmp(renderingIntent, "Saturation") == 0) {
>+      transform = XYZ2DisplayTransformSat;
>+    } else if (strcmp(renderingIntent, "Perceptual") == 0) {
>+      transform = XYZ2DisplayTransformPerc;
>+    }
>+  }
>+  if (transform == NULL) {
>+    transform = XYZ2DisplayTransform;
>+  }
>+  return transform;
>+}
>+
>+#endif
>+
> void GfxState::setPath(GfxPath *pathA) {
>   delete path;
>   path = pathA;
>diff --git a/poppler/GfxState.h b/poppler/GfxState.h
>index 286008d..106b2c0 100644
>--- a/poppler/GfxState.h
>+++ b/poppler/GfxState.h
>@@ -52,6 +52,7 @@ class GfxShading;
> class PopplerCache;
> class GooList;
> class OutputDev;
>+class GfxState;
>
> class Matrix {
> public:
>@@ -181,14 +182,18 @@ class GfxColorTransform {
> public:
>   void doTransform(void *in, void *out, unsigned int size);
>   // transformA should be a cmsHTRANSFORM
>-  GfxColorTransform(void *transformA);
>+  GfxColorTransform(void *transformA, int cmsIntent, unsigned int
>transformPixelType);
>   ~GfxColorTransform();
>+  int getIntent() { return cmsIntent; }
>+  int getTransformPixelType() { return transformPixelType; }
>   void ref();
>   unsigned int unref();
> private:
>   GfxColorTransform() {}
>   void *transform;
>   unsigned int refCount;
>+  int cmsIntent;
>+  unsigned int transformPixelType;
> };
>
> class GfxColorSpace {
>@@ -200,7 +205,7 @@ public:
>   virtual GfxColorSpaceMode getMode() = 0;
>
>   // Construct a color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Object *csObj, OutputDev *out, int
>recursion = 0);
>+  static GfxColorSpace *parse(Object *csObj, OutputDev *out, GfxState
>*state, int recursion = 0);
>
>   // Convert to gray, RGB, or CMYK.
>   virtual void getGray(GfxColor *color, GfxGray *gray) = 0;
>@@ -313,7 +318,7 @@ public:
>   virtual GfxColorSpaceMode getMode() { return csCalGray; }
>
>   // Construct a CalGray color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Array *arr);
>+  static GfxColorSpace *parse(Array *arr, GfxState *state);
>
>   virtual void getGray(GfxColor *color, GfxGray *gray);
>   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
>@@ -339,6 +344,9 @@ private:
>   double gamma;                           // gamma value
>   double kr, kg, kb;              // gamut mapping mulitpliers
>   void getXYZ(GfxColor *color, double *pX, double *pY, double *pZ);
>+#ifdef USE_CMS
>+  GfxColorTransform *transform;
>+#endif
> };
>
>
>//------------------------------------------------------------------------
>@@ -388,7 +396,7 @@ public:
>   virtual GfxColorSpaceMode getMode() { return csCalRGB; }
>
>   // Construct a CalRGB color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Array *arr);
>+  static GfxColorSpace *parse(Array *arr, GfxState *state);
>
>   virtual void getGray(GfxColor *color, GfxGray *gray);
>   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
>@@ -418,6 +426,9 @@ private:
>   double mat[9];                  // ABC -> XYZ transform matrix
>   double kr, kg, kb;              // gamut mapping mulitpliers
>   void getXYZ(GfxColor *color, double *pX, double *pY, double *pZ);
>+#ifdef USE_CMS
>+  GfxColorTransform *transform;
>+#endif
> };
>
>
>//------------------------------------------------------------------------
>@@ -464,7 +475,7 @@ public:
>   virtual GfxColorSpaceMode getMode() { return csLab; }
>
>   // Construct a Lab color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Array *arr);
>+  static GfxColorSpace *parse(Array *arr, GfxState *state);
>
>   virtual void getGray(GfxColor *color, GfxGray *gray);
>   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
>@@ -496,6 +507,9 @@ private:
>   double aMin, aMax, bMin, bMax;    // range for the a and b components
>   double kr, kg, kb;              // gamut mapping mulitpliers
>   void getXYZ(GfxColor *color, double *pX, double *pY, double *pZ);
>+#ifdef USE_CMS
>+  GfxColorTransform *transform;
>+#endif
> };
>
>
>//------------------------------------------------------------------------
>@@ -512,7 +526,7 @@ public:
>   virtual GfxColorSpaceMode getMode() { return csICCBased; }
>
>   // Construct an ICCBased color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion);
>+  static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState
>*state, int recursion);
>
>   virtual void getGray(GfxColor *color, GfxGray *gray);
>   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
>@@ -545,6 +559,7 @@ private:
>   double rangeMax[4];         // max values for each component
>   Ref iccProfileStream;               // the ICC profile
> #ifdef USE_CMS
>+  int getIntent() { return (transform != NULL) ? transform->getIntent()
>: 0; }
>   GfxColorTransform *transform;
>   GfxColorTransform *lineTransform; // color transform for line
>   std::map<unsigned int, unsigned int> cmsCache;
>@@ -563,7 +578,7 @@ public:
>   virtual GfxColorSpaceMode getMode() { return csIndexed; }
>
>   // Construct an Indexed color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion);
>+  static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState
>*state, int recursion);
>
>   virtual void getGray(GfxColor *color, GfxGray *gray);
>   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
>@@ -616,7 +631,7 @@ public:
>   virtual GfxColorSpaceMode getMode() { return csSeparation; }
>
>   // Construct a Separation color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion);
>+  static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState
>*state, int recursion);
>
>   virtual void getGray(GfxColor *color, GfxGray *gray);
>   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
>@@ -661,7 +676,7 @@ public:
>   virtual GfxColorSpaceMode getMode() { return csDeviceN; }
>
>   // Construct a DeviceN color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion);
>+  static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState
>*state, int recursion);
>
>   virtual void getGray(GfxColor *color, GfxGray *gray);
>   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
>@@ -708,7 +723,7 @@ public:
>   virtual GfxColorSpaceMode getMode() { return csPattern; }
>
>   // Construct a Pattern color space.  Returns NULL if unsuccessful.
>-  static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion);
>+  static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState
>*state, int recursion);
>
>   virtual void getGray(GfxColor *color, GfxGray *gray);
>   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
>@@ -737,7 +752,7 @@ public:
>   GfxPattern(int typeA);
>   virtual ~GfxPattern();
>
>-  static GfxPattern *parse(Object *obj, OutputDev *out);
>+  static GfxPattern *parse(Object *obj, OutputDev *out, GfxState *state);
>
>   virtual GfxPattern *copy() = 0;
>
>@@ -793,7 +808,7 @@ private:
> class GfxShadingPattern: public GfxPattern {
> public:
>
>-  static GfxShadingPattern *parse(Object *patObj, OutputDev *out);
>+  static GfxShadingPattern *parse(Object *patObj, OutputDev *out,
>GfxState *state);
>   virtual ~GfxShadingPattern();
>
>   virtual GfxPattern *copy();
>@@ -820,7 +835,7 @@ public:
>   GfxShading(GfxShading *shading);
>   virtual ~GfxShading();
>
>-  static GfxShading *parse(Object *obj, OutputDev *out);
>+  static GfxShading *parse(Object *obj, OutputDev *out, GfxState *state);
>
>   virtual GfxShading *copy() = 0;
>
>@@ -834,7 +849,7 @@ public:
>
> protected:
>
>-  GBool init(Dict *dict, OutputDev *out);
>+  GBool init(Dict *dict, OutputDev *out, GfxState *state);
>
>   int type;
>   GfxColorSpace *colorSpace;
>@@ -903,7 +918,7 @@ public:
>   GfxFunctionShading(GfxFunctionShading *shading);
>   virtual ~GfxFunctionShading();
>
>-  static GfxFunctionShading *parse(Dict *dict, OutputDev *out);
>+  static GfxFunctionShading *parse(Dict *dict, OutputDev *out, GfxState
>*state);
>
>   virtual GfxShading *copy();
>
>@@ -937,7 +952,7 @@ public:
>   GfxAxialShading(GfxAxialShading *shading);
>   virtual ~GfxAxialShading();
>
>-  static GfxAxialShading *parse(Dict *dict, OutputDev *out);
>+  static GfxAxialShading *parse(Dict *dict, OutputDev *out, GfxState
>*state);
>
>   virtual GfxShading *copy();
>
>@@ -970,7 +985,7 @@ public:
>   GfxRadialShading(GfxRadialShading *shading);
>   virtual ~GfxRadialShading();
>
>-  static GfxRadialShading *parse(Dict *dict, OutputDev *out);
>+  static GfxRadialShading *parse(Dict *dict, OutputDev *out, GfxState
>*state);
>
>   virtual GfxShading *copy();
>
>@@ -1008,7 +1023,7 @@ public:
>   GfxGouraudTriangleShading(GfxGouraudTriangleShading *shading);
>   virtual ~GfxGouraudTriangleShading();
>
>-  static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream
>*str, OutputDev *out);
>+  static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream
>*str, OutputDev *out, GfxState *state);
>
>   virtual GfxShading *copy();
>
>@@ -1094,7 +1109,7 @@ public:
>   GfxPatchMeshShading(GfxPatchMeshShading *shading);
>   virtual ~GfxPatchMeshShading();
>
>-  static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str,
>OutputDev *out);
>+  static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str,
>OutputDev *out, GfxState *state);
>
>   virtual GfxShading *copy();
>
>@@ -1439,6 +1454,7 @@ public:
>   double getLeading() { return leading; }
>   double getRise() { return rise; }
>   int getRender() { return render; }
>+  char *getRenderingIntent() { return renderingIntent; }
>   GfxPath *getPath() { return path; }
>   void setPath(GfxPath *pathA);
>   double getCurX() { return curX; }
>@@ -1517,6 +1533,14 @@ public:
>     { rise = riseA; }
>   void setRender(int renderA)
>     { render = renderA; }
>+  void setRenderingIntent(const char *intent)
>+    { strncpy(renderingIntent, intent, 31); }
>+
>+#ifdef USE_CMS
>+  void setDisplayProfile(void *localDisplayProfileA);
>+  void *getDisplayProfile() { return localDisplayProfile; }
>+  GfxColorTransform *getXYZ2DisplayTransform();
>+#endif
>
>   // Add to path.
>   void moveTo(double x, double y)
>@@ -1605,10 +1629,20 @@ private:
>
>   double clipXMin, clipYMin,  // bounding box for clip region
>          clipXMax, clipYMax;
>+  char renderingIntent[32];
>
>   GfxState *saved;            // next GfxState on stack
>
>   GfxState(GfxState *state, GBool copyPath);
>+
>+#ifdef USE_CMS
>+  void *localDisplayProfile;
>+  int displayProfileRef;
>+  GfxColorTransform *XYZ2DisplayTransformRelCol;
>+  GfxColorTransform *XYZ2DisplayTransformAbsCol;
>+  GfxColorTransform *XYZ2DisplayTransformSat;
>+  GfxColorTransform *XYZ2DisplayTransformPerc;
>+#endif
> };
>
> #endif
>diff --git a/poppler/Page.cc b/poppler/Page.cc
>index 0465c6b..ecdff32 100644
>--- a/poppler/Page.cc
>+++ b/poppler/Page.cc
>@@ -672,7 +672,7 @@ GBool Page::loadThumb(unsigned char **data_out,
>     obj1.free ();
>     dict->lookup ("CS", &obj1);
>   }
>-  colorSpace = GfxColorSpace::parse(&obj1, NULL);
>+  colorSpace = GfxColorSpace::parse(&obj1, NULL, NULL);
>   obj1.free();
>   if (!colorSpace) {
>     fprintf (stderr, "Error: Cannot parse color space\n");
>_______________________________________________
>poppler mailing list
>poppler at lists.freedesktop.org
>http://lists.freedesktop.org/mailman/listinfo/poppler



More information about the poppler mailing list