summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--poppler/Gfx.cc4
-rw-r--r--poppler/GfxState.cc314
-rw-r--r--poppler/GfxState.h55
-rw-r--r--qt5/src/poppler-document.cc6
-rw-r--r--qt5/src/poppler-qt5.h11
-rw-r--r--utils/pdftocairo.cc9
6 files changed, 195 insertions, 204 deletions
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