[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freedesktop-poppler
Subject:    [poppler] 4 commits - poppler/Gfx.cc poppler/GfxState.cc poppler/GfxState.h poppler/OutputDev.h popp
From:       GitLab Mirror <gitlab-mirror () kemper ! freedesktop ! org>
Date:       2020-06-02 22:08:13
Message-ID: 20200602220813.B977C7610B () kemper ! freedesktop ! org
[Download RAW message or body]

 poppler/Gfx.cc              |    1 
 poppler/GfxState.cc         |  255 +++++++++++---------------------------------
 poppler/GfxState.h          |   18 +--
 poppler/OutputDev.h         |   26 ++--
 poppler/Page.cc             |   27 ++--
 qt5/src/CMakeLists.txt      |    3 
 qt5/src/poppler-document.cc |   23 ++-
 qt5/src/poppler-page.cc     |    8 +
 qt5/src/poppler-private.h   |    4 
 utils/pdftocairo.cc         |    4 
 10 files changed, 134 insertions(+), 235 deletions(-)

New commits:
commit 7257d33a3a938d5621aab0ed53b09c7ce797a646
Author: Philipp Knechtges <philipp-dev@knechtges.com>
Date:   Fri May 22 18:23:09 2020 +0200

    add a dummy GfxState to Page::loadThumb for proper color space handling
    
    As far as I can tell this was the only remaining spot in the code where
    GfxColorSpace::parse was called without a properly initialized GfxState.

diff --git a/poppler/Page.cc b/poppler/Page.cc
index 670768ab..2ac178d7 100644
--- a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -643,7 +643,6 @@ bool Page::loadThumb(unsigned char **data_out,
   Object obj1;
   Dict *dict;
   GfxColorSpace *colorSpace;
-  bool success = false;
   Stream *str;
   GfxImageColorMap *colorMap;
 
@@ -658,17 +657,17 @@ bool Page::loadThumb(unsigned char **data_out,
   str = fetched_thumb.getStream(); 
 		
   if (!dict->lookupInt("Width", "W", &width))
-    goto fail1;
+    return false;
   if (!dict->lookupInt("Height", "H", &height))
-    goto fail1;
+    return false;
   if (!dict->lookupInt("BitsPerComponent", "BPC", &bits))
-    goto fail1;
+    return false;
 		
   /* Check for invalid dimensions and integer overflow. */
   if (width <= 0 || height <= 0)
-    goto fail1;
+    return false;
   if (width > INT_MAX / 3 / height)
-    goto fail1;
+    return false;
   pixbufdatasize = width * height * 3;
 
   /* Get color space */
@@ -676,10 +675,14 @@ bool Page::loadThumb(unsigned char **data_out,
   if (obj1.isNull ()) {
     obj1 = dict->lookup ("CS");
   }
-  colorSpace = GfxColorSpace::parse(nullptr, &obj1, nullptr, nullptr);
+  // Just initialize some dummy GfxState for GfxColorSpace::parse.
+  // This will set a sRGB profile for ICC-based colorspaces.
+  auto pdfrectangle = std::make_shared<PDFRectangle>();
+  auto state = std::make_shared<GfxState>(72.0,72.0,pdfrectangle.get(), 0, false);
+  colorSpace = GfxColorSpace::parse(nullptr, &obj1, nullptr, state.get());
   if (!colorSpace) {
     fprintf (stderr, "Error: Cannot parse color space\n");
-    goto fail1;
+    return false;
   }
 
   obj1 = dict->lookup("Decode");
@@ -690,7 +693,7 @@ bool Page::loadThumb(unsigned char **data_out,
   if (!colorMap->isOk()) {
     fprintf (stderr, "Error: invalid colormap\n");
     delete colorMap;
-    goto fail1;
+    return false;
   }
 
   if (data_out) {
@@ -718,8 +721,6 @@ bool Page::loadThumb(unsigned char **data_out,
     delete imgstr;
   }
 
-  success = true;
-
   if (width_out)
     *width_out = width;
   if (height_out)
@@ -728,8 +729,8 @@ bool Page::loadThumb(unsigned char **data_out,
     *rowstride_out = width * 3;
 
   delete colorMap;
- fail1:
-  return success;
+
+  return true;
 }
 
 void Page::makeBox(double hDPI, double vDPI, int rotate,
commit b2141b8921525141560b8e4ef5a351f505d7cf5b
Author: Philipp Knechtges <philipp-dev@knechtges.com>
Date:   Fri May 22 18:17:16 2020 +0200

    cleanup displayprofile initialization
    
    There were a bunch of global variables that were used to initilize the first \
version  of the display profiles. This code was removed, and all the static \
initilization was moved  from GfxColorSpace to GfxState. Furthermore, for most \
"users" the setting of the  display profile was moved from the static \
GfxColorSpace::setDisplayProfile function  to the OutputDev class. The latter is now \
invoked early in the initilization of Gfx  to set the initial state in the GfxState \
instance.

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 2a5b295c..37a8996a 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -548,6 +548,7 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict \
*resDict,  // initialize
   out = outA;
   state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown());
+  out->initGfxState(state);
   stackHeight = 1;
   pushStateGuard();
   fontChanged = false;
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 51922565..e8091681 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -189,9 +189,6 @@ static const std::map<unsigned int, unsigned int>::size_type \
CMSCACHE_LIMIT = 20  #include <lcms2.h>
 #define LCMS_FLAGS cmsFLAGS_NOOPTIMIZE | cmsFLAGS_BLACKPOINTCOMPENSATION
 
-#define COLOR_PROFILE_DIR "/ColorProfiles/"
-#define GLOBAL_COLOR_PROFILE_DIR POPPLER_DATADIR COLOR_PROFILE_DIR
-
 static void lcmsprofiledeleter(void* profile)
 {
     cmsCloseProfile(profile);
@@ -221,59 +218,9 @@ GfxColorTransform::~GfxColorTransform() {
   cmsDeleteTransform(transform);
 }
 
-static GfxLCMSProfilePtr RGBProfile = nullptr;
-static GooString *displayProfileName = nullptr; // display profile file Name
-static GfxLCMSProfilePtr displayProfile = nullptr; // display profile
-static unsigned int displayPixelType = 0;
-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 GfxLCMSProfilePtr loadColorProfile(const char *fileName);
-
-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) {
-    cmsHTRANSFORM transform;
-    unsigned int nChannels;
-
-    displayPixelType = getCMSColorSpaceType(cmsGetColorSpace(displayProfile.get()));
-    nChannels = getCMSNChannels(cmsGetColorSpace(displayProfile.get()));
-    // create transform from XYZ
-    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 = std::make_shared<GfxColorTransform>(transform, \
                INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
-    }
-  }
-}
-
-void GfxColorSpace::setDisplayProfileName(GooString *name) {
-  if (displayProfile != nullptr) {
-    error(errInternal, -1, "The display color profile can only be set before any \
                rendering is done.");
-    return;
-  }
-  delete displayProfileName;
-  displayProfileName = name->copy();
-}
-
-GfxLCMSProfilePtr GfxColorSpace::getRGBProfile() {
-  return RGBProfile;
-}
-
-GfxLCMSProfilePtr GfxColorSpace::getDisplayProfile() {
-  return displayProfile;
-}
 
 #endif
 
@@ -459,83 +406,12 @@ const char *GfxColorSpace::getColorSpaceModeName(int idx) {
 }
 
 #ifdef USE_CMS
-GfxLCMSProfilePtr loadColorProfile(const char *fileName)
-{
-  cmsHPROFILE hp = nullptr;
-  FILE *fp;
-
-  if (fileName[0] == '/') {
-    // full path
-    // check if open the file
-    if ((fp = openFile(fileName,"r")) != nullptr) {
-      fclose(fp);
-      hp = cmsOpenProfileFromFile(fileName,"r");
-    }
-    return make_GfxLCMSProfilePtr(hp);
-  }
-  // try to load from global directory
-  GooString *path = new GooString(GLOBAL_COLOR_PROFILE_DIR);
-  path->append(fileName);
-  // check if open the file
-  if ((fp = openFile(path->c_str(),"r")) != nullptr) {
-    fclose(fp);
-    hp = cmsOpenProfileFromFile(path->c_str(),"r");
-  }
-  delete path;
-  return make_GfxLCMSProfilePtr(hp);
-}
 
 static void CMSError(cmsContext /*contextId*/, cmsUInt32Number /*ecode*/, const char \
*text)  {
     error(errSyntaxWarning, -1, "{0:s}", text);
 }
 
-int GfxColorSpace::setupColorProfiles()
-{
-  static bool initialized = false;
-  cmsHTRANSFORM transform;
-  unsigned int nChannels;
-
-  // do only once
-  if (initialized) return 0;
-  initialized = true;
-
-  // set error handlor
-  cmsSetLogErrorHandler(CMSError);
-
-  if (!displayProfile) {
-    // load display profile if it was not already loaded.
-    if (displayProfileName == nullptr) {
-      displayProfile = loadColorProfile("display.icc");
-    } else if (displayProfileName->getLength() > 0) {
-      displayProfile = loadColorProfile(displayProfileName->c_str());
-    }
-  }
-  // load RGB profile
-  RGBProfile = loadColorProfile("RGB.icc");
-  if (!RGBProfile) {
-    /* use built in sRGB profile */
-    RGBProfile = make_GfxLCMSProfilePtr(cmsCreate_sRGBProfile());
-  }
-  // create transforms
-  if (displayProfile) {
-    displayPixelType = getCMSColorSpaceType(cmsGetColorSpace(displayProfile.get()));
-    nChannels = getCMSNChannels(cmsGetColorSpace(displayProfile.get()));
-    // create transform from XYZ
-    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 = std::make_shared<GfxColorTransform>(transform, \
                INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
-    }
-  }
-  return 0;
-}
-
 unsigned int getCMSColorSpaceType(cmsColorSpaceSignature cs)
 {
     switch (cs) {
@@ -815,7 +691,7 @@ GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr, GfxState \
*state) {  xyzrgb[2][1] * cs->whiteY +
 		xyzrgb[2][2] * cs->whiteZ);
 #ifdef USE_CMS
-  cs->transform = (state != nullptr) ? state->getXYZ2DisplayTransform() : \
XYZ2DisplayTransform; +  cs->transform = (state != nullptr) ? \
state->getXYZ2DisplayTransform() : nullptr;  #endif
   return cs;
 }
@@ -1175,7 +1051,7 @@ GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr, GfxState \
*state) {  xyzrgb[2][2] * cs->whiteZ);
 
 #ifdef USE_CMS
-  cs->transform = (state != nullptr) ? state->getXYZ2DisplayTransform() : \
XYZ2DisplayTransform; +  cs->transform = (state != nullptr) ? \
state->getXYZ2DisplayTransform() : nullptr;  #endif
   return cs;
 }
@@ -1521,7 +1397,7 @@ GfxColorSpace *GfxLabColorSpace::parse(Array *arr, GfxState \
*state) {  xyzrgb[2][2] * cs->whiteZ);
 
 #ifdef USE_CMS
-  cs->transform = (state != nullptr) ? state->getXYZ2DisplayTransform() : \
XYZ2DisplayTransform; +  cs->transform = (state != nullptr) ? \
state->getXYZ2DisplayTransform() : nullptr;  #endif
   return cs;
 }
@@ -1838,12 +1714,9 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, \
OutputDev *out, GfxState  if (!hp) {
     error(errSyntaxWarning, -1, "read ICCBased color space profile error");
   } else {
-    auto dhp = (state != nullptr && state->getDisplayProfile() != nullptr) ? \
state->getDisplayProfile() : displayProfile; +    auto dhp = (state != nullptr && \
state->getDisplayProfile() != nullptr) ? state->getDisplayProfile() : nullptr;  if \
                (!dhp) {
-      if (unlikely(!RGBProfile)) {
-        GfxColorSpace::setupColorProfiles();
-      }
-      dhp = RGBProfile;
+      dhp = GfxState::sRGBProfile;
     }
     unsigned int cst = getCMSColorSpaceType(cmsGetColorSpace(hp.get()));
     unsigned int dNChannels = getCMSNChannels(cmsGetColorSpace(dhp.get()));
@@ -6461,12 +6334,22 @@ GfxState::GfxState(double hDPIA, double vDPIA, const \
PDFRectangle *pageBox,  
   saved = nullptr;
 #ifdef USE_CMS
-  GfxColorSpace::setupColorProfiles();
   XYZ2DisplayTransformRelCol = nullptr;
   XYZ2DisplayTransformAbsCol = nullptr;
   XYZ2DisplayTransformSat = nullptr;
   XYZ2DisplayTransformPerc = nullptr;
   localDisplayProfile = nullptr;
+
+  if (!sRGBProfile) {
+    // This is probably the one of the first invocations of lcms2, so we set the \
error handler +    cmsSetLogErrorHandler(CMSError);
+
+    sRGBProfile = make_GfxLCMSProfilePtr(cmsCreate_sRGBProfile());
+  }
+
+  if (!XYZProfile) {
+    XYZProfile = make_GfxLCMSProfilePtr(cmsCreateXYZProfile());
+  }
 #endif
 }
 
@@ -6600,6 +6483,10 @@ GfxState::GfxState(const GfxState *state, bool copyPath) {
 }
 
 #ifdef USE_CMS
+
+GfxLCMSProfilePtr GfxState::sRGBProfile = nullptr;
+GfxLCMSProfilePtr GfxState::XYZProfile = nullptr;
+
 void GfxState::setDisplayProfile(const GfxLCMSProfilePtr& localDisplayProfileA) {
   localDisplayProfile = localDisplayProfileA;
   if (localDisplayProfile) {
@@ -6610,7 +6497,6 @@ void GfxState::setDisplayProfile(const GfxLCMSProfilePtr& \
                localDisplayProfileA)
     localDisplayPixelType = \
                getCMSColorSpaceType(cmsGetColorSpace(localDisplayProfile.get()));
     nChannels = getCMSNChannels(cmsGetColorSpace(localDisplayProfile.get()));
     // create transform from XYZ
-    auto XYZProfile = make_GfxLCMSProfilePtr(cmsCreateXYZProfile());
     if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
 	   localDisplayProfile.get(),
 	   COLORSPACE_SH(localDisplayPixelType) |
@@ -6662,9 +6548,6 @@ std::shared_ptr<GfxColorTransform> \
GfxState::getXYZ2DisplayTransform() {  } else if (strcmp(renderingIntent, \
"Perceptual") == 0) {  transform = XYZ2DisplayTransformPerc;
   }
-  if (!transform) {
-    transform = XYZ2DisplayTransform;
-  }
   return transform;
 }
 
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index be5bb7df..c30c1a99 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -283,13 +283,6 @@ public:
   // Return the name of the <idx>th color space mode.
   static const char *getColorSpaceModeName(int idx);
 
-#ifdef USE_CMS
-  static int setupColorProfiles();
-  static void setDisplayProfile(const GfxLCMSProfilePtr& displayProfileA);
-  static void setDisplayProfileName(GooString *name);
-  static GfxLCMSProfilePtr getRGBProfile();
-  static GfxLCMSProfilePtr getDisplayProfile();
-#endif
 protected:
 
   unsigned int overprintMask;
@@ -1608,6 +1601,7 @@ public:
   GfxLCMSProfilePtr getDisplayProfile() { return localDisplayProfile; }
   std::shared_ptr<GfxColorTransform> getXYZ2DisplayTransform();
   int getCmsRenderingIntent();
+  static GfxLCMSProfilePtr sRGBProfile;
 #endif
 
   // Add to path.
@@ -1709,6 +1703,7 @@ private:
   std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformAbsCol;
   std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformSat;
   std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformPerc;
+  static GfxLCMSProfilePtr XYZProfile;
 #endif
 };
 
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index 9dc052ae..609fa8d5 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -40,6 +40,7 @@
 #include "Object.h"
 #include "PopplerCache.h"
 #include "ProfileData.h"
+#include "GfxState.h"
 #include <memory>
 #include <unordered_map>
 #include <string>
@@ -47,21 +48,7 @@
 class Annot;
 class Dict;
 class GooString;
-class GfxState;
 class Gfx;
-struct GfxColor;
-class GfxColorSpace;
-#ifdef USE_CMS
-class GfxICCBasedColorSpace;
-#endif
-class GfxImageColorMap;
-class GfxFunctionShading;
-class GfxAxialShading;
-class GfxGouraudTriangleShading;
-class GfxPatchMeshShading;
-class GfxRadialShading;
-class GfxGouraudTriangleShading;
-class GfxPatchMeshShading;
 class Stream;
 class Links;
 class AnnotLink;
@@ -150,6 +137,13 @@ public:
   // Dump page contents to display.
   virtual void dump() {}
 
+  virtual void initGfxState (GfxState* state)
+  {
+#ifdef USE_CMS
+    state->setDisplayProfile(displayprofile);
+#endif
+  }
+
   //----- coordinate conversion
 
   // Convert between device and user coordinates.
@@ -370,6 +364,8 @@ public:
 #endif
 
 #ifdef USE_CMS
+  void setDisplayProfile(const GfxLCMSProfilePtr& profile) { displayprofile = \
profile; } +
   PopplerCache<Ref, GfxICCBasedColorSpace> *getIccColorSpaceCache() { return \
&iccColorSpaceCache; }  #endif
 
@@ -380,6 +376,8 @@ private:
   std::unique_ptr<std::unordered_map<std::string, ProfileData>> profileHash;
 
 #ifdef USE_CMS
+  GfxLCMSProfilePtr displayprofile;
+
   PopplerCache<Ref, GfxICCBasedColorSpace> iccColorSpaceCache;
 #endif
 };
diff --git a/qt5/src/CMakeLists.txt b/qt5/src/CMakeLists.txt
index e75b5730..bbcd612d 100644
--- a/qt5/src/CMakeLists.txt
+++ b/qt5/src/CMakeLists.txt
@@ -52,6 +52,9 @@ endif()
 if (ENABLE_NSS3)
     target_include_directories(poppler-qt5 SYSTEM PRIVATE ${NSS3_INCLUDE_DIRS})
 endif()
+if(USE_CMS)
+    target_link_libraries(poppler-qt5 poppler ${LCMS2_LIBRARIES})
+endif()
 install(TARGETS poppler-qt5 RUNTIME DESTINATION bin LIBRARY DESTINATION \
${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})  
 install(FILES
diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc
index a40d4bac..cc6f01ad 100644
--- a/qt5/src/poppler-document.cc
+++ b/qt5/src/poppler-document.cc
@@ -649,7 +649,16 @@ namespace Poppler {
     void Document::setColorDisplayProfile(void* outputProfileA)
     {
 #if defined(USE_CMS)
-        GfxColorSpace::setDisplayProfile(make_GfxLCMSProfilePtr(outputProfileA));
+        if (m_doc->m_sRGBProfile && m_doc->m_sRGBProfile.get() == outputProfileA) {
+            // Catch the special case that the user passes the sRGB profile
+            m_doc->m_displayProfile = m_doc->m_sRGBProfile;
+            return;
+        }
+        if (m_doc->m_displayProfile && m_doc->m_displayProfile.get() == \
outputProfileA) { +            // Catch the special case that the user passes the \
display profile +            return;
+        }
+        m_doc->m_displayProfile = make_GfxLCMSProfilePtr(outputProfileA);
 #else
         Q_UNUSED(outputProfileA);
 #endif
@@ -658,9 +667,8 @@ namespace Poppler {
     void Document::setColorDisplayProfileName(const QString &name)
     {
 #if defined(USE_CMS)
-        GooString *profileName = QStringToGooString( name );
-        GfxColorSpace::setDisplayProfileName(profileName);
-        delete profileName;
+        void* rawprofile = \
cmsOpenProfileFromFile(name.toLocal8Bit().constData(),"r"); +        \
m_doc->m_displayProfile = make_GfxLCMSProfilePtr(rawprofile);  #else
         Q_UNUSED(name);
 #endif
@@ -669,7 +677,10 @@ namespace Poppler {
     void* Document::colorRgbProfile() const
     {
 #if defined(USE_CMS)
-        return GfxColorSpace::getRGBProfile().get();
+        if (!m_doc->m_sRGBProfile) {
+            m_doc->m_sRGBProfile = make_GfxLCMSProfilePtr(cmsCreate_sRGBProfile());
+        }
+        return m_doc->m_sRGBProfile.get();
 #else
         return nullptr;
 #endif
@@ -678,7 +689,7 @@ namespace Poppler {
     void* Document::colorDisplayProfile() const
     {
 #if defined(USE_CMS)
-       return GfxColorSpace::getDisplayProfile().get();
+       return m_doc->m_displayProfile.get();
 #else
        return nullptr;
 #endif
diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc
index dab4bc43..e06e88bf 100644
--- a/qt5/src/poppler-page.cc
+++ b/qt5/src/poppler-page.cc
@@ -592,6 +592,10 @@ QImage Page::renderToImage(double xres, double yres, int xPos, \
                int yPos, int w,
       splash_output.setFreeTypeHinting(m_page->parentDoc->m_hints & \
                Document::TextHinting ? true : false,
                                         m_page->parentDoc->m_hints & \
Document::TextSlightHinting ? true : false);  
+#ifdef USE_CMS
+      splash_output.setDisplayProfile(m_page->parentDoc->m_displayProfile);
+#endif
+
       splash_output.startDoc(m_page->parentDoc->doc);
 
       const bool hideAnnotations = m_page->parentDoc->m_hints & \
Document::HideAnnotations; @@ -624,6 +628,10 @@ QImage Page::renderToImage(double \
xres, double yres, int xPos, int yPos, int w,  
       arthur_output.setHintingPreference(QFontHintingFromPopplerHinting(m_page->parentDoc->m_hints));
  
+#ifdef USE_CMS
+      arthur_output.setDisplayProfile(m_page->parentDoc->m_displayProfile);
+#endif
+
       arthur_output.setCallbacks(partialUpdateCallback, \
                shouldDoPartialUpdateCallback, shouldAbortRenderCallback, payload);
       renderToArthur(&arthur_output, &painter, m_page, xres, yres, xPos, yPos, w, h, \
rotate, DontSaveAndRestore);  painter.end();
diff --git a/qt5/src/poppler-private.h b/qt5/src/poppler-private.h
index 1ccea2b9..899b4850 100644
--- a/qt5/src/poppler-private.h
+++ b/qt5/src/poppler-private.h
@@ -178,6 +178,10 @@ namespace Poppler {
 	QPointer<OptContentModel> m_optContentModel;
 	QColor paperColor;
 	int m_hints;
+#ifdef USE_CMS
+        GfxLCMSProfilePtr m_sRGBProfile;
+        GfxLCMSProfilePtr m_displayProfile;
+#endif
     };
 
     class FontInfoData
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 4f51d427..a6d9384f 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -1137,7 +1137,6 @@ int main(int argc, char *argv[]) {
   } else {
     profile = make_GfxLCMSProfilePtr(cmsCreate_sRGBProfile());
   }
-  GfxColorSpace::setDisplayProfile(profile);
 #endif
 
   doc = PDFDocFactory().createPDFDoc(*fileName, ownerPW, userPW);
@@ -1212,6 +1211,9 @@ int main(int argc, char *argv[]) {
 
 
   cairoOut = new CairoOutputDev();
+#ifdef USE_CMS
+  cairoOut->setDisplayProfile(profile);
+#endif
   cairoOut->startDoc(doc);
   if (sz != 0)
     crop_w = crop_h = sz;
commit 7dc4f0b56057aa4facc7ba559998d6dac5042792
Author: Philipp Knechtges <philipp-dev@knechtges.com>
Date:   Fri May 22 11:47:54 2020 +0200

    remove sourceProfile variable from GfxColorTransform
    
    The sourceProfile variable was initially introduced in commit \
1f698b44564b0313c019557616866eae11bf2cc9  for the Postscript CSA generation code. \
With the last commit this code has been moved to GfxICCBasedColorSpace  anyway, so \
there is no use anymore for storing the profile in GfxColorTransform.

diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 2fb78c1c..51922565 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -210,8 +210,7 @@ void GfxColorTransform::doTransform(void *in, void *out, unsigned \
int size) {  }
 
 // transformA should be a cmsHTRANSFORM
-GfxColorTransform::GfxColorTransform(const GfxLCMSProfilePtr& sourceProfileA, void \
*transformA, int cmsIntentA, unsigned int inputPixelTypeA, unsigned int \
                transformPixelTypeA) {
-  sourceProfile = sourceProfileA;
+GfxColorTransform::GfxColorTransform(void *transformA, int cmsIntentA, unsigned int \
inputPixelTypeA, unsigned int transformPixelTypeA) {  transform = transformA;
   cmsIntent = cmsIntentA;
   inputPixelType = inputPixelTypeA;
@@ -254,7 +253,7 @@ void GfxColorSpace::setDisplayProfile(const GfxLCMSProfilePtr& \
displayProfileA)  INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
     } else {
-      XYZ2DisplayTransform = std::make_shared<GfxColorTransform>(displayProfile, \
transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType); +      \
XYZ2DisplayTransform = std::make_shared<GfxColorTransform>(transform, \
INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);  }
   }
 }
@@ -531,7 +530,7 @@ int GfxColorSpace::setupColorProfiles()
 	  INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
     } else {
-      XYZ2DisplayTransform = std::make_shared<GfxColorTransform>(XYZProfile, \
transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType); +      \
XYZ2DisplayTransform = std::make_shared<GfxColorTransform>(transform, \
INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);  }
   }
   return 0;
@@ -1864,7 +1863,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, \
OutputDev *out, GfxState  error(errSyntaxWarning, -1, "Can't create transform");
       cs->transform = nullptr;
     } else {
-      cs->transform = std::make_shared<GfxColorTransform>(hp, transform, cmsIntent, \
cst, dcst); +      cs->transform = std::make_shared<GfxColorTransform>(transform, \
cmsIntent, cst, dcst);  }
     if (dcst == PT_RGB || dcst == PT_CMYK) {
        // create line transform only when the display is RGB type color space 
@@ -1874,7 +1873,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, \
OutputDev *out, GfxState  error(errSyntaxWarning, -1, "Can't create transform");
 	cs->lineTransform = nullptr;
       } else {
-	cs->lineTransform = std::make_shared<GfxColorTransform>(hp, transform, cmsIntent, \
cst, dcst); +	cs->lineTransform = std::make_shared<GfxColorTransform>(transform, \
cmsIntent, cst, dcst);  }
     }
   }
@@ -6619,7 +6618,7 @@ void GfxState::setDisplayProfile(const GfxLCMSProfilePtr& \
localDisplayProfileA)  INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
     } else {
-      XYZ2DisplayTransformRelCol = std::make_shared<GfxColorTransform>(XYZProfile, \
transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, localDisplayPixelType); +      \
XYZ2DisplayTransformRelCol = std::make_shared<GfxColorTransform>(transform, \
INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);  }
 
     if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
@@ -6629,7 +6628,7 @@ void GfxState::setDisplayProfile(const GfxLCMSProfilePtr& \
localDisplayProfileA)  INTENT_ABSOLUTE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
     } else {
-      XYZ2DisplayTransformAbsCol = std::make_shared<GfxColorTransform>(XYZProfile, \
transform, INTENT_ABSOLUTE_COLORIMETRIC, PT_XYZ, localDisplayPixelType); +      \
XYZ2DisplayTransformAbsCol = std::make_shared<GfxColorTransform>(transform, \
INTENT_ABSOLUTE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);  }
 
     if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
@@ -6639,7 +6638,7 @@ void GfxState::setDisplayProfile(const GfxLCMSProfilePtr& \
localDisplayProfileA)  INTENT_SATURATION,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
     } else {
-      XYZ2DisplayTransformSat = std::make_shared<GfxColorTransform>(XYZProfile, \
transform, INTENT_SATURATION, PT_XYZ, localDisplayPixelType); +      \
XYZ2DisplayTransformSat = std::make_shared<GfxColorTransform>(transform, \
INTENT_SATURATION, PT_XYZ, localDisplayPixelType);  }
 
     if ((transform = cmsCreateTransform(XYZProfile.get(), TYPE_XYZ_DBL,
@@ -6649,7 +6648,7 @@ void GfxState::setDisplayProfile(const GfxLCMSProfilePtr& \
localDisplayProfileA)  INTENT_PERCEPTUAL,LCMS_FLAGS)) == nullptr) {
       error(errSyntaxWarning, -1, "Can't create Lab transform");
     } else {
-      XYZ2DisplayTransformPerc = std::make_shared<GfxColorTransform>(XYZProfile, \
transform, INTENT_PERCEPTUAL, PT_XYZ, localDisplayPixelType); +      \
XYZ2DisplayTransformPerc = std::make_shared<GfxColorTransform>(transform, \
INTENT_PERCEPTUAL, PT_XYZ, localDisplayPixelType);  }
   }
 }
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index f79c6bc7..be5bb7df 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -204,7 +204,7 @@ class GfxColorTransform {
 public:
   void doTransform(void *in, void *out, unsigned int size);
   // transformA should be a cmsHTRANSFORM
-  GfxColorTransform(const GfxLCMSProfilePtr& sourceProfileA, void *transformA, int \
cmsIntent, +  GfxColorTransform(void *transformA, int cmsIntent,
                     unsigned int inputPixelType, unsigned int transformPixelType);
   ~GfxColorTransform();
   GfxColorTransform(const GfxColorTransform &) = delete;
@@ -212,10 +212,8 @@ public:
   int getIntent() const { return cmsIntent; }
   int getInputPixelType() const { return inputPixelType; }
   int getTransformPixelType() const { return transformPixelType; }
-  GfxLCMSProfilePtr getSourceProfile() { return sourceProfile; }
 private:
   GfxColorTransform() {}
-  GfxLCMSProfilePtr sourceProfile;
   void *transform;
   int cmsIntent;
   unsigned int inputPixelType;
commit 344f3e655cb0018421350c1a9916381d686025b6
Author: Philipp Knechtges <philipp-dev@knechtges.com>
Date:   Fri May 22 11:39:28 2020 +0200

    move Postscript CSA generation from GfxColorTransform to GfxICCBasedColorSpace
    
    With proper ref counting for profiles in place, we can now let \
GfxICCBasedColorSpace  directly generate the CSA rather than going through \
GfxColorTransform, which in the  pre-ref-counting era had the sole ownership on the \
profiles.

diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index fb8cb37a..2fb78c1c 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -216,51 +216,10 @@ GfxColorTransform::GfxColorTransform(const GfxLCMSProfilePtr& \
sourceProfileA, vo  cmsIntent = cmsIntentA;
   inputPixelType = inputPixelTypeA;
   transformPixelType = transformPixelTypeA;
-  psCSA = nullptr;
 }
 
 GfxColorTransform::~GfxColorTransform() {
   cmsDeleteTransform(transform);
-  if (psCSA)
-    gfree(psCSA);
-}
-
-char *GfxColorTransform::getPostScriptCSA()
-{
-#if LCMS_VERSION>=2070
-  // The runtime version check of lcms2 is only available from release 2.7 upwards.
-  // The generation of the CSA code only works reliably for version 2.10 and \
                upwards.
-  // Cf. the explanation in the corresponding lcms2 merge request [1], and the \
                original mail thread [2].
-  // [1] https://github.com/mm2/Little-CMS/pull/214
-  // [2] https://sourceforge.net/p/lcms/mailman/message/33182987/
-  if (cmsGetEncodedCMMversion() < 2100)
-    return nullptr;
-
-  int size;
-
-  if (psCSA)
-    return psCSA;
-
-  if (!sourceProfile) {
-    error(errSyntaxWarning, -1, "profile is nullptr");
-    return nullptr;
-  }
-
-  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(rawprofile), rawprofile, cmsIntent, 0, \
                psCSA, size);
-  psCSA[size] = 0;
-
-  return psCSA;
-#else
-  return nullptr;
-#endif
 }
 
 static GfxLCMSProfilePtr RGBProfile = nullptr;
@@ -1758,11 +1717,16 @@ GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, \
GfxColorSpace *altA,  #ifdef USE_CMS
   transform = nullptr;
   lineTransform = nullptr;
+  psCSA = nullptr;
 #endif
 }
 
 GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
   delete alt;
+#ifdef USE_CMS
+  if (psCSA)
+    gfree(psCSA);
+#endif
 }
 
 GfxColorSpace *GfxICCBasedColorSpace::copy() const {
@@ -1870,6 +1834,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, \
OutputDev *out, GfxState  
   profBuf = iccStream->toUnsignedChars(&length, 65536, 65536);
   auto hp = make_GfxLCMSProfilePtr(cmsOpenProfileFromMem(profBuf,length));
+  cs->profile = hp;
   gfree(profBuf);
   if (!hp) {
     error(errSyntaxWarning, -1, "read ICCBased color space profile error");
@@ -2366,10 +2331,40 @@ void GfxICCBasedColorSpace::getDefaultRanges(double \
*decodeLow,  #ifdef USE_CMS
 char *GfxICCBasedColorSpace::getPostScriptCSA()
 {
-  if (transform)
-    return transform->getPostScriptCSA();
-  else
+#if LCMS_VERSION>=2070
+  // The runtime version check of lcms2 is only available from release 2.7 upwards.
+  // The generation of the CSA code only works reliably for version 2.10 and \
upwards. +  // Cf. the explanation in the corresponding lcms2 merge request [1], and \
the original mail thread [2]. +  // [1] https://github.com/mm2/Little-CMS/pull/214
+  // [2] https://sourceforge.net/p/lcms/mailman/message/33182987/
+  if (cmsGetEncodedCMMversion() < 2100)
     return nullptr;
+
+  int size;
+
+  if (psCSA)
+    return psCSA;
+
+  if (!profile) {
+    error(errSyntaxWarning, -1, "profile is nullptr");
+    return nullptr;
+  }
+
+  void *rawprofile = profile.get();
+  size = cmsGetPostScriptCSA(cmsGetProfileContextID(rawprofile), rawprofile, \
getIntent(), 0, nullptr, 0); +  if (size == 0) {
+    error(errSyntaxWarning, -1, "PostScript CSA is nullptr");
+    return nullptr;
+  }
+
+  psCSA = (char*)gmalloc(size+1);
+  cmsGetPostScriptCSA(cmsGetProfileContextID(rawprofile), rawprofile, getIntent(), \
0, psCSA, size); +  psCSA[size] = 0;
+
+  return psCSA;
+#else
+  return nullptr;
+#endif
 }
 #endif
 
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index 1a673b20..f79c6bc7 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -213,7 +213,6 @@ public:
   int getInputPixelType() const { return inputPixelType; }
   int getTransformPixelType() const { return transformPixelType; }
   GfxLCMSProfilePtr getSourceProfile() { return sourceProfile; }
-  char *getPostScriptCSA();
 private:
   GfxColorTransform() {}
   GfxLCMSProfilePtr sourceProfile;
@@ -221,7 +220,6 @@ private:
   int cmsIntent;
   unsigned int inputPixelType;
   unsigned int transformPixelType;
-  char *psCSA;
 };
 
 class GfxColorSpace {
@@ -582,6 +580,7 @@ public:
   Ref getRef() { return iccProfileStream; }
 #ifdef USE_CMS
   char *getPostScriptCSA();
+  GfxLCMSProfilePtr getProfile() { return profile; }
 #endif
 
 private:
@@ -592,6 +591,8 @@ private:
   double rangeMax[4];		// max values for each component
   Ref iccProfileStream;		// the ICC profile
 #ifdef USE_CMS
+  GfxLCMSProfilePtr profile;
+  char* psCSA;
   int getIntent() { return (transform != nullptr) ? transform->getIntent() : 0; }
   std::shared_ptr<GfxColorTransform> transform;
   std::shared_ptr<GfxColorTransform> lineTransform; // color transform for line
_______________________________________________
poppler mailing list
poppler@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/poppler


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic