From 5c7ecbfa28d0dad59441d3774c175ab142a3b04b Mon Sep 17 00:00:00 2001
From: notmasteryet <async.processingjs@yahoo.com>
Date: Wed, 17 Aug 2011 20:21:54 -0500
Subject: [PATCH 1/3] Basic annotation link support

---
 pdf.js        | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
 web/viewer.js | 34 +++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/pdf.js b/pdf.js
index 79ae776f6..46eb202ff 100644
--- a/pdf.js
+++ b/pdf.js
@@ -3154,6 +3154,9 @@ var Page = (function() {
       return shadow(this, 'mediaBox',
                     ((IsArray(obj) && obj.length == 4) ? obj : null));
     },
+    get annotations() {
+      return shadow(this, 'annotations', this.inheritPageProp('Annots'));
+    },
     get width() {
       var mediaBox = this.mediaBox;
       var rotate = this.rotate;
@@ -3266,6 +3269,56 @@ var Page = (function() {
             rotate: this.rotate });
       gfx.execute(this.code, xref, resources);
       gfx.endDrawing();
+    },
+    rotatePoint: function (x, y) {
+      var rotate = this.rotate;
+      switch (rotate) {
+        default:
+        case 0:
+          return {x: x, y: this.height - y};
+        case 180:
+          return {x: this.width - x, y: y};
+        case 90:
+          return {x: this.width - y, y: this.height - x};
+        case 270:
+          return {x: y, y: x};
+      }
+    },
+    getLinks: function(scale) {
+      var xref = this.xref;
+      var annotations = xref.fetchIfRef(this.annotations);
+      var i, n = annotations.length;
+      var links = [];
+      for (i = 0; i < n; ++i) {
+        var annotation = xref.fetch(annotations[i]);
+        if (!IsDict(annotation, 'Annot'))
+          continue;
+        var subtype = annotation.get("Subtype");
+        if (!IsName(subtype) || subtype.name != 'Link')
+          continue;
+        var rect = annotation.get("Rect");
+        var topLeftCorner = this.rotatePoint(rect[0], rect[1]);
+        var bottomRightCorner = this.rotatePoint(rect[2], rect[3]);
+
+        var link = {};
+        link.x = scale * Math.min(topLeftCorner.x, bottomRightCorner.x);
+        link.y = scale * Math.min(topLeftCorner.y, bottomRightCorner.y);
+        link.width = scale * Math.abs(topLeftCorner.x - bottomRightCorner.x);
+        link.height = scale * Math.abs(topLeftCorner.y - bottomRightCorner.y);
+        var a = annotation.get("A");
+        if (a) {
+          switch(a.get("S").name) {
+            case "URI":
+              link.url = a.get("URI");
+              break;
+            default:
+              TODO("other link types");
+              break;
+          }
+        }
+        links.push(link);
+      }
+      return links;
     }
   };
 
diff --git a/web/viewer.js b/web/viewer.js
index 0307e7ea3..e4db38bc8 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -165,6 +165,38 @@ var PageView = function(container, content, id, width, height, stats) {
       div.removeChild(div.lastChild);
   };
 
+  function setupLinks(canvas, content, scale) {
+    var links = content.getLinks(scale);
+    var currentLink = null;
+    if (links.length > 0)
+    {
+      canvas.addEventListener('mousemove', function(e) {
+        var x = e.pageX;
+        var y = e.pageY;
+        for (var p = canvas; p; p = p.offsetParent) {
+          x -= p.offsetLeft;
+          y -= p.offsetTop;
+        }
+        for (var i = 0; i < links.length; i++) {
+          var link = links[i];
+          if (!link.url)
+            continue;
+          if (link.x <= x && link.y <= y &&
+            x < link.x + link.width && y < link.y + link.height) {
+            currentLink = link;
+            canvas.style.cursor = 'pointer';
+            return;
+          }
+        }
+        currentLink = null;
+        canvas.style.cursor = 'default';
+      }, false);
+      canvas.addEventListener('mousedown', function(e) {
+        window.location.href = currentLink.url;
+      }, false);
+    }
+  }
+
   this.draw = function() {
     if (div.hasChildNodes()) {
       this.updateStats();
@@ -188,6 +220,8 @@ var PageView = function(container, content, id, width, height, stats) {
     stats.begin = Date.now();
     this.content.startRendering(ctx, this.updateStats);
 
+    setupLinks(canvas, this.content, this.scale);
+
     return true;
   };
 

From c2eaa55cd97ee64451dea80472c4d16b1aa1a390 Mon Sep 17 00:00:00 2001
From: notmasteryet <async.processingjs@yahoo.com>
Date: Thu, 18 Aug 2011 22:48:07 -0500
Subject: [PATCH 2/3] Move scale out of pdf.js

---
 pdf.js        | 10 +++++-----
 web/viewer.js |  4 +++-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/pdf.js b/pdf.js
index 79a9bba77..63aefcd32 100644
--- a/pdf.js
+++ b/pdf.js
@@ -3340,7 +3340,7 @@ var Page = (function() {
           return {x: y, y: x};
       }
     },
-    getLinks: function(scale) {
+    getLinks: function() {
       var xref = this.xref;
       var annotations = xref.fetchIfRef(this.annotations);
       var i, n = annotations.length;
@@ -3357,10 +3357,10 @@ var Page = (function() {
         var bottomRightCorner = this.rotatePoint(rect[2], rect[3]);
 
         var link = {};
-        link.x = scale * Math.min(topLeftCorner.x, bottomRightCorner.x);
-        link.y = scale * Math.min(topLeftCorner.y, bottomRightCorner.y);
-        link.width = scale * Math.abs(topLeftCorner.x - bottomRightCorner.x);
-        link.height = scale * Math.abs(topLeftCorner.y - bottomRightCorner.y);
+        link.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
+        link.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
+        link.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
+        link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
         var a = annotation.get("A");
         if (a) {
           switch(a.get("S").name) {
diff --git a/web/viewer.js b/web/viewer.js
index e4db38bc8..b1e28407f 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -166,7 +166,7 @@ var PageView = function(container, content, id, width, height, stats) {
   };
 
   function setupLinks(canvas, content, scale) {
-    var links = content.getLinks(scale);
+    var links = content.getLinks();
     var currentLink = null;
     if (links.length > 0)
     {
@@ -177,6 +177,8 @@ var PageView = function(container, content, id, width, height, stats) {
           x -= p.offsetLeft;
           y -= p.offsetTop;
         }
+        x /= scale;
+        y /= scale;
         for (var i = 0; i < links.length; i++) {
           var link = links[i];
           if (!link.url)

From 1e8090c19d1f885cf7ff93ce5c6bad71f08972ff Mon Sep 17 00:00:00 2001
From: notmasteryet <async.processingjs@yahoo.com>
Date: Thu, 18 Aug 2011 23:12:10 -0500
Subject: [PATCH 3/3] brace fix

---
 web/viewer.js | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/web/viewer.js b/web/viewer.js
index b1e28407f..e501a10b2 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -168,8 +168,7 @@ var PageView = function(container, content, id, width, height, stats) {
   function setupLinks(canvas, content, scale) {
     var links = content.getLinks();
     var currentLink = null;
-    if (links.length > 0)
-    {
+    if (links.length > 0) {
       canvas.addEventListener('mousemove', function(e) {
         var x = e.pageX;
         var y = e.pageY;