summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Knechtges <philipp-dev@knechtges.com>2020-05-22 18:17:16 +0200
committerPhilipp Knechtges <philipp-dev@knechtges.com>2020-06-02 23:26:29 +0200
commitb2141b8921525141560b8e4ef5a351f505d7cf5b (patch)
tree58cc69fc077e3b266a1004def88ec87861834067
parent7dc4f0b56057aa4facc7ba559998d6dac5042792 (diff)
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.
-rw-r--r--poppler/Gfx.cc1
-rw-r--r--poppler/GfxState.cc157
-rw-r--r--poppler/GfxState.h9
-rw-r--r--poppler/OutputDev.h26
-rw-r--r--qt5/src/CMakeLists.txt3
-rw-r--r--qt5/src/poppler-document.cc23
-rw-r--r--qt5/src/poppler-page.cc8
-rw-r--r--qt5/src/poppler-private.h4
-rw-r--r--utils/pdftocairo.cc4
9 files changed, 70 insertions, 165 deletions
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;