From 048e40b869ac075b8b3118fe08e6aa227fb91c30 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Tue, 14 Feb 2012 14:48:58 -0500 Subject: [PATCH 1/4] Fixes #1155 --- src/core.js | 28 ++++++++++++++++++--------- src/util.js | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/src/core.js b/src/core.js index ae0f97231..9a8f516d7 100644 --- a/src/core.js +++ b/src/core.js @@ -104,23 +104,33 @@ var Page = (function PageClosure() { return shadow(this, 'mediaBox', obj); }, get view() { - var obj = this.inheritPageProp('CropBox'); + var cropBox = this.inheritPageProp('CropBox'); var view = { x: 0, y: 0, width: this.width, height: this.height }; + if (!isArray(cropBox) || cropBox.length !== 4) + return shadow(this, 'cropBox', view); + var mediaBox = this.mediaBox; var offsetX = mediaBox[0], offsetY = mediaBox[1]; - if (isArray(obj) && obj.length == 4) { - var tl = this.rotatePoint(obj[0] - offsetX, obj[1] - offsetY); - var br = this.rotatePoint(obj[2] - offsetX, obj[3] - offsetY); - view.x = Math.min(tl.x, br.x); - view.y = Math.min(tl.y, br.y); - view.width = Math.abs(tl.x - br.x); - view.height = Math.abs(tl.y - br.y); - } + + // 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) + return shadow(this, 'cropBox', view); + + var tl = this.rotatePoint(cropBox[0] - offsetX, cropBox[1] - offsetY); + var br = this.rotatePoint(cropBox[2] - offsetX, cropBox[3] - offsetY); + view.x = Math.min(tl.x, br.x); + view.y = Math.min(tl.y, br.y); + view.width = Math.abs(tl.x - br.x); + view.height = Math.abs(tl.y - br.y); return shadow(this, 'cropBox', view); }, diff --git a/src/util.js b/src/util.js index f00fcd1ce..93bd36b55 100644 --- a/src/util.js +++ b/src/util.js @@ -111,6 +111,62 @@ var Util = (function UtilClosure() { ]; } + // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) + // For coordinate systems whose origin lies in the bottom-left, this + // means normalization to (BL,TR) ordering. For systems with origin in the + // top-left, this means (TL,BR) ordering. + Util.normalizeRect = function normalizeRect(rect) { + var r = rect.slice(0); // clone rect + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + } + + // Returns a rectangle [x1, y1, x2, y2] corresponding to the + // intersection of rect1 and rect2. If no intersection, returns 'false' + // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] + Util.intersect = function intersect(rect1, rect2) { + function compare(a, b) { + return a - b; + }; + + // Order points along the axes + var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare), + orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare), + result = []; + + rect1 = Util.normalizeRect(rect1); + rect2 = Util.normalizeRect(rect2); + + // X: first and second points belong to different rectangles? + if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) || + (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) { + // Intersection must be between second and third points + result[0] = orderedX[1]; + result[2] = orderedX[2]; + } else { + return false; + } + + // Y: first and second points belong to different rectangles? + if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) || + (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) { + // Intersection must be between second and third points + result[1] = orderedY[1]; + result[3] = orderedY[2]; + } else { + return false; + } + + return result; + } + Util.sign = function sign(num) { return num < 0 ? -1 : 1; }; From f1dfe880e8651b88df7aa567acfc1fce34d3e852 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Tue, 14 Feb 2012 14:55:39 -0500 Subject: [PATCH 2/4] Adding regression test --- test/issue1155.pdf.link | 1 + test/test_manifest.json | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 test/issue1155.pdf.link diff --git a/test/issue1155.pdf.link b/test/issue1155.pdf.link new file mode 100644 index 000000000..13df4e035 --- /dev/null +++ b/test/issue1155.pdf.link @@ -0,0 +1 @@ +http://www.madbad.altervista.org/_altervista_ht/2142.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 3a1b5bd70..6ed413970 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -458,5 +458,12 @@ "rounds": 1, "link": true, "type": "eq" + }, + { "id": "issue1155", + "file": "pdfs/issue1155.pdf", + "md5": "b732ef25c16c9c20a77e40edef5aa6fe", + "rounds": 1, + "link": true, + "type": "eq" } ] From db5f43be46982e65d8c78b816dde1451da51b959 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Tue, 14 Feb 2012 15:00:43 -0500 Subject: [PATCH 3/4] oops --- test/{ => pdfs}/issue1155.pdf.link | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{ => pdfs}/issue1155.pdf.link (100%) diff --git a/test/issue1155.pdf.link b/test/pdfs/issue1155.pdf.link similarity index 100% rename from test/issue1155.pdf.link rename to test/pdfs/issue1155.pdf.link From 9cf9c3622729eb85377cf94b484d832fe6311e2b Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Thu, 16 Feb 2012 12:02:18 -0500 Subject: [PATCH 4/4] Addressing reviewer comments --- src/core.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core.js b/src/core.js index 9a8f516d7..137452257 100644 --- a/src/core.js +++ b/src/core.js @@ -112,7 +112,7 @@ var Page = (function PageClosure() { height: this.height }; if (!isArray(cropBox) || cropBox.length !== 4) - return shadow(this, 'cropBox', view); + return shadow(this, 'view', view); var mediaBox = this.mediaBox; var offsetX = mediaBox[0], offsetY = mediaBox[1]; @@ -123,7 +123,7 @@ var Page = (function PageClosure() { // effectively reduced to their intersection with the media box." cropBox = Util.intersect(cropBox, mediaBox); if (!cropBox) - return shadow(this, 'cropBox', view); + return shadow(this, 'view', view); var tl = this.rotatePoint(cropBox[0] - offsetX, cropBox[1] - offsetY); var br = this.rotatePoint(cropBox[2] - offsetX, cropBox[3] - offsetY); @@ -132,7 +132,7 @@ var Page = (function PageClosure() { view.width = Math.abs(tl.x - br.x); view.height = Math.abs(tl.y - br.y); - return shadow(this, 'cropBox', view); + return shadow(this, 'view', view); }, get annotations() { return shadow(this, 'annotations', this.inheritPageProp('Annots'));