[poppler] poppler/Gfx.cc poppler/GfxState.cc poppler/GfxState.h qt5/src utils/pdftocairo.cc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat May 23 18:12:49 UTC 2020


 poppler/Gfx.cc              |    4 
 poppler/GfxState.cc         |  314 ++++++++++++++++++++------------------------
 poppler/GfxState.h          |   55 ++++---
 qt5/src/poppler-document.cc |    6 
 qt5/src/poppler-qt5.h       |   11 +
 utils/pdftocairo.cc         |    9 -
 6 files changed, 195 insertions(+), 204 deletions(-)

New commits:
commit 5927e0b08f1ad6868d04cb209ee1e17b4ac07b70
Author: Philipp Knechtges <philipp-dev at knechtges.com>
Date:   Sat May 23 18:12:46 2020 +0000

    GfxState: substitute manual ref counting in GfxColorTransform by a shared_ptr
    
    This patch as said replaces the manual ref counting in GfxColorTransform. Along the lines
    it also introduces another shared_ptr for cmsHPROFILEs, which is named GfxLCMSProfilePtr.

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index c248c576..c1462c86 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -654,8 +654,8 @@ void Gfx::initDisplayProfile() {
                 Stream *iccStream = profile.getStream();
                 int length = 0;
                 unsigned char *profBuf = iccStream->toUnsignedChars(&length, 65536, 65536);
-                cmsHPROFILE hp = cmsOpenProfileFromMem(profBuf,length);
-                if (hp == nullptr) {
+                auto hp = make_GfxLCMSProfilePtr(cmsOpenProfileFromMem(profBuf,length));
+                if (!hp) {
                   error(errSyntaxWarning, -1, "read ICCBased color space profile error");
                 } else {
                   state->setDisplayProfile(hp);
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index bd0f0de5..fb8cb37a 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -192,15 +192,27 @@ static const std::map<unsigned int, unsigned int>::size_type CMSCACHE_LIMIT = 20
 #define COLOR_PROFILE_DIR "/ColorProfiles/"
 #define GLOBAL_COLOR_PROFILE_DIR POPPLER_DATADIR COLOR_PROFILE_DIR
 
+static void lcmsprofiledeleter(void* profile)
+{
+    cmsCloseProfile(profile);
+}
+
+GfxLCMSProfilePtr make_GfxLCMSProfilePtr(void* profile)
+{
+    if (profile == nullptr) {
+        return GfxLCMSProfilePtr();
+    }
+    return GfxLCMSProfilePtr(profile, lcmsprofiledeleter);
+}
+
 void GfxColorTransform::doTransform(void *in, void *out, unsigned int size) {
   cmsDoTransform(transform, in, out, size);
 }
 
 // transformA should be a cmsHTRANSFORM
-GfxColorTransform::GfxColorTransform(void *sourceProfileA, void *transformA, int cmsIntentA, unsigned int inputPixelTypeA, unsigned int transformPixelTypeA) {
+GfxColorTransform::GfxColorTransform(const GfxLCMSProfilePtr& sourceProfileA, void *transformA, int cmsIntentA, unsigned int inputPixelTypeA, unsigned int transformPixelTypeA) {
   sourceProfile = sourceProfileA;
   transform = transformA;
-  refCount = 1;
   cmsIntent = cmsIntentA;
   inputPixelType = inputPixelTypeA;
   transformPixelType = transformPixelTypeA;
@@ -208,21 +220,11 @@ GfxColorTransform::GfxColorTransform(void *sourceProfileA, void *transformA, int
 }
 
 GfxColorTransform::~GfxColorTransform() {
-  if (sourceProfile)
-    cmsCloseProfile(sourceProfile);
   cmsDeleteTransform(transform);
   if (psCSA)
     gfree(psCSA);
 }
 
-void GfxColorTransform::ref() {
-  refCount++;
-}
-
-unsigned int GfxColorTransform::unref() {
-  return --refCount;
-}
-
 char *GfxColorTransform::getPostScriptCSA()
 {
 #if LCMS_VERSION>=2070
@@ -239,19 +241,20 @@ char *GfxColorTransform::getPostScriptCSA()
   if (psCSA)
     return psCSA;
 
-  if (sourceProfile == nullptr) {
+  if (!sourceProfile) {
     error(errSyntaxWarning, -1, "profile is nullptr");
     return nullptr;
   }
 
-  size = cmsGetPostScriptCSA(cmsGetProfileContextID(sourceProfile), sourceProfile, cmsIntent, 0, nullptr, 0);
+  void *rawprofile = sourceProfile.get();
+  size = cmsGetPostScriptCSA(cmsGetProfileContextID(rawprofile), rawprofile, cmsIntent, 0, nullptr, 0);
   if (size == 0) {
     error(errSyntaxWarning, -1, "PostScript CSA is nullptr");
     return nullptr;
   }
 
   psCSA = (char*)gmalloc(size+1);
-  cmsGetPostScriptCSA(cmsGetProfileContextID(sourceProfile), sourceProfile, cmsIntent, 0, psCSA, size);
+  cmsGetPostScriptCSA(cmsGetProfileContextID(rawprofile), rawprofile, cmsIntent, 0, psCSA, size);
   psCSA[size] = 0;
 
   return psCSA;
@@ -260,39 +263,39 @@ char *GfxColorTransform::getPostScriptCSA()
 #endif
 }
 
-static cmsHPROFILE RGBProfile = nullptr;
+static GfxLCMSProfilePtr RGBProfile = nullptr;
 static GooString *displayProfileName = nullptr; // display profile file Name
-static cmsHPROFILE displayProfile = nullptr; // display profile
+static GfxLCMSProfilePtr displayProfile = nullptr; // display profile
 static unsigned int displayPixelType = 0;
-static GfxColorTransform *XYZ2DisplayTransform = nullptr;
+static std::shared_ptr<GfxColorTransform> XYZ2DisplayTransform = nullptr;
 
 // convert color space signature to cmsColor type 
 static unsigned int getCMSColorSpaceType(cmsColorSpaceSignature cs);
 static unsigned int getCMSNChannels(cmsColorSpaceSignature cs);
-static cmsHPROFILE loadColorProfile(const char *fileName);
+static GfxLCMSProfilePtr loadColorProfile(const char *fileName);
 
-void GfxColorSpace::setDisplayProfile(void *displayProfileA) {
-  if (displayProfile != nullptr) {
+void GfxColorSpace::setDisplayProfile(const GfxLCMSProfilePtr& displayProfileA) {
+  if (displayProfile) {
     error(errInternal, -1, "The display color profile can only be set once before any rendering is done.");
     return;
   }
   displayProfile = displayProfileA;
-  if (displayProfile != nullptr) {
+  if (displayProfile) {
     cmsHTRANSFORM transform;
     unsigned int nChannels;
 
-    displayPixelType = getCMSColorSpaceType(cmsGetColorSpace(displayProfile));
-    nChannels = getCMSNChannels(cmsGetColorSpace(displayProfile));
+    displayPixelType = getCMSColorSpaceType(cmsGetColorSpace(displayProfile.get()));
+    nChannels = getCMSNChannels(cmsGetColorSpace(displayProfile.get()));
     // create transform from XYZ
-    cmsHPROFILE XYZProfile = cmsCreateXYZProfile();
-    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
-	   displayProfile,
+    auto XYZProfile = make_GfxLCMSProfilePtr(cmsCreateXYZProfile());
+    if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
+	   displayProfile.get(),
 	   COLORSPACE_SH(displayPixelType) |
 	     CHANNELS_SH(nChannels) | BYTES_SH(1),
 	  INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
     } else {
-      XYZ2DisplayTransform = new GfxColorTransform(displayProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
+      XYZ2DisplayTransform = std::make_shared<GfxColorTransform>(displayProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
     }
   }
 }
@@ -306,11 +309,11 @@ void GfxColorSpace::setDisplayProfileName(GooString *name) {
   displayProfileName = name->copy();
 }
 
-cmsHPROFILE GfxColorSpace::getRGBProfile() {
+GfxLCMSProfilePtr GfxColorSpace::getRGBProfile() {
   return RGBProfile;
 }
 
-cmsHPROFILE GfxColorSpace::getDisplayProfile() {
+GfxLCMSProfilePtr GfxColorSpace::getDisplayProfile() {
   return displayProfile;
 }
 
@@ -498,7 +501,7 @@ const char *GfxColorSpace::getColorSpaceModeName(int idx) {
 }
 
 #ifdef USE_CMS
-cmsHPROFILE loadColorProfile(const char *fileName)
+GfxLCMSProfilePtr loadColorProfile(const char *fileName)
 {
   cmsHPROFILE hp = nullptr;
   FILE *fp;
@@ -510,7 +513,7 @@ cmsHPROFILE loadColorProfile(const char *fileName)
       fclose(fp);
       hp = cmsOpenProfileFromFile(fileName,"r");
     }
-    return hp;
+    return make_GfxLCMSProfilePtr(hp);
   }
   // try to load from global directory
   GooString *path = new GooString(GLOBAL_COLOR_PROFILE_DIR);
@@ -521,7 +524,7 @@ cmsHPROFILE loadColorProfile(const char *fileName)
     hp = cmsOpenProfileFromFile(path->c_str(),"r");
   }
   delete path;
-  return hp;
+  return make_GfxLCMSProfilePtr(hp);
 }
 
 static void CMSError(cmsContext /*contextId*/, cmsUInt32Number /*ecode*/, const char *text)
@@ -542,7 +545,7 @@ int GfxColorSpace::setupColorProfiles()
   // set error handlor
   cmsSetLogErrorHandler(CMSError);
 
-  if (displayProfile == nullptr) {
+  if (!displayProfile) {
     // load display profile if it was not already loaded.
     if (displayProfileName == nullptr) {
       displayProfile = loadColorProfile("display.icc");
@@ -552,25 +555,24 @@ int GfxColorSpace::setupColorProfiles()
   }
   // load RGB profile
   RGBProfile = loadColorProfile("RGB.icc");
-  if (RGBProfile == nullptr) {
+  if (!RGBProfile) {
     /* use built in sRGB profile */
-    RGBProfile = cmsCreate_sRGBProfile();
+    RGBProfile = make_GfxLCMSProfilePtr(cmsCreate_sRGBProfile());
   }
   // create transforms
-  if (displayProfile != nullptr) {
-    displayPixelType = getCMSColorSpaceType(cmsGetColorSpace(displayProfile));
-    nChannels = getCMSNChannels(cmsGetColorSpace(displayProfile));
+  if (displayProfile) {
+    displayPixelType = getCMSColorSpaceType(cmsGetColorSpace(displayProfile.get()));
+    nChannels = getCMSNChannels(cmsGetColorSpace(displayProfile.get()));
     // create transform from XYZ
-    cmsHPROFILE XYZProfile = cmsCreateXYZProfile();
-    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
-	   displayProfile,
+    auto XYZProfile = make_GfxLCMSProfilePtr(cmsCreateXYZProfile());
+    if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
+	   displayProfile.get(),
 	   COLORSPACE_SH(displayPixelType) |
 	     CHANNELS_SH(nChannels) | BYTES_SH(1),
 	  INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
-      cmsCloseProfile(XYZProfile);
     } else {
-      XYZ2DisplayTransform = new GfxColorTransform(XYZProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
+      XYZ2DisplayTransform = std::make_shared<GfxColorTransform>(XYZProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
     }
   }
   return 0;
@@ -790,11 +792,6 @@ GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
 }
 
 GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
-#ifdef USE_CMS
-  if (transform != nullptr) {
-    if (transform->unref() == 0) delete transform;
-  }
-#endif
 }
 
 GfxColorSpace *GfxCalGrayColorSpace::copy() const {
@@ -813,7 +810,6 @@ GfxColorSpace *GfxCalGrayColorSpace::copy() const {
   cs->kb = kb;
 #ifdef USE_CMS
   cs->transform = transform;
-  if (transform != nullptr) transform->ref();
 #endif
   return cs;
 }
@@ -862,7 +858,6 @@ GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr, GfxState *state) {
 		xyzrgb[2][2] * cs->whiteZ);
 #ifdef USE_CMS
   cs->transform = (state != nullptr) ? state->getXYZ2DisplayTransform() : XYZ2DisplayTransform;
-  if (cs->transform != nullptr) cs->transform->ref();
 #endif
   return cs;
 }
@@ -882,7 +877,7 @@ void GfxCalGrayColorSpace::getGray(const GfxColor *color, GfxGray *gray) const {
   GfxRGB rgb;
 
 #ifdef USE_CMS
-  if (transform != nullptr && transform->getTransformPixelType() == PT_GRAY) {
+  if (transform && transform->getTransformPixelType() == PT_GRAY) {
     unsigned char out[gfxColorMaxComps];
     double in[gfxColorMaxComps];
     double X, Y, Z;
@@ -908,7 +903,7 @@ void GfxCalGrayColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const {
 
   getXYZ(color,&X,&Y,&Z);
 #ifdef USE_CMS
-  if (transform != nullptr && transform->getTransformPixelType() == PT_RGB) {
+  if (transform && transform->getTransformPixelType() == PT_RGB) {
     unsigned char out[gfxColorMaxComps];
     double in[gfxColorMaxComps];
     
@@ -939,7 +934,7 @@ void GfxCalGrayColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const {
   GfxColorComp c, m, y, k;
 
 #ifdef USE_CMS
-  if (transform != nullptr && transform->getTransformPixelType() == PT_CMYK) {
+  if (transform && transform->getTransformPixelType() == PT_CMYK) {
     double in[gfxColorMaxComps];
     unsigned char out[gfxColorMaxComps];
     double X, Y, Z;
@@ -1145,11 +1140,6 @@ GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
 }
 
 GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
-#ifdef USE_CMS
-  if (transform != nullptr) {
-    if (transform->unref() == 0) delete transform;
-  }
-#endif
 }
 
 GfxColorSpace *GfxCalRGBColorSpace::copy() const {
@@ -1174,7 +1164,6 @@ GfxColorSpace *GfxCalRGBColorSpace::copy() const {
   }
 #ifdef USE_CMS
   cs->transform = transform;
-  if (transform != nullptr) transform->ref();
 #endif
   return cs;
 }
@@ -1229,7 +1218,6 @@ GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr, GfxState *state) {
 
 #ifdef USE_CMS
   cs->transform = (state != nullptr) ? state->getXYZ2DisplayTransform() : XYZ2DisplayTransform;
-  if (cs->transform != nullptr) cs->transform->ref();
 #endif
   return cs;
 }
@@ -1499,11 +1487,6 @@ GfxLabColorSpace::GfxLabColorSpace() {
 }
 
 GfxLabColorSpace::~GfxLabColorSpace() {
-#ifdef USE_CMS
-  if (transform != nullptr) {
-    if (transform->unref() == 0) delete transform;
-  }
-#endif
 }
 
 GfxColorSpace *GfxLabColorSpace::copy() const {
@@ -1525,7 +1508,6 @@ GfxColorSpace *GfxLabColorSpace::copy() const {
   cs->kb = kb;
 #ifdef USE_CMS
   cs->transform = transform;
-  if (transform != nullptr) transform->ref();
 #endif
   return cs;
 }
@@ -1582,7 +1564,6 @@ GfxColorSpace *GfxLabColorSpace::parse(Array *arr, GfxState *state) {
 
 #ifdef USE_CMS
   cs->transform = (state != nullptr) ? state->getXYZ2DisplayTransform() : XYZ2DisplayTransform;
-  if (cs->transform != nullptr) cs->transform->ref();
 #endif
   return cs;
 }
@@ -1782,14 +1763,6 @@ GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
 
 GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
   delete alt;
-#ifdef USE_CMS
-  if (transform != nullptr) {
-    if (transform->unref() == 0) delete transform;
-  }
-  if (lineTransform != nullptr) {
-    if (lineTransform->unref() == 0) delete lineTransform;
-  }
-#endif
 }
 
 GfxColorSpace *GfxICCBasedColorSpace::copy() const {
@@ -1803,9 +1776,7 @@ GfxColorSpace *GfxICCBasedColorSpace::copy() const {
   }
 #ifdef USE_CMS
   cs->transform = transform;
-  if (transform != nullptr) transform->ref();
   cs->lineTransform = lineTransform;
-  if (lineTransform != nullptr) lineTransform->ref();
 #endif
   return cs;
 }
@@ -1898,52 +1869,49 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, GfxState
   int length = 0;
 
   profBuf = iccStream->toUnsignedChars(&length, 65536, 65536);
-  cmsHPROFILE hp = cmsOpenProfileFromMem(profBuf,length);
+  auto hp = make_GfxLCMSProfilePtr(cmsOpenProfileFromMem(profBuf,length));
   gfree(profBuf);
-  if (hp == nullptr) {
+  if (!hp) {
     error(errSyntaxWarning, -1, "read ICCBased color space profile error");
   } else {
-    cmsHPROFILE dhp = (state != nullptr && state->getDisplayProfile() != nullptr) ? state->getDisplayProfile() : displayProfile;
-    if (dhp == nullptr) {
-      if (unlikely(RGBProfile == nullptr)) {
+    auto dhp = (state != nullptr && state->getDisplayProfile() != nullptr) ? state->getDisplayProfile() : displayProfile;
+    if (!dhp) {
+      if (unlikely(!RGBProfile)) {
         GfxColorSpace::setupColorProfiles();
       }
       dhp = RGBProfile;
     }
-    unsigned int cst = getCMSColorSpaceType(cmsGetColorSpace(hp));
-    unsigned int dNChannels = getCMSNChannels(cmsGetColorSpace(dhp));
-    unsigned int dcst = getCMSColorSpaceType(cmsGetColorSpace(dhp));
+    unsigned int cst = getCMSColorSpaceType(cmsGetColorSpace(hp.get()));
+    unsigned int dNChannels = getCMSNChannels(cmsGetColorSpace(dhp.get()));
+    unsigned int dcst = getCMSColorSpaceType(cmsGetColorSpace(dhp.get()));
     cmsHTRANSFORM transform;
 
     int cmsIntent = INTENT_RELATIVE_COLORIMETRIC;
     if (state != nullptr) {
       cmsIntent = state->getCmsRenderingIntent();
     }
-    if ((transform = cmsCreateTransform(hp,
+    if ((transform = cmsCreateTransform(hp.get(),
 	   COLORSPACE_SH(cst) |CHANNELS_SH(nCompsA) | BYTES_SH(1),
-	   dhp,
+	   dhp.get(),
 	   COLORSPACE_SH(dcst) |
 	     CHANNELS_SH(dNChannels) | BYTES_SH(1),
 	   cmsIntent, LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create transform");
       cs->transform = nullptr;
     } else {
-      cs->transform = new GfxColorTransform(hp, transform, cmsIntent, cst, dcst);
+      cs->transform = std::make_shared<GfxColorTransform>(hp, transform, cmsIntent, cst, dcst);
     }
     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,
+      if ((transform = cmsCreateTransform(hp.get(),
+	    CHANNELS_SH(nCompsA) | BYTES_SH(1),dhp.get(),
 	    (dcst == PT_RGB) ? TYPE_RGB_8 : TYPE_CMYK_8, cmsIntent, LCMS_FLAGS)) == nullptr) {
 	error(errSyntaxWarning, -1, "Can't create transform");
 	cs->lineTransform = nullptr;
       } else {
-	cs->lineTransform = new GfxColorTransform(nullptr, transform, cmsIntent, cst, dcst);
+	cs->lineTransform = std::make_shared<GfxColorTransform>(hp, transform, cmsIntent, cst, dcst);
       }
     }
-    if (cs->transform == nullptr) {
-      cmsCloseProfile(hp);
-    }
   }
   // put this colorSpace into cache
   if (out && iccProfileStreamA != Ref::INVALID()) {
@@ -6505,7 +6473,6 @@ GfxState::GfxState(double hDPIA, double vDPIA, const PDFRectangle *pageBox,
   XYZ2DisplayTransformSat = nullptr;
   XYZ2DisplayTransformPerc = nullptr;
   localDisplayProfile = nullptr;
-  displayProfileRef = 0;
 #endif
 }
 
@@ -6537,150 +6504,163 @@ 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 != nullptr) {
-    cmsCloseProfile(localDisplayProfile);
-  }
-#endif
 }
 
 // Used for copy();
 GfxState::GfxState(const GfxState *state, bool copyPath) {
   int i;
 
-  memcpy(this, state, sizeof(GfxState));
+  hDPI = state->hDPI;
+  vDPI = state->vDPI;
+  memcpy(ctm, state->ctm, sizeof(ctm));
+  px1 = state->px1;
+  py1 = state->py1;
+  px2 = state->px2;
+  py2 = state->py2;
+  pageWidth = state->pageWidth;
+  pageHeight = state->pageHeight;
+  rotate = state->rotate;
+
+  fillColorSpace = state->fillColorSpace;
   if (fillColorSpace) {
     fillColorSpace = state->fillColorSpace->copy();
   }
+  strokeColorSpace = state->strokeColorSpace;
   if (strokeColorSpace) {
     strokeColorSpace = state->strokeColorSpace->copy();
   }
+  fillColor = state->fillColor;
+  strokeColor = state->strokeColor;
+
+  fillPattern = state->fillPattern;
   if (fillPattern) {
     fillPattern = state->fillPattern->copy();
   }
+  strokePattern = state->strokePattern;
   if (strokePattern) {
     strokePattern = state->strokePattern->copy();
   }
+  blendMode = state->blendMode;
+  fillOpacity = state->fillOpacity;
+  strokeOpacity = state->strokeOpacity;
+  fillOverprint = state->fillOverprint;
+  strokeOverprint = state->strokeOverprint;
+  overprintMode = state->overprintMode;
   for (i = 0; i < 4; ++i) {
+    transfer[i] = state->transfer[i];
     if (transfer[i]) {
       transfer[i] = state->transfer[i]->copy();
     }
   }
+  lineWidth = state->lineWidth;
+  lineDashLength = state->lineDashLength;
+  lineDash = nullptr;
   if (lineDashLength > 0) {
     lineDash = (double *)gmallocn(lineDashLength, sizeof(double));
     memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
   }
+  lineDashStart = state->lineDashStart;
+  flatness = state->flatness;
+  lineJoin = state->lineJoin;
+  lineCap = state->lineCap;
+  miterLimit = state->miterLimit;
+  strokeAdjust = state->strokeAdjust;
+  alphaIsShape = state->alphaIsShape;
+  textKnockout = state->textKnockout;
+
+  font = state->font;
   if (font)
     font->incRefCnt();
-
+  fontSize = state->fontSize;
+  memcpy(textMat, state->textMat, sizeof(textMat));
+  charSpace = state->charSpace;
+  wordSpace = state->wordSpace;
+  horizScaling = state->horizScaling;
+  leading = state->leading;
+  rise = state->rise;
+  render = state->render;
+
+  path = state->path;
   if (copyPath) {
     path = state->path->copy();
   }
+  curX = state->curX;
+  curY = state->curY;
+  lineX = state->lineX;
+  lineY = state->lineY;
+
+  clipXMin = state->clipXMin;
+  clipYMin = state->clipYMin;
+  clipXMax = state->clipXMax;
+  clipYMax = state->clipYMax;
+  memcpy(renderingIntent, state->renderingIntent, sizeof(renderingIntent));
+
   saved = nullptr;
 #ifdef USE_CMS
-  if (XYZ2DisplayTransformRelCol) {
-    XYZ2DisplayTransformRelCol->ref();
-  }
-  if (XYZ2DisplayTransformAbsCol) {
-    XYZ2DisplayTransformAbsCol->ref();
-  }
-  if (XYZ2DisplayTransformSat) {
-    XYZ2DisplayTransformSat->ref();
-  }
-  if (XYZ2DisplayTransformPerc) {
-    XYZ2DisplayTransformPerc->ref();
-  }
-  if (localDisplayProfile) {
-    displayProfileRef++;
-  }
+  localDisplayProfile = state->localDisplayProfile;
+  XYZ2DisplayTransformRelCol = state->XYZ2DisplayTransformRelCol;
+  XYZ2DisplayTransformAbsCol = state->XYZ2DisplayTransformAbsCol;
+  XYZ2DisplayTransformSat = state->XYZ2DisplayTransformSat;
+  XYZ2DisplayTransformPerc = state->XYZ2DisplayTransformPerc;
 #endif
 }
 
 #ifdef USE_CMS
-void GfxState::setDisplayProfile(cmsHPROFILE localDisplayProfileA) {
-  if (localDisplayProfile != nullptr) {
-    cmsCloseProfile(localDisplayProfile);
-  }
+void GfxState::setDisplayProfile(const GfxLCMSProfilePtr& localDisplayProfileA) {
   localDisplayProfile = localDisplayProfileA;
-  if (localDisplayProfileA != nullptr) {
+  if (localDisplayProfile) {
     cmsHTRANSFORM transform;
     unsigned int nChannels;
     unsigned int localDisplayPixelType;
 
-    localDisplayPixelType = getCMSColorSpaceType(cmsGetColorSpace(localDisplayProfile));
-    nChannels = getCMSNChannels(cmsGetColorSpace(localDisplayProfile));
-    displayProfileRef = 1;
+    localDisplayPixelType = getCMSColorSpaceType(cmsGetColorSpace(localDisplayProfile.get()));
+    nChannels = getCMSNChannels(cmsGetColorSpace(localDisplayProfile.get()));
     // create transform from XYZ
-    cmsHPROFILE XYZProfile = cmsCreateXYZProfile();
-    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
-	   localDisplayProfile,
+    auto XYZProfile = make_GfxLCMSProfilePtr(cmsCreateXYZProfile());
+    if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
+	   localDisplayProfile.get(),
 	   COLORSPACE_SH(localDisplayPixelType) |
 	     CHANNELS_SH(nChannels) | BYTES_SH(1),
 	  INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
-      cmsCloseProfile(XYZProfile);
     } else {
-      XYZ2DisplayTransformRelCol = new GfxColorTransform(XYZProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);
+      XYZ2DisplayTransformRelCol = std::make_shared<GfxColorTransform>(XYZProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);
     }
 
-    XYZProfile = cmsCreateXYZProfile();
-    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
-	   localDisplayProfile,
+    if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
+	   localDisplayProfile.get(),
 	   COLORSPACE_SH(localDisplayPixelType) |
 	     CHANNELS_SH(nChannels) | BYTES_SH(1),
 	  INTENT_ABSOLUTE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
-      cmsCloseProfile(XYZProfile);
     } else {
-      XYZ2DisplayTransformAbsCol = new GfxColorTransform(XYZProfile, transform, INTENT_ABSOLUTE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);
+      XYZ2DisplayTransformAbsCol = std::make_shared<GfxColorTransform>(XYZProfile, transform, INTENT_ABSOLUTE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);
     }
 
-    XYZProfile = cmsCreateXYZProfile();
-    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
-	   localDisplayProfile,
+    if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
+	   localDisplayProfile.get(),
 	   COLORSPACE_SH(localDisplayPixelType) |
 	     CHANNELS_SH(nChannels) | BYTES_SH(1),
 	  INTENT_SATURATION,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
-      cmsCloseProfile(XYZProfile);
     } else {
-      XYZ2DisplayTransformSat = new GfxColorTransform(XYZProfile, transform, INTENT_SATURATION, PT_XYZ, localDisplayPixelType);
+      XYZ2DisplayTransformSat = std::make_shared<GfxColorTransform>(XYZProfile, transform, INTENT_SATURATION, PT_XYZ, localDisplayPixelType);
     }
 
-    XYZProfile = cmsCreateXYZProfile();
-    if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
-	   localDisplayProfile,
+    if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
+	   localDisplayProfile.get(),
 	   COLORSPACE_SH(localDisplayPixelType) |
 	     CHANNELS_SH(nChannels) | BYTES_SH(1),
 	  INTENT_PERCEPTUAL,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
-      cmsCloseProfile(XYZProfile);
     } else {
-      XYZ2DisplayTransformPerc = new GfxColorTransform(XYZProfile, transform, INTENT_PERCEPTUAL, PT_XYZ, localDisplayPixelType);
+      XYZ2DisplayTransformPerc = std::make_shared<GfxColorTransform>(XYZProfile, transform, INTENT_PERCEPTUAL, PT_XYZ, localDisplayPixelType);
     }
   }
 }
 
-GfxColorTransform *GfxState::getXYZ2DisplayTransform() {
-  GfxColorTransform *transform;
-
-  transform = XYZ2DisplayTransformRelCol;
+std::shared_ptr<GfxColorTransform> GfxState::getXYZ2DisplayTransform() {
+  auto transform = XYZ2DisplayTransformRelCol;
   if (strcmp(renderingIntent, "AbsoluteColorimetric") == 0) {
     transform = XYZ2DisplayTransformAbsCol;
   } else if (strcmp(renderingIntent, "Saturation") == 0) {
@@ -6688,7 +6668,7 @@ GfxColorTransform *GfxState::getXYZ2DisplayTransform() {
   } else if (strcmp(renderingIntent, "Perceptual") == 0) {
     transform = XYZ2DisplayTransformPerc;
   }
-  if (transform == nullptr) {
+  if (!transform) {
     transform = XYZ2DisplayTransform;
   }
   return transform;
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index 8119898d..1a673b20 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -42,6 +42,7 @@
 
 #include <cassert>
 #include <map>
+#include <memory>
 
 class Array;
 class Gfx;
@@ -189,12 +190,21 @@ enum GfxColorSpaceMode {
   csPattern
 };
 
+// This shall hold a cmsHPROFILE handle.
+// Only use the make_GfxLCMSProfilePtr function to construct this pointer,
+// to ensure that the resources are properly released after usage.
+typedef std::shared_ptr<void> GfxLCMSProfilePtr;
+
+#ifdef USE_CMS
+GfxLCMSProfilePtr make_GfxLCMSProfilePtr(void* profile);
+#endif
+
 // wrapper of cmsHTRANSFORM to copy
 class GfxColorTransform {
 public:
   void doTransform(void *in, void *out, unsigned int size);
   // transformA should be a cmsHTRANSFORM
-  GfxColorTransform(void *sourceProfileA, void *transformA, int cmsIntent,
+  GfxColorTransform(const GfxLCMSProfilePtr& sourceProfileA, void *transformA, int cmsIntent,
                     unsigned int inputPixelType, unsigned int transformPixelType);
   ~GfxColorTransform();
   GfxColorTransform(const GfxColorTransform &) = delete;
@@ -202,15 +212,12 @@ public:
   int getIntent() const { return cmsIntent; }
   int getInputPixelType() const { return inputPixelType; }
   int getTransformPixelType() const { return transformPixelType; }
-  void ref();
-  unsigned int unref();
-  void *getSourceProfile() { return sourceProfile; }
+  GfxLCMSProfilePtr getSourceProfile() { return sourceProfile; }
   char *getPostScriptCSA();
 private:
   GfxColorTransform() {}
-  void *sourceProfile;
+  GfxLCMSProfilePtr sourceProfile;
   void *transform;
-  unsigned int refCount;
   int cmsIntent;
   unsigned int inputPixelType;
   unsigned int transformPixelType;
@@ -282,13 +289,10 @@ public:
 
 #ifdef USE_CMS
   static int setupColorProfiles();
-  // displayProfileA should be a cmsHPROFILE 
-  static void setDisplayProfile(void *displayProfileA);
+  static void setDisplayProfile(const GfxLCMSProfilePtr& displayProfileA);
   static void setDisplayProfileName(GooString *name);
-  // result will be a cmsHPROFILE 
-  static void *getRGBProfile();
-  // result will be a cmsHPROFILE 
-  static void *getDisplayProfile();
+  static GfxLCMSProfilePtr getRGBProfile();
+  static GfxLCMSProfilePtr getDisplayProfile();
 #endif
 protected:
 
@@ -370,7 +374,7 @@ private:
   double kr, kg, kb;		    // gamut mapping mulitpliers
   void getXYZ(const GfxColor *color, double *pX, double *pY, double *pZ) const;
 #ifdef USE_CMS
-  GfxColorTransform *transform;
+  std::shared_ptr<GfxColorTransform> transform;
 #endif
 };
 
@@ -452,7 +456,7 @@ private:
   double kr, kg, kb;		    // gamut mapping mulitpliers
   void getXYZ(const GfxColor *color, double *pX, double *pY, double *pZ) const;
 #ifdef USE_CMS
-  GfxColorTransform *transform;
+  std::shared_ptr<GfxColorTransform> transform;
 #endif
 };
 
@@ -533,7 +537,7 @@ private:
   double kr, kg, kb;		    // gamut mapping mulitpliers
   void getXYZ(const GfxColor *color, double *pX, double *pY, double *pZ) const;
 #ifdef USE_CMS
-  GfxColorTransform *transform;
+  std::shared_ptr<GfxColorTransform> transform;
 #endif
 };
 
@@ -589,8 +593,8 @@ private:
   Ref iccProfileStream;		// the ICC profile
 #ifdef USE_CMS
   int getIntent() { return (transform != nullptr) ? transform->getIntent() : 0; }
-  GfxColorTransform *transform;
-  GfxColorTransform *lineTransform; // color transform for line
+  std::shared_ptr<GfxColorTransform> transform;
+  std::shared_ptr<GfxColorTransform> lineTransform; // color transform for line
   mutable std::map<unsigned int, unsigned int> cmsCache;
 #endif
 };
@@ -1601,9 +1605,9 @@ public:
     { strncpy(renderingIntent, intent, 31); }
 
 #ifdef USE_CMS
-  void setDisplayProfile(void *localDisplayProfileA);
-  void *getDisplayProfile() { return localDisplayProfile; }
-  GfxColorTransform *getXYZ2DisplayTransform();
+  void setDisplayProfile(const GfxLCMSProfilePtr& localDisplayProfileA);
+  GfxLCMSProfilePtr getDisplayProfile() { return localDisplayProfile; }
+  std::shared_ptr<GfxColorTransform> getXYZ2DisplayTransform();
   int getCmsRenderingIntent();
 #endif
 
@@ -1701,12 +1705,11 @@ private:
   GfxState(const GfxState *state, bool copyPath);
 
 #ifdef USE_CMS
-  void *localDisplayProfile;
-  int displayProfileRef;
-  GfxColorTransform *XYZ2DisplayTransformRelCol;
-  GfxColorTransform *XYZ2DisplayTransformAbsCol;
-  GfxColorTransform *XYZ2DisplayTransformSat;
-  GfxColorTransform *XYZ2DisplayTransformPerc;
+  GfxLCMSProfilePtr localDisplayProfile;
+  std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformRelCol;
+  std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformAbsCol;
+  std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformSat;
+  std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformPerc;
 #endif
 };
 
diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc
index cba9da39..901fc4e7 100644
--- a/qt5/src/poppler-document.cc
+++ b/qt5/src/poppler-document.cc
@@ -648,7 +648,7 @@ namespace Poppler {
     void Document::setColorDisplayProfile(void* outputProfileA)
     {
 #if defined(USE_CMS)
-        GfxColorSpace::setDisplayProfile((cmsHPROFILE)outputProfileA);
+        GfxColorSpace::setDisplayProfile(make_GfxLCMSProfilePtr(outputProfileA));
 #else
         Q_UNUSED(outputProfileA);
 #endif
@@ -668,7 +668,7 @@ namespace Poppler {
     void* Document::colorRgbProfile() const
     {
 #if defined(USE_CMS)
-        return (void*)GfxColorSpace::getRGBProfile();
+        return GfxColorSpace::getRGBProfile().get();
 #else
         return nullptr;
 #endif
@@ -677,7 +677,7 @@ namespace Poppler {
     void* Document::colorDisplayProfile() const
     {
 #if defined(USE_CMS)
-       return (void*)GfxColorSpace::getDisplayProfile();
+       return GfxColorSpace::getDisplayProfile().get();
 #else
        return nullptr;
 #endif
diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h
index 665f98a4..e7d6ccb1 100644
--- a/qt5/src/poppler-qt5.h
+++ b/qt5/src/poppler-qt5.h
@@ -1190,7 +1190,10 @@ delete it;
 
 	  \param outputProfileA is a \c cmsHPROFILE of the LCMS library.
 
-	  \note This should be called before any rendering happens and only once during the lifetime of the current process.
+	  \note This should be called before any rendering happens.
+
+	  \note It is assumed that poppler takes over the owernship of the corresponding cmsHPROFILE. In particular,
+          it is no longer the caller's responsibility to close the profile after use.
 
 	   \since 0.12
 	*/
@@ -1210,6 +1213,9 @@ delete it;
 
 	  \return a \c cmsHPROFILE of the LCMS library.
 
+	  \note The returned profile stays a property of poppler and shall NOT be closed by the user. It's
+	  existence is guaranteed for as long as this instance of the Document class is not deleted.
+
 	   \since 0.12
 	*/
 	void* colorRgbProfile() const;
@@ -1218,6 +1224,9 @@ delete it;
 
 	  \return a \c cmsHPROFILE of the LCMS library.
 
+	  \note The returned profile stays a property of poppler and shall NOT be closed by the user. It's
+	  existence is guaranteed for as long as this instance of the Document class is not deleted.
+
 	   \since 0.12
 	*/
 	void *colorDisplayProfile() const;
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index af07a9e5..553f14c4 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -288,7 +288,7 @@ static cairo_antialias_t antialiasEnum = CAIRO_ANTIALIAS_DEFAULT;
 #ifdef USE_CMS
 static unsigned char *icc_data;
 static int icc_data_size;
-static cmsHPROFILE profile;
+static GfxLCMSProfilePtr profile;
 #endif
 
 struct AntialiasOption
@@ -413,7 +413,7 @@ static void writePageImage(GooString *filename)
       cmsUInt8Number profileID[17];
       profileID[16] = '\0';
 
-      cmsGetHeaderProfileID(profile,profileID);
+      cmsGetHeaderProfileID(profile.get(),profileID);
       static_cast<PNGWriter*>(writer)->setICCProfile(reinterpret_cast<char *>(profileID), icc_data, icc_data_size);
     } else {
       static_cast<PNGWriter*>(writer)->setSRGBProfile();
@@ -1128,13 +1128,13 @@ int main(int argc, char *argv[]) {
       exit(4);
     }
     fclose(file);
-    profile = cmsOpenProfileFromMem(icc_data, icc_data_size);
+    profile = make_GfxLCMSProfilePtr(cmsOpenProfileFromMem(icc_data, icc_data_size));
     if (!profile) {
       fprintf(stderr, "Error: lcms error opening profile\n");
       exit(4);
     }
   } else {
-    profile = cmsCreate_sRGBProfile();
+    profile = make_GfxLCMSProfilePtr(cmsCreate_sRGBProfile());
   }
   GfxColorSpace::setDisplayProfile(profile);
 #endif
@@ -1286,7 +1286,6 @@ int main(int argc, char *argv[]) {
     delete userPW;
 
 #ifdef USE_CMS
-  cmsCloseProfile(profile);
   if (icc_data)
     gfree(icc_data);
 #endif


More information about the poppler mailing list