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-...@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 _______________________________________________ poppler mailing list poppler@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/poppler