From 9be3aee9c93d55920a9bf27733472b1d8d366757 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 6 Dec 2016 10:21:42 +0100 Subject: [PATCH 1/2] Add a parameter to `Page_getInheritedPageProp` to make it possible to fetch (and dereference) Arrays, and use that for the `MediaBox`/`CropBox` getters (issue 7872) --- src/core/document.js | 9 ++--- test/pdfs/.gitignore | 1 + test/pdfs/issue7872.pdf | 80 +++++++++++++++++++++++++++++++++++++++++ test/test_manifest.json | 8 +++++ 4 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 test/pdfs/issue7872.pdf diff --git a/src/core/document.js b/src/core/document.js index 53e625637..b535cb9fe 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -91,13 +91,14 @@ var Page = (function PageClosure() { return this.pageDict.get(key); }, - getInheritedPageProp: function Page_getInheritedPageProp(key) { + getInheritedPageProp: function Page_getInheritedPageProp(key, getArray) { var dict = this.pageDict, valueArray = null, loopCount = 0; var MAX_LOOP_COUNT = 100; + getArray = getArray || false; // Always walk up the entire parent chain, to be able to find // e.g. \Resources placed on multiple levels of the tree. while (dict) { - var value = dict.get(key); + var value = getArray ? dict.getArray(key) : dict.get(key); if (value) { if (!valueArray) { valueArray = []; @@ -132,7 +133,7 @@ var Page = (function PageClosure() { }, get mediaBox() { - var obj = this.getInheritedPageProp('MediaBox'); + var obj = this.getInheritedPageProp('MediaBox', true); // Reset invalid media box to letter size. if (!isArray(obj) || obj.length !== 4) { obj = LETTER_SIZE_MEDIABOX; @@ -150,7 +151,7 @@ var Page = (function PageClosure() { get view() { var mediaBox = this.mediaBox; - var cropBox = this.getInheritedPageProp('CropBox'); + var cropBox = this.getInheritedPageProp('CropBox', true); if (!isArray(cropBox) || cropBox.length !== 4) { return shadow(this, 'view', mediaBox); } diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index aa088e3d4..90f561d3a 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -43,6 +43,7 @@ !issue7665.pdf !issue7835.pdf !issue7855.pdf +!issue7872.pdf !bad-PageLabels.pdf !filled-background.pdf !ArabicCIDTrueType.pdf diff --git a/test/pdfs/issue7872.pdf b/test/pdfs/issue7872.pdf new file mode 100644 index 000000000..01f295e7e --- /dev/null +++ b/test/pdfs/issue7872.pdf @@ -0,0 +1,80 @@ +%PDF-1.7 +%âãÏÓ +1 0 obj +<< +/Pages 2 0 R +/Type /Catalog +>> +endobj +2 0 obj +<< +/Kids [3 0 R] +/Count 1 +/Type /Pages +>> +endobj +3 0 obj +<< +/CropBox [4 0 R 5 0 R 6 0 R 7 0 R] +/Parent 2 0 R +/MediaBox [4 0 R 5 0 R 6 0 R 7 0 R] +/Resources +<< +/Font +<< +/F1 8 0 R +>> +>> +/Contents 9 0 R +/Type /Page +>> +endobj +8 0 obj +<< +/BaseFont /Times-Roman +/Subtype /Type1 +/Encoding /WinAnsiEncoding +/Type /Font +>> +endobj +9 0 obj +<< +/Length 74 +>> +stream +BT +10 20 TD +/F1 12 Tf +(MediaBox and CropBox with indirect objects.) Tj +ET + +endstream +endobj +4 0 obj 0 +endobj +5 0 obj 0 +endobj +6 0 obj 250 +endobj +7 0 obj 50 +endobj xref +0 10 +0000000000 65535 f +0000000015 00000 n +0000000066 00000 n +0000000125 00000 n +0000000530 00000 n +0000000548 00000 n +0000000566 00000 n +0000000586 00000 n +0000000302 00000 n +0000000403 00000 n +trailer + +<< +/Root 1 0 R +/Size 10 +>> +startxref +604 +%%EOF diff --git a/test/test_manifest.json b/test/test_manifest.json index 5d669044e..5f7fd9b97 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -1343,6 +1343,14 @@ "link": true, "type": "eq" }, + { "id": "issue7872", + "file": "pdfs/issue7872.pdf", + "md5": "81781dfecfcb7e9cd9cc7e60f8b747b7", + "rounds": 1, + "link": false, + "type": "eq", + "about": "MediaBox and CropBox with indirect objects." + }, { "id": "issue2642", "file": "pdfs/issue2642.pdf", "md5": "b6679861fdce3bbab0c1fa51bb7f5077", From 3800b5e4639b3c6154ee5321891a820b7ddad8fa Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Tue, 6 Dec 2016 01:00:12 +0100 Subject: [PATCH 2/2] Document: extract `CropBox` fetching and validation into a getter This patch refactors the `CropBox` code to combine fetching and validation code in a getter, like we already did for the `MediaBox` property. Combined with variable name changes, this improves readability of the code and makes the `view` getter simpler as well. --- src/core/document.js | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/core/document.js b/src/core/document.js index b535cb9fe..ed0a8eff0 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -133,12 +133,21 @@ var Page = (function PageClosure() { }, get mediaBox() { - var obj = this.getInheritedPageProp('MediaBox', true); + var mediaBox = this.getInheritedPageProp('MediaBox', true); // Reset invalid media box to letter size. - if (!isArray(obj) || obj.length !== 4) { - obj = LETTER_SIZE_MEDIABOX; + if (!isArray(mediaBox) || mediaBox.length !== 4) { + return shadow(this, 'mediaBox', LETTER_SIZE_MEDIABOX); } - return shadow(this, 'mediaBox', obj); + return shadow(this, 'mediaBox', mediaBox); + }, + + get cropBox() { + var cropBox = this.getInheritedPageProp('CropBox', true); + // Reset invalid crop box to media box. + if (!isArray(cropBox) || cropBox.length !== 4) { + return shadow(this, 'cropBox', this.mediaBox); + } + return shadow(this, 'cropBox', cropBox); }, get userUnit() { @@ -150,21 +159,16 @@ var Page = (function PageClosure() { }, get view() { - var mediaBox = this.mediaBox; - var cropBox = this.getInheritedPageProp('CropBox', true); - if (!isArray(cropBox) || cropBox.length !== 4) { - return shadow(this, 'view', mediaBox); - } - // From the spec, 6th ed., p.963: // "The crop, bleed, trim, and art boxes should not ordinarily // extend beyond the boundaries of the media box. If they do, they are // effectively reduced to their intersection with the media box." - cropBox = Util.intersect(cropBox, mediaBox); - if (!cropBox) { + var mediaBox = this.mediaBox, cropBox = this.cropBox; + if (mediaBox === cropBox) { return shadow(this, 'view', mediaBox); } - return shadow(this, 'view', cropBox); + var intersection = Util.intersect(cropBox, mediaBox); + return shadow(this, 'view', intersection || mediaBox); }, get rotate() {