[poppler] poppler/Gfx.cc poppler/Gfx.h poppler/GfxState.cc poppler/GfxState.h poppler/Page.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Wed Oct 2 14:36:29 PDT 2013


 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");


More information about the poppler mailing list