From d0c8992e8aec2e4807a0e6db427432cda3d0c13d Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Wed, 20 Dec 2017 15:35:04 +0100 Subject: [PATCH] Attempt to actually resolve ColourSpace names in accordance with the specification (issue 9285) Please refer to the PDF specification, in particular http://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G7.3801570 > A colour space shall be specified in one of two ways: > - Within a content stream, the CS or cs operator establishes the current colour space parameter in the graphics state. The operand shall always be name object, which either identifies one of the colour spaces that need no additional parameters (DeviceGray, DeviceRGB, DeviceCMYK, or some cases of Pattern) or shall be used as a key in the ColorSpace subdictionary of the current resource dictionary (see 7.8.3, "Resource Dictionaries"). In the latter case, the value of the dictionary entry in turn shall be a colour space array or name. A colour space array shall never be inline within a content stream. > > - Outside a content stream, certain objects, such as image XObjects, shall specify a colour space as an explicit parameter, often associated with the key ColorSpace. In this case, the colour space array or name shall always be defined directly as a PDF object, not by an entry in the ColorSpace resource subdictionary. This convention also applies when colour spaces are defined in terms of other colour spaces. --- src/core/colorspace.js | 26 +++++++++++++++----------- src/core/evaluator.js | 2 ++ src/core/image.js | 12 ++++++++---- test/pdfs/issue9285.pdf.link | 1 + test/test_manifest.json | 8 ++++++++ 5 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 test/pdfs/issue9285.pdf.link diff --git a/src/core/colorspace.js b/src/core/colorspace.js index f92aaba5d..0ba480b02 100644 --- a/src/core/colorspace.js +++ b/src/core/colorspace.js @@ -258,17 +258,7 @@ var ColorSpace = (function ColorSpaceClosure() { } }; - ColorSpace.parseToIR = function(cs, xref, res, pdfFunctionFactory) { - if (isName(cs)) { - var colorSpaces = res.get('ColorSpace'); - if (isDict(colorSpaces)) { - var refcs = colorSpaces.get(cs.name); - if (refcs) { - cs = refcs; - } - } - } - + ColorSpace.parseToIR = function(cs, xref, res = null, pdfFunctionFactory) { cs = xref.fetchIfRef(cs); if (isName(cs)) { switch (cs.name) { @@ -284,6 +274,20 @@ var ColorSpace = (function ColorSpaceClosure() { case 'Pattern': return ['PatternCS', null]; default: + if (isDict(res)) { + let colorSpaces = res.get('ColorSpace'); + if (isDict(colorSpaces)) { + let resCS = colorSpaces.get(cs.name); + if (resCS) { + if (isName(resCS)) { + return ColorSpace.parseToIR(resCS, xref, res, + pdfFunctionFactory); + } + cs = resCS; + break; + } + } + } throw new FormatError(`unrecognized colorspace ${cs.name}`); } } diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 876f40ea1..acb7aa0df 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -412,6 +412,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { xref: this.xref, res: resources, image, + isInline: inline, pdfFunctionFactory: this.pdfFunctionFactory, }); // We force the use of RGBA_32BPP images here, because we can't handle @@ -464,6 +465,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { xref: this.xref, res: resources, image, + isInline: inline, nativeDecoder: nativeImageDecoder, pdfFunctionFactory: this.pdfFunctionFactory, }).then((imageObj) => { diff --git a/src/core/image.js b/src/core/image.js index 7121d83ce..9fa090365 100644 --- a/src/core/image.js +++ b/src/core/image.js @@ -75,8 +75,8 @@ var PDFImage = (function PDFImageClosure() { return dest; } - function PDFImage({ xref, res, image, smask = null, mask = null, - isMask = false, pdfFunctionFactory, }) { + function PDFImage({ xref, res, image, isInline = false, smask = null, + mask = null, isMask = false, pdfFunctionFactory, }) { this.image = image; var dict = image.dict; if (dict.has('Filter')) { @@ -139,7 +139,8 @@ var PDFImage = (function PDFImageClosure() { 'color components not supported.'); } } - this.colorSpace = ColorSpace.parse(colorSpace, xref, res, + let resources = isInline ? res : null; + this.colorSpace = ColorSpace.parse(colorSpace, xref, resources, pdfFunctionFactory); this.numComps = this.colorSpace.numComps; } @@ -167,6 +168,7 @@ var PDFImage = (function PDFImageClosure() { xref, res, image: smask, + isInline, pdfFunctionFactory, }); } else if (mask) { @@ -179,6 +181,7 @@ var PDFImage = (function PDFImageClosure() { xref, res, image: mask, + isInline, isMask: true, pdfFunctionFactory, }); @@ -193,7 +196,7 @@ var PDFImage = (function PDFImageClosure() { * Handles processing of image data and returns the Promise that is resolved * with a PDFImage when the image is ready to be used. */ - PDFImage.buildImage = function({ handler, xref, res, image, + PDFImage.buildImage = function({ handler, xref, res, image, isInline = false, nativeDecoder = null, pdfFunctionFactory, }) { var imagePromise = handleImageData(image, nativeDecoder); @@ -227,6 +230,7 @@ var PDFImage = (function PDFImageClosure() { xref, res, image: imageData, + isInline, smask: smaskData, mask: maskData, pdfFunctionFactory, diff --git a/test/pdfs/issue9285.pdf.link b/test/pdfs/issue9285.pdf.link new file mode 100644 index 000000000..6452b5c94 --- /dev/null +++ b/test/pdfs/issue9285.pdf.link @@ -0,0 +1 @@ +https://github.com/mozilla/pdf.js/files/1563256/4149180-355989.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 11f260ba2..f32fb1b6f 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -741,6 +741,14 @@ "link": false, "type": "eq" }, + { "id": "issue9285", + "file": "pdfs/issue9285.pdf", + "md5": "aa53ad98a72fd76c414101927951448b", + "rounds": 1, + "link": true, + "lastPage": 1, + "type": "eq" + }, { "id": "issue8707", "file": "pdfs/issue8707.pdf", "md5": "d3dc670adde9ec9fb82c974027033029",