diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc index f2971d6..f223676 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -460,7 +460,7 @@ void GfxResources::lookupColorSpace(const char *name, Object *obj) { obj->initNull(); } -GfxPattern *GfxResources::lookupPattern(char *name, OutputDev *out) { +GfxPattern *GfxResources::lookupPattern(char *name, OutputDev *out, GfxState *state) { GfxResources *resPtr; GfxPattern *pattern; Object obj; @@ -468,7 +468,7 @@ GfxPattern *GfxResources::lookupPattern(char *name, OutputDev *out) { for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->patternDict.isDict()) { if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) { - pattern = GfxPattern::parse(&obj, out); + pattern = GfxPattern::parse(&obj, out, state); obj.free(); return pattern; } @@ -479,7 +479,7 @@ GfxPattern *GfxResources::lookupPattern(char *name, OutputDev *out) { return NULL; } -GfxShading *GfxResources::lookupShading(char *name, OutputDev *out) { +GfxShading *GfxResources::lookupShading(char *name, OutputDev *out, GfxState *state) { GfxResources *resPtr; GfxShading *shading; Object obj; @@ -487,7 +487,7 @@ GfxShading *GfxResources::lookupShading(char *name, OutputDev *out) { for (resPtr = this; resPtr; resPtr = resPtr->next) { if (resPtr->shadingDict.isDict()) { if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) { - shading = GfxShading::parse(&obj, out); + shading = GfxShading::parse(&obj, out, state); obj.free(); return shading; } @@ -539,51 +539,20 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, GBool (*abortCheckCbkA)(void *data), void *abortCheckCbkDataA, XRef *xrefA) { - int i; - doc = docA; xref = (xrefA == NULL) ? doc->getXRef() : xrefA; catalog = doc->getCatalog(); subPage = gFalse; - printCommands = globalParams->getPrintCommands(); - profileCommands = globalParams->getProfileCommands(); - mcStack = NULL; - parser = NULL; // start the resource stack res = new GfxResources(xref, resDict, NULL); // initialize - out = outA; - state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); - stackHeight = 1; - pushStateGuard(); - fontChanged = gFalse; - clip = clipNone; - ignoreUndef = 0; + init(hDPI, vDPI, rotate, outA, outA->upsideDown(), box, cropBox, + abortCheckCbkA, abortCheckCbkDataA); out->startPage(pageNum, state, xref); out->setDefaultCTM(state->getCTM()); out->updateAll(state); - for (i = 0; i < 6; ++i) { - baseMatrix[i] = state->getCTM()[i]; - } - formDepth = 0; - ocState = gTrue; - parser = NULL; - abortCheckCbk = abortCheckCbkA; - abortCheckCbkData = abortCheckCbkDataA; - - // set crop box - if (cropBox) { - state->moveTo(cropBox->x1, cropBox->y1); - state->lineTo(cropBox->x2, cropBox->y1); - state->lineTo(cropBox->x2, cropBox->y2); - state->lineTo(cropBox->x1, cropBox->y2); - state->closePath(); - state->clip(); - out->clip(state); - state->clearPath(); - } } Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, @@ -591,23 +560,40 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, GBool (*abortCheckCbkA)(void *data), void *abortCheckCbkDataA, XRef *xrefA) { - int i; - doc = docA; xref = (xrefA == NULL) ? doc->getXRef() : xrefA; catalog = doc->getCatalog(); subPage = gTrue; - printCommands = globalParams->getPrintCommands(); - profileCommands = globalParams->getProfileCommands(); - mcStack = NULL; - parser = NULL; // start the resource stack res = new GfxResources(xref, resDict, NULL); // initialize + init(72, 72, 0, outA, gFalse, box, cropBox, + abortCheckCbkA, abortCheckCbkDataA); +} + +#ifdef USE_CMS + +#ifdef USE_LCMS1 +#include +#else +#include +#define LCMS_FLAGS cmsFLAGS_NOOPTIMIZE +#endif + +#endif + +void Gfx::init(double hDPI, double vDPI, int rotate, OutputDev *outA, + GBool upsideDown, PDFRectangle *box, PDFRectangle *cropBox, + GBool (*abortCheckCbkA)(void *data), void *abortCheckCbkDataA) { + int i; + + printCommands = globalParams->getPrintCommands(); + profileCommands = globalParams->getProfileCommands(); + mcStack = NULL; out = outA; - state = new GfxState(72, 72, box, 0, gFalse); + state = new GfxState(hDPI, vDPI, box, rotate, upsideDown); stackHeight = 1; pushStateGuard(); fontChanged = gFalse; @@ -633,6 +619,38 @@ Gfx::Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, out->clip(state); state->clearPath(); } +#ifdef USE_CMS + + Object catDict; + xref->getCatalog(&catDict); + if (catDict.isDict()) { + Object outputIntents; + catDict.dictLookup("OutputIntents", &outputIntents); + if (outputIntents.isArray() && outputIntents.arrayGetLength() == 1) { + Object firstElement; + outputIntents.arrayGet(0, &firstElement); + if (firstElement.isDict()) { + Object profile; + firstElement.dictLookup("DestOutputProfile", &profile); + if (profile.isStream()) { + Stream *iccStream = profile.getStream(); + int length = 0; + Guchar *profBuf = iccStream->toUnsignedChars(&length, 65536, 65536); + cmsHPROFILE hp = cmsOpenProfileFromMem(profBuf,length); + if (hp == 0) { + error(errSyntaxWarning, -1, "read ICCBased color space profile error"); + } else { + GfxColorSpace::setDisplayProfile(hp); + } + } + profile.free(); + } + firstElement.free(); + } + outputIntents.free(); + } + catDict.free(); +#endif } Gfx::~Gfx() { @@ -1183,7 +1201,7 @@ void Gfx::opSetExtGState(Object args[], int numArgs) { blendingColorSpace = NULL; isolated = knockout = gFalse; if (!obj4.dictLookup("CS", &obj5)->isNull()) { - blendingColorSpace = GfxColorSpace::parse(&obj5, out); + blendingColorSpace = GfxColorSpace::parse(&obj5, out, state); } obj5.free(); if (obj4.dictLookup("I", &obj5)->isBool()) { @@ -1371,6 +1389,7 @@ void Gfx::doSoftMask(Object *str, GBool alpha, } void Gfx::opSetRenderingIntent(Object args[], int numArgs) { + state->setRenderingIntent(args[0].getName()); } //------------------------------------------------------------------------ @@ -1385,7 +1404,7 @@ void Gfx::opSetFillGray(Object args[], int numArgs) { state->setFillPattern(NULL); res->lookupColorSpace("DefaultGray", &obj); if (!obj.isNull()) { - colorSpace = GfxColorSpace::parse(&obj, out); + colorSpace = GfxColorSpace::parse(&obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceGrayColorSpace(); @@ -1406,7 +1425,7 @@ void Gfx::opSetStrokeGray(Object args[], int numArgs) { state->setStrokePattern(NULL); res->lookupColorSpace("DefaultGray", &obj); if (!obj.isNull()) { - colorSpace = GfxColorSpace::parse(&obj, out); + colorSpace = GfxColorSpace::parse(&obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceGrayColorSpace(); @@ -1427,7 +1446,7 @@ void Gfx::opSetFillCMYKColor(Object args[], int numArgs) { res->lookupColorSpace("DefaultCMYK", &obj); if (!obj.isNull()) { - colorSpace = GfxColorSpace::parse(&obj, out); + colorSpace = GfxColorSpace::parse(&obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceCMYKColorSpace(); @@ -1452,7 +1471,7 @@ void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) { state->setStrokePattern(NULL); res->lookupColorSpace("DefaultCMYK", &obj); if (!obj.isNull()) { - colorSpace = GfxColorSpace::parse(&obj, out); + colorSpace = GfxColorSpace::parse(&obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceCMYKColorSpace(); @@ -1476,7 +1495,7 @@ void Gfx::opSetFillRGBColor(Object args[], int numArgs) { state->setFillPattern(NULL); res->lookupColorSpace("DefaultRGB", &obj); if (!obj.isNull()) { - colorSpace = GfxColorSpace::parse(&obj, out); + colorSpace = GfxColorSpace::parse(&obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceRGBColorSpace(); @@ -1500,7 +1519,7 @@ void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) { state->setStrokePattern(NULL); res->lookupColorSpace("DefaultRGB", &obj); if (!obj.isNull()) { - colorSpace = GfxColorSpace::parse(&obj, out); + colorSpace = GfxColorSpace::parse(&obj, out, state); } if (colorSpace == NULL) { colorSpace = new GfxDeviceRGBColorSpace(); @@ -1522,9 +1541,9 @@ void Gfx::opSetFillColorSpace(Object args[], int numArgs) { res->lookupColorSpace(args[0].getName(), &obj); if (obj.isNull()) { - colorSpace = GfxColorSpace::parse(&args[0], out); + colorSpace = GfxColorSpace::parse(&args[0], out, state); } else { - colorSpace = GfxColorSpace::parse(&obj, out); + colorSpace = GfxColorSpace::parse(&obj, out, state); } obj.free(); if (colorSpace) { @@ -1547,9 +1566,9 @@ void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { state->setStrokePattern(NULL); res->lookupColorSpace(args[0].getName(), &obj); if (obj.isNull()) { - colorSpace = GfxColorSpace::parse(&args[0], out); + colorSpace = GfxColorSpace::parse(&args[0], out, state); } else { - colorSpace = GfxColorSpace::parse(&obj, out); + colorSpace = GfxColorSpace::parse(&obj, out, state); } obj.free(); if (colorSpace) { @@ -1620,7 +1639,7 @@ void Gfx::opSetFillColorN(Object args[], int numArgs) { } if (numArgs > 0) { if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName(), out))) { + (pattern = res->lookupPattern(args[numArgs-1].getName(), out, state))) { state->setFillPattern(pattern); } } @@ -1672,7 +1691,7 @@ void Gfx::opSetStrokeColorN(Object args[], int numArgs) { return; } if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName(), out))) { + (pattern = res->lookupPattern(args[numArgs-1].getName(), out, state))) { state->setStrokePattern(pattern); } @@ -2382,7 +2401,7 @@ void Gfx::opShFill(Object args[], int numArgs) { return; } - if (!(shading = res->lookupShading(args[0].getName(), out))) { + if (!(shading = res->lookupShading(args[0].getName(), out, state))) { return; } @@ -4339,14 +4358,29 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { } } if (!obj1.isNull()) { - colorSpace = GfxColorSpace::parse(&obj1, out); + Object objIntent; + char *tempIntent = NULL; + dict->lookup("Intent", &objIntent); + if (objIntent.isName()) { + tempIntent = state->getRenderingIntent(); + if (tempIntent != NULL) { + tempIntent = strdup(tempIntent); + } + state->setRenderingIntent(objIntent.getName()); + } + colorSpace = GfxColorSpace::parse(&obj1, out, state); + if (objIntent.isName()) { + state->setRenderingIntent(tempIntent); + free(tempIntent); + } + objIntent.free(); } else if (csMode == streamCSDeviceGray) { Object objCS; res->lookupColorSpace("DefaultGray", &objCS); if (objCS.isNull()) { colorSpace = new GfxDeviceGrayColorSpace(); } else { - colorSpace = GfxColorSpace::parse(&objCS, out); + colorSpace = GfxColorSpace::parse(&objCS, out, state); } objCS.free(); } else if (csMode == streamCSDeviceRGB) { @@ -4355,7 +4389,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { if (objCS.isNull()) { colorSpace = new GfxDeviceRGBColorSpace(); } else { - colorSpace = GfxColorSpace::parse(&objCS, out); + colorSpace = GfxColorSpace::parse(&objCS, out, state); } objCS.free(); } else if (csMode == streamCSDeviceCMYK) { @@ -4364,7 +4398,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { if (objCS.isNull()) { colorSpace = new GfxDeviceCMYKColorSpace(); } else { - colorSpace = GfxColorSpace::parse(&objCS, out); + colorSpace = GfxColorSpace::parse(&objCS, out, state); } objCS.free(); } else { @@ -4459,7 +4493,7 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { obj2.free(); } } - maskColorSpace = GfxColorSpace::parse(&obj1, out); + maskColorSpace = GfxColorSpace::parse(&obj1, out, state); obj1.free(); if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { goto err1; @@ -4755,7 +4789,7 @@ void Gfx::doForm(Object *str) { if (dict->lookup("Group", &obj1)->isDict()) { if (obj1.dictLookup("S", &obj2)->isName("Transparency")) { if (!obj1.dictLookup("CS", &obj3)->isNull()) { - blendingColorSpace = GfxColorSpace::parse(&obj3, out); + blendingColorSpace = GfxColorSpace::parse(&obj3, out, state); } obj3.free(); if (obj1.dictLookup("I", &obj3)->isBool()) { diff --git a/poppler/Gfx.h b/poppler/Gfx.h index aba3b7e..a42b8b3 100644 --- a/poppler/Gfx.h +++ b/poppler/Gfx.h @@ -117,8 +117,8 @@ public: GBool lookupXObjectNF(char *name, Object *obj); GBool lookupMarkedContentNF(char *name, Object *obj); void lookupColorSpace(const char *name, Object *obj); - GfxPattern *lookupPattern(char *name, OutputDev *out); - GfxShading *lookupShading(char *name, OutputDev *out); + GfxPattern *lookupPattern(char *name, OutputDev *out, GfxState *state); + GfxShading *lookupShading(char *name, OutputDev *out, GfxState *state); GBool lookupGState(char *name, Object *obj); GBool lookupGStateNF(char *name, Object *obj); @@ -157,6 +157,10 @@ public: GBool (*abortCheckCbkA)(void *data) = NULL, void *abortCheckCbkDataA = NULL, XRef *xrefA = NULL); + void init(double hDPI, double vDPI, int rotate, OutputDev *outA, + GBool upsideDown, PDFRectangle *box, PDFRectangle *cropBox, + GBool (*abortCheckCbkA)(void *data), void *abortCheckCbkDataA); + ~Gfx(); XRef *getXRef() { return xref; } diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc index 0bafb6d..6184cd1 100644 --- a/poppler/GfxState.cc +++ b/poppler/GfxState.cc @@ -198,9 +198,10 @@ void GfxColorTransform::doTransform(void *in, void *out, unsigned int size) { } // transformA should be a cmsHTRANSFORM -GfxColorTransform::GfxColorTransform(void *transformA) { +GfxColorTransform::GfxColorTransform(void *transformA, int cmsIntentA) { transform = transformA; refCount = 1; + cmsIntent = cmsIntentA; } GfxColorTransform::~GfxColorTransform() { @@ -228,6 +229,7 @@ static cmsHPROFILE loadColorProfile(const char *fileName); void GfxColorSpace::setDisplayProfile(void *displayProfileA) { displayProfile = displayProfileA; + displayPixelType = getCMSColorSpaceType(cmsGetColorSpace(displayProfile)); } void GfxColorSpace::setDisplayProfileName(GooString *name) { @@ -256,7 +258,7 @@ GfxColorSpace::GfxColorSpace() { GfxColorSpace::~GfxColorSpace() { } -GfxColorSpace *GfxColorSpace::parse(Object *csObj, OutputDev *out, int recursion) { +GfxColorSpace *GfxColorSpace::parse(Object *csObj, OutputDev *out, GfxState *state, int recursion) { GfxColorSpace *cs; Object obj1; @@ -293,15 +295,15 @@ GfxColorSpace *GfxColorSpace::parse(Object *csObj, OutputDev *out, int recursion } else if (obj1.isName("Lab")) { cs = GfxLabColorSpace::parse(csObj->getArray()); } else if (obj1.isName("ICCBased")) { - cs = GfxICCBasedColorSpace::parse(csObj->getArray(), out, recursion); + cs = GfxICCBasedColorSpace::parse(csObj->getArray(), out, state, recursion); } else if (obj1.isName("Indexed") || obj1.isName("I")) { - cs = GfxIndexedColorSpace::parse(csObj->getArray(), out, recursion); + cs = GfxIndexedColorSpace::parse(csObj->getArray(), out, state, recursion); } else if (obj1.isName("Separation")) { - cs = GfxSeparationColorSpace::parse(csObj->getArray(), out, recursion); + cs = GfxSeparationColorSpace::parse(csObj->getArray(), out, state, recursion); } else if (obj1.isName("DeviceN")) { - cs = GfxDeviceNColorSpace::parse(csObj->getArray(), out, recursion); + cs = GfxDeviceNColorSpace::parse(csObj->getArray(), out, state, recursion); } else if (obj1.isName("Pattern")) { - cs = GfxPatternColorSpace::parse(csObj->getArray(), out, recursion); + cs = GfxPatternColorSpace::parse(csObj->getArray(), out, state, recursion); } else { error(errSyntaxWarning, -1, "Bad color space"); } @@ -426,7 +428,7 @@ int GfxColorSpace::setupColorProfiles() INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == 0) { error(errSyntaxWarning, -1, "Can't create Lab transform"); } else { - XYZ2DisplayTransform = new GfxColorTransform(transform); + XYZ2DisplayTransform = new GfxColorTransform(transform, INTENT_RELATIVE_COLORIMETRIC); } cmsCloseProfile(XYZProfile); } @@ -1626,7 +1628,7 @@ GfxColorSpace *GfxICCBasedColorSpace::copy() { return cs; } -GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, int recursion) { +GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, GfxState *state, int recursion) { GfxICCBasedColorSpace *cs; Ref iccProfileStreamA; int nCompsA; @@ -1655,7 +1657,23 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, int recu if (item != NULL) { cs = static_cast(item->cs->copy()); - return cs; + int transformIntent = cs->getIntent(); + int cmsIntent = INTENT_RELATIVE_COLORIMETRIC; + if (state != NULL) { + const char *intent = state->getRenderingIntent(); + if (intent != NULL) { + if (strcmp(intent, "AbsoluteColorimetric") == 0) { + cmsIntent = INTENT_ABSOLUTE_COLORIMETRIC; + } else if (strcmp(intent, "Saturation") == 0) { + cmsIntent = INTENT_SATURATION; + } else if (strcmp(intent, "Perceptual") == 0) { + cmsIntent = INTENT_PERCEPTUAL; + } + } + } + if (transformIntent == cmsIntent) + return cs; + delete cs; } } #endif @@ -1681,7 +1699,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, int recu nCompsA = 4; } if (dict->lookup("Alternate", &obj2)->isNull() || - !(altA = GfxColorSpace::parse(&obj2, out, recursion + 1))) { + !(altA = GfxColorSpace::parse(&obj2, out, state, recursion + 1))) { switch (nCompsA) { case 1: altA = new GfxDeviceGrayColorSpace(); @@ -1737,26 +1755,40 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, int recu unsigned int dNChannels = getCMSNChannels(cmsGetColorSpace(dhp)); unsigned int dcst = getCMSColorSpaceType(cmsGetColorSpace(dhp)); cmsHTRANSFORM transform; + + int cmsIntent = INTENT_RELATIVE_COLORIMETRIC; + if (state != NULL) { + const char *intent = state->getRenderingIntent(); + if (intent != NULL) { + if (strcmp(intent, "AbsoluteColorimetric") == 0) { + cmsIntent = INTENT_ABSOLUTE_COLORIMETRIC; + } else if (strcmp(intent, "Saturation") == 0) { + cmsIntent = INTENT_SATURATION; + } else if (strcmp(intent, "Perceptual") == 0) { + cmsIntent = INTENT_PERCEPTUAL; + } + } + } if ((transform = cmsCreateTransform(hp, COLORSPACE_SH(cst) |CHANNELS_SH(nCompsA) | BYTES_SH(1), dhp, COLORSPACE_SH(dcst) | CHANNELS_SH(dNChannels) | BYTES_SH(1), - INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == 0) { + cmsIntent, LCMS_FLAGS)) == 0) { error(errSyntaxWarning, -1, "Can't create transform"); cs->transform = NULL; } else { - cs->transform = new GfxColorTransform(transform); + cs->transform = new GfxColorTransform(transform, cmsIntent); } if (dcst == PT_RGB) { // create line transform only when the display is RGB type color space if ((transform = cmsCreateTransform(hp, CHANNELS_SH(nCompsA) | BYTES_SH(1),dhp, - TYPE_RGB_8,INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == 0) { + TYPE_RGB_8, cmsIntent, LCMS_FLAGS)) == 0) { error(errSyntaxWarning, -1, "Can't create transform"); cs->lineTransform = NULL; } else { - cs->lineTransform = new GfxColorTransform(transform); + cs->lineTransform = new GfxColorTransform(transform, cmsIntent); } } cmsCloseProfile(hp); @@ -1809,6 +1841,27 @@ void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { rgb->r = byteToCol(out[0]); rgb->g = byteToCol(out[1]); rgb->b = byteToCol(out[2]); + } else if (transform != NULL && displayPixelType == PT_CMYK) { + Guchar in[gfxColorMaxComps]; + Guchar out[gfxColorMaxComps]; + double c, m, y, k, c1, m1, y1, k1, r, g, b; + + for (int i = 0;i < nComps;i++) { + in[i] = colToByte(color->c[i]); + } + transform->doTransform(in,out,1); + c = byteToDbl(out[0]); + m = byteToDbl(out[1]); + y = byteToDbl(out[2]); + k = byteToDbl(out[3]); + c1 = 1 - c; + m1 = 1 - m; + y1 = 1 - y; + k1 = 1 - k; + cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b); + rgb->r = clip01(dblToCol(r)); + rgb->g = clip01(dblToCol(g)); + rgb->b = clip01(dblToCol(b)); } else { alt->getRGB(color, rgb); } @@ -1993,7 +2046,7 @@ GfxColorSpace *GfxIndexedColorSpace::copy() { return cs; } -GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, OutputDev *out, int recursion) { +GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, OutputDev *out, GfxState *state, int recursion) { GfxIndexedColorSpace *cs; GfxColorSpace *baseA; int indexHighA; @@ -2006,7 +2059,7 @@ GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr, OutputDev *out, int recur goto err1; } arr->get(1, &obj1); - if (!(baseA = GfxColorSpace::parse(&obj1, out, recursion + 1))) { + if (!(baseA = GfxColorSpace::parse(&obj1, out, state, recursion + 1))) { error(errSyntaxWarning, -1, "Bad Indexed color space (base color space)"); goto err2; } @@ -2228,7 +2281,7 @@ GfxColorSpace *GfxSeparationColorSpace::copy() { } //~ handle the 'All' and 'None' colorants -GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, OutputDev *out, int recursion) { +GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, OutputDev *out, GfxState *state, int recursion) { GfxSeparationColorSpace *cs; GooString *nameA; GfxColorSpace *altA; @@ -2246,7 +2299,7 @@ GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr, OutputDev *out, int re nameA = new GooString(obj1.getName()); obj1.free(); arr->get(2, &obj1); - if (!(altA = GfxColorSpace::parse(&obj1, out, recursion + 1))) { + if (!(altA = GfxColorSpace::parse(&obj1, out, state, recursion + 1))) { error(errSyntaxWarning, -1, "Bad Separation color space (alternate color space)"); goto err3; } @@ -2477,7 +2530,7 @@ GfxColorSpace *GfxDeviceNColorSpace::copy() { } //~ handle the 'None' colorant -GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, OutputDev *out, int recursion) { +GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, OutputDev *out, GfxState *state, int recursion) { GfxDeviceNColorSpace *cs; int nCompsA; GooString *namesA[gfxColorMaxComps]; @@ -2512,7 +2565,7 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, OutputDev *out, int recur } obj1.free(); arr->get(2, &obj1); - if (!(altA = GfxColorSpace::parse(&obj1, out, recursion + 1))) { + if (!(altA = GfxColorSpace::parse(&obj1, out, state, recursion + 1))) { error(errSyntaxWarning, -1, "Bad DeviceN color space (alternate color space)"); goto err3; } @@ -2535,7 +2588,7 @@ GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr, OutputDev *out, int recur Object obj3; colorants->getVal(i, &obj3); if (obj3.isArray()) { - separationList->append(GfxSeparationColorSpace::parse(obj3.getArray(), out, recursion)); + separationList->append(GfxSeparationColorSpace::parse(obj3.getArray(), out, state, recursion)); } else { obj3.free(); obj2.free(); @@ -2743,7 +2796,7 @@ GfxColorSpace *GfxPatternColorSpace::copy() { (GfxColorSpace *)NULL); } -GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, OutputDev *out, int recursion) { +GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, OutputDev *out, GfxState *state, int recursion) { GfxPatternColorSpace *cs; GfxColorSpace *underA; Object obj1; @@ -2755,7 +2808,7 @@ GfxColorSpace *GfxPatternColorSpace::parse(Array *arr, OutputDev *out, int recur underA = NULL; if (arr->getLength() == 2) { arr->get(1, &obj1); - if (!(underA = GfxColorSpace::parse(&obj1, out, recursion + 1))) { + if (!(underA = GfxColorSpace::parse(&obj1, out, state, recursion + 1))) { error(errSyntaxWarning, -1, "Bad Pattern color space (underlying color space)"); obj1.free(); return NULL; @@ -2800,7 +2853,7 @@ GfxPattern::GfxPattern(int typeA) { GfxPattern::~GfxPattern() { } -GfxPattern *GfxPattern::parse(Object *obj, OutputDev *out) { +GfxPattern *GfxPattern::parse(Object *obj, OutputDev *out, GfxState *state) { GfxPattern *pattern; Object obj1; @@ -2815,7 +2868,7 @@ GfxPattern *GfxPattern::parse(Object *obj, OutputDev *out) { if (obj1.isInt() && obj1.getInt() == 1) { pattern = GfxTilingPattern::parse(obj); } else if (obj1.isInt() && obj1.getInt() == 2) { - pattern = GfxShadingPattern::parse(obj, out); + pattern = GfxShadingPattern::parse(obj, out, state); } obj1.free(); return pattern; @@ -2943,7 +2996,7 @@ GfxPattern *GfxTilingPattern::copy() { // GfxShadingPattern //------------------------------------------------------------------------ -GfxShadingPattern *GfxShadingPattern::parse(Object *patObj, OutputDev *out) { +GfxShadingPattern *GfxShadingPattern::parse(Object *patObj, OutputDev *out, GfxState *state) { Dict *dict; GfxShading *shadingA; double matrixA[6]; @@ -2956,7 +3009,7 @@ GfxShadingPattern *GfxShadingPattern::parse(Object *patObj, OutputDev *out) { dict = patObj->getDict(); dict->lookup("Shading", &obj1); - shadingA = GfxShading::parse(&obj1, out); + shadingA = GfxShading::parse(&obj1, out, state); obj1.free(); if (!shadingA) { return NULL; @@ -3029,7 +3082,7 @@ GfxShading::~GfxShading() { } } -GfxShading *GfxShading::parse(Object *obj, OutputDev *out) { +GfxShading *GfxShading::parse(Object *obj, OutputDev *out, GfxState *state) { GfxShading *shading; Dict *dict; int typeA; @@ -3053,17 +3106,17 @@ GfxShading *GfxShading::parse(Object *obj, OutputDev *out) { switch (typeA) { case 1: - shading = GfxFunctionShading::parse(dict, out); + shading = GfxFunctionShading::parse(dict, out, state); break; case 2: - shading = GfxAxialShading::parse(dict, out); + shading = GfxAxialShading::parse(dict, out, state); break; case 3: - shading = GfxRadialShading::parse(dict, out); + shading = GfxRadialShading::parse(dict, out, state); break; case 4: if (obj->isStream()) { - shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream(), out); + shading = GfxGouraudTriangleShading::parse(4, dict, obj->getStream(), out, state); } else { error(errSyntaxWarning, -1, "Invalid Type 4 shading object"); goto err1; @@ -3071,7 +3124,7 @@ GfxShading *GfxShading::parse(Object *obj, OutputDev *out) { break; case 5: if (obj->isStream()) { - shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream(), out); + shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream(), out, state); } else { error(errSyntaxWarning, -1, "Invalid Type 5 shading object"); goto err1; @@ -3079,7 +3132,7 @@ GfxShading *GfxShading::parse(Object *obj, OutputDev *out) { break; case 6: if (obj->isStream()) { - shading = GfxPatchMeshShading::parse(6, dict, obj->getStream(), out); + shading = GfxPatchMeshShading::parse(6, dict, obj->getStream(), out, state); } else { error(errSyntaxWarning, -1, "Invalid Type 6 shading object"); goto err1; @@ -3087,7 +3140,7 @@ GfxShading *GfxShading::parse(Object *obj, OutputDev *out) { break; case 7: if (obj->isStream()) { - shading = GfxPatchMeshShading::parse(7, dict, obj->getStream(), out); + shading = GfxPatchMeshShading::parse(7, dict, obj->getStream(), out, state); } else { error(errSyntaxWarning, -1, "Invalid Type 7 shading object"); goto err1; @@ -3104,12 +3157,12 @@ GfxShading *GfxShading::parse(Object *obj, OutputDev *out) { return NULL; } -GBool GfxShading::init(Dict *dict, OutputDev *out) { +GBool GfxShading::init(Dict *dict, OutputDev *out, GfxState *state) { Object obj1, obj2; int i; dict->lookup("ColorSpace", &obj1); - if (!(colorSpace = GfxColorSpace::parse(&obj1, out))) { + if (!(colorSpace = GfxColorSpace::parse(&obj1, out, state))) { error(errSyntaxWarning, -1, "Bad color space in shading dictionary"); obj1.free(); return gFalse; @@ -3216,7 +3269,7 @@ GfxFunctionShading::~GfxFunctionShading() { } } -GfxFunctionShading *GfxFunctionShading::parse(Dict *dict, OutputDev *out) { +GfxFunctionShading *GfxFunctionShading::parse(Dict *dict, OutputDev *out, GfxState *state) { GfxFunctionShading *shading; double x0A, y0A, x1A, y1A; double matrixA[6]; @@ -3284,7 +3337,7 @@ GfxFunctionShading *GfxFunctionShading::parse(Dict *dict, OutputDev *out) { shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA, funcsA, nFuncsA); - if (!shading->init(dict, out)) { + if (!shading->init(dict, out, state)) { delete shading; return NULL; } @@ -3535,7 +3588,7 @@ GfxAxialShading::GfxAxialShading(GfxAxialShading *shading): GfxAxialShading::~GfxAxialShading() { } -GfxAxialShading *GfxAxialShading::parse(Dict *dict, OutputDev *out) { +GfxAxialShading *GfxAxialShading::parse(Dict *dict, OutputDev *out, GfxState *state) { GfxAxialShading *shading; double x0A, y0A, x1A, y1A; double t0A, t1A; @@ -3632,7 +3685,7 @@ GfxAxialShading *GfxAxialShading::parse(Dict *dict, OutputDev *out) { shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A, funcsA, nFuncsA, extend0A, extend1A); - if (!shading->init(dict, out)) { + if (!shading->init(dict, out, state)) { delete shading; return NULL; } @@ -3743,7 +3796,7 @@ GfxRadialShading::GfxRadialShading(GfxRadialShading *shading): GfxRadialShading::~GfxRadialShading() { } -GfxRadialShading *GfxRadialShading::parse(Dict *dict, OutputDev *out) { +GfxRadialShading *GfxRadialShading::parse(Dict *dict, OutputDev *out, GfxState *state) { GfxRadialShading *shading; double x0A, y0A, r0A, x1A, y1A, r1A; double t0A, t1A; @@ -3822,7 +3875,7 @@ GfxRadialShading *GfxRadialShading::parse(Dict *dict, OutputDev *out) { shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A, funcsA, nFuncsA, extend0A, extend1A); - if (!shading->init(dict, out)) { + if (!shading->init(dict, out, state)) { delete shading; return NULL; } @@ -4266,7 +4319,7 @@ GfxGouraudTriangleShading::~GfxGouraudTriangleShading() { GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, Dict *dict, Stream *str, - OutputDev *out) { + OutputDev *out, GfxState *gfxState) { GfxGouraudTriangleShading *shading; Function *funcsA[gfxColorMaxComps]; int nFuncsA; @@ -4462,7 +4515,7 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA, shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA, trianglesA, nTrianglesA, funcsA, nFuncsA); - if (!shading->init(dict, out)) { + if (!shading->init(dict, out, gfxState)) { delete shading; return NULL; } @@ -4609,7 +4662,7 @@ GfxPatchMeshShading::~GfxPatchMeshShading() { } GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, - Stream *str, OutputDev *out) { + Stream *str, OutputDev *out, GfxState *state) { GfxPatchMeshShading *shading; Function *funcsA[gfxColorMaxComps]; int nFuncsA; @@ -5133,7 +5186,7 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict, shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA, funcsA, nFuncsA); - if (!shading->init(dict, out)) { + if (!shading->init(dict, out, state)) { delete shading; return NULL; } @@ -5981,6 +6034,8 @@ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox, clipXMax = pageWidth; clipYMax = pageHeight; + renderingIntent = NULL; + saved = NULL; #ifdef USE_CMS GfxColorSpace::setupColorProfiles(); diff --git a/poppler/GfxState.h b/poppler/GfxState.h index 2f3efcf..0da4587 100644 --- a/poppler/GfxState.h +++ b/poppler/GfxState.h @@ -51,6 +51,7 @@ class GfxShading; class PopplerCache; class GooList; class OutputDev; +class GfxState; class Matrix { public: @@ -180,14 +181,16 @@ class GfxColorTransform { public: void doTransform(void *in, void *out, unsigned int size); // transformA should be a cmsHTRANSFORM - GfxColorTransform(void *transformA); + GfxColorTransform(void *transformA, int cmsIntent); ~GfxColorTransform(); + int getIntent() { return cmsIntent; } void ref(); unsigned int unref(); private: GfxColorTransform() {} void *transform; unsigned int refCount; + int cmsIntent; }; class GfxColorSpace { @@ -199,7 +202,7 @@ public: virtual GfxColorSpaceMode getMode() = 0; // Construct a color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Object *csObj, OutputDev *out, int recursion = 0); + static GfxColorSpace *parse(Object *csObj, OutputDev *out, GfxState *state, int recursion = 0); // Convert to gray, RGB, or CMYK. virtual void getGray(GfxColor *color, GfxGray *gray) = 0; @@ -493,7 +496,7 @@ public: virtual GfxColorSpaceMode getMode() { return csICCBased; } // Construct an ICCBased color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion); + static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState *state, int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -522,6 +525,7 @@ private: double rangeMax[4]; // max values for each component Ref iccProfileStream; // the ICC profile #ifdef USE_CMS + int getIntent() { return transform->getIntent(); } GfxColorTransform *transform; GfxColorTransform *lineTransform; // color transform for line #endif @@ -539,7 +543,7 @@ public: virtual GfxColorSpaceMode getMode() { return csIndexed; } // Construct an Indexed color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion); + static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState *state, int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -588,7 +592,7 @@ public: virtual GfxColorSpaceMode getMode() { return csSeparation; } // Construct a Separation color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion); + static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState *state, int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -633,7 +637,7 @@ public: virtual GfxColorSpaceMode getMode() { return csDeviceN; } // Construct a DeviceN color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion); + static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState *state, int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -680,7 +684,7 @@ public: virtual GfxColorSpaceMode getMode() { return csPattern; } // Construct a Pattern color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr, OutputDev *out, int recursion); + static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState *state, int recursion); virtual void getGray(GfxColor *color, GfxGray *gray); virtual void getRGB(GfxColor *color, GfxRGB *rgb); @@ -709,7 +713,7 @@ public: GfxPattern(int typeA); virtual ~GfxPattern(); - static GfxPattern *parse(Object *obj, OutputDev *out); + static GfxPattern *parse(Object *obj, OutputDev *out, GfxState *state); virtual GfxPattern *copy() = 0; @@ -765,7 +769,7 @@ private: class GfxShadingPattern: public GfxPattern { public: - static GfxShadingPattern *parse(Object *patObj, OutputDev *out); + static GfxShadingPattern *parse(Object *patObj, OutputDev *out, GfxState *state); virtual ~GfxShadingPattern(); virtual GfxPattern *copy(); @@ -792,7 +796,7 @@ public: GfxShading(GfxShading *shading); virtual ~GfxShading(); - static GfxShading *parse(Object *obj, OutputDev *out); + static GfxShading *parse(Object *obj, OutputDev *out, GfxState *state); virtual GfxShading *copy() = 0; @@ -806,7 +810,7 @@ public: protected: - GBool init(Dict *dict, OutputDev *out); + GBool init(Dict *dict, OutputDev *out, GfxState *state); int type; GfxColorSpace *colorSpace; @@ -875,7 +879,7 @@ public: GfxFunctionShading(GfxFunctionShading *shading); virtual ~GfxFunctionShading(); - static GfxFunctionShading *parse(Dict *dict, OutputDev *out); + static GfxFunctionShading *parse(Dict *dict, OutputDev *out, GfxState *state); virtual GfxShading *copy(); @@ -909,7 +913,7 @@ public: GfxAxialShading(GfxAxialShading *shading); virtual ~GfxAxialShading(); - static GfxAxialShading *parse(Dict *dict, OutputDev *out); + static GfxAxialShading *parse(Dict *dict, OutputDev *out, GfxState *state); virtual GfxShading *copy(); @@ -942,7 +946,7 @@ public: GfxRadialShading(GfxRadialShading *shading); virtual ~GfxRadialShading(); - static GfxRadialShading *parse(Dict *dict, OutputDev *out); + static GfxRadialShading *parse(Dict *dict, OutputDev *out, GfxState *state); virtual GfxShading *copy(); @@ -980,7 +984,7 @@ public: GfxGouraudTriangleShading(GfxGouraudTriangleShading *shading); virtual ~GfxGouraudTriangleShading(); - static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str, OutputDev *out); + static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str, OutputDev *out, GfxState *state); virtual GfxShading *copy(); @@ -1066,7 +1070,7 @@ public: GfxPatchMeshShading(GfxPatchMeshShading *shading); virtual ~GfxPatchMeshShading(); - static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str, OutputDev *out); + static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str, OutputDev *out, GfxState *state); virtual GfxShading *copy(); @@ -1407,6 +1411,7 @@ public: double getLeading() { return leading; } double getRise() { return rise; } int getRender() { return render; } + char *getRenderingIntent() { return renderingIntent; } GfxPath *getPath() { return path; } void setPath(GfxPath *pathA); double getCurX() { return curX; } @@ -1485,6 +1490,15 @@ public: { rise = riseA; } void setRender(int renderA) { render = renderA; } + void setRenderingIntent(const char *intent) + { + free(renderingIntent); + if (intent != NULL) { + renderingIntent = strdup(intent); + } else { + renderingIntent = NULL; + } + } // Add to path. void moveTo(double x, double y) @@ -1573,6 +1587,7 @@ private: double clipXMin, clipYMin, // bounding box for clip region clipXMax, clipYMax; + char *renderingIntent; GfxState *saved; // next GfxState on stack diff --git a/poppler/Page.cc b/poppler/Page.cc index e0a3b29..9db78be 100644 --- a/poppler/Page.cc +++ b/poppler/Page.cc @@ -671,7 +671,7 @@ GBool Page::loadThumb(unsigned char **data_out, obj1.free (); dict->lookup ("CS", &obj1); } - colorSpace = GfxColorSpace::parse(&obj1, NULL); + colorSpace = GfxColorSpace::parse(&obj1, NULL, NULL); obj1.free(); if (!colorSpace) { fprintf (stderr, "Error: Cannot parse color space\n");