diff --git a/src/canvas.js b/src/canvas.js
index 99968d014..c8c46a400 100644
--- a/src/canvas.js
+++ b/src/canvas.js
@@ -968,14 +968,20 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
       var ctx = this.ctx;
       var font = this.current.font;
       var ctxMatrix = ctx.mozCurrentTransform;
-      if (ctxMatrix) {
-        var bl = Util.applyTransform([0, 0], ctxMatrix);
-        var tr = Util.applyTransform([1, 1], ctxMatrix);
-        geometry.x = bl[0];
-        geometry.y = bl[1];
-        geometry.hScale = tr[0] - bl[0];
-        geometry.vScale = tr[1] - bl[1];
-      }
+      var a = ctxMatrix[0], b = ctxMatrix[1], c = ctxMatrix[2];
+      var d = ctxMatrix[3], e = ctxMatrix[4], f = ctxMatrix[5];
+      var sx = (a >= 0) ?
+          Math.sqrt((a * a) + (b * b)) : -Math.sqrt((a * a) + (b * b));
+      var sy = (d >= 0) ?
+          Math.sqrt((c * c) + (d * d)) : -Math.sqrt((c * c) + (d * d));
+      var angle = Math.atan2(b, a);
+      var x = e;
+      var y = f;
+      geometry.x = x;
+      geometry.y = y;
+      geometry.hScale = sx;
+      geometry.vScale = sy;
+      geometry.angle = angle;
       geometry.spaceWidth = font.spaceWidth;
       geometry.fontName = font.loadedName;
       geometry.fontFamily = font.fallbackName;
diff --git a/test/driver.js b/test/driver.js
index 50272ea61..36f2309e7 100644
--- a/test/driver.js
+++ b/test/driver.js
@@ -194,15 +194,18 @@ SimpleTextLayerBuilder.prototype = {
   appendText: function SimpleTextLayerBuilder_AppendText(geom) {
     var ctx = this.ctx, viewport = this.viewport;
     // vScale and hScale already contain the scaling to pixel units
-    var fontHeight = geom.fontSize * geom.vScale;
+    var fontHeight = geom.fontSize * Math.abs(geom.vScale);
+    ctx.save();
     ctx.beginPath();
     ctx.strokeStyle = 'red';
     ctx.fillStyle = 'yellow';
-    ctx.rect(geom.x, geom.y - fontHeight,
-             geom.canvasWidth * geom.hScale, fontHeight);
+    ctx.translate(geom.x + (fontHeight * Math.sin(geom.angle)),
+                  geom.y - (fontHeight * Math.cos(geom.angle)));
+    ctx.rotate(geom.angle);
+    ctx.rect(0, 0, geom.canvasWidth * Math.abs(geom.hScale), fontHeight);
     ctx.stroke();
     ctx.fill();
-
+    ctx.restore();
     var textContent = this.textContent.bidiTexts[this.textCounter].str;
     ctx.font = fontHeight + 'px ' + geom.fontFamily;
     ctx.fillStyle = 'black';
diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore
index b8a523177..79c8ec6aa 100644
--- a/test/pdfs/.gitignore
+++ b/test/pdfs/.gitignore
@@ -29,6 +29,7 @@
 !TAMReview.pdf
 !issue918.pdf
 !issue1905.pdf
+!rotated.pdf
 !issue1249.pdf
 !smaskdim.pdf
 !endchar.pdf
diff --git a/test/pdfs/TaroUTR50SortedList112.pdf.link b/test/pdfs/TaroUTR50SortedList112.pdf.link
new file mode 100644
index 000000000..b8b7b6207
--- /dev/null
+++ b/test/pdfs/TaroUTR50SortedList112.pdf.link
@@ -0,0 +1 @@
+http://blogs.adobe.com/CCJKType/files/2012/07/TaroUTR50SortedList112.pdf
diff --git a/test/pdfs/rotated.pdf b/test/pdfs/rotated.pdf
new file mode 100644
index 000000000..3da0186e9
Binary files /dev/null and b/test/pdfs/rotated.pdf differ
diff --git a/test/test_manifest.json b/test/test_manifest.json
index 53730a45f..a2ea41615 100644
--- a/test/test_manifest.json
+++ b/test/test_manifest.json
@@ -178,6 +178,20 @@
        "rounds": 1,
        "type": "eq"
     },
+    {  "id": "taro-text",
+       "file": "pdfs/TaroUTR50SortedList112.pdf",
+       "md5": "ce63eab622ff473a43f8a8de85ef8a46",
+       "link":true,
+       "rounds": 1,
+       "lastPage": 4,
+       "type": "text"
+    },
+    {  "id": "rotated-text",
+       "file": "pdfs/rotated.pdf",
+       "md5": "aed187f53e969ccdcbab0bb4c59f9e46",
+       "rounds": 1,
+       "type": "text"
+    },
     {
       "id": "issue3115",
       "file": "pdfs/issue3115.pdf",
diff --git a/web/text_layer_builder.js b/web/text_layer_builder.js
index de9b72d0b..5aa6edfa1 100644
--- a/web/text_layer_builder.js
+++ b/web/text_layer_builder.js
@@ -81,11 +81,12 @@ var TextLayerBuilder = function textLayerBuilder(options) {
 
       if (width > 0) {
         var textScale = textDiv.dataset.canvasWidth / width;
-
+        var rotation = textDiv.dataset.angle;
         var transform = 'scale(' + textScale + ', 1)';
         if (bidiTexts[i].dir === 'ttb') {
-          transform = 'rotate(90deg) ' + transform;
+          rotation += 90;
         }
+        transform = 'rotate(' + rotation + 'deg) ' + transform;
         CustomStyle.setProp('transform' , textDiv, transform);
         CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
 
@@ -125,13 +126,14 @@ var TextLayerBuilder = function textLayerBuilder(options) {
 
     // vScale and hScale already contain the scaling to pixel units
     var fontHeight = geom.fontSize * Math.abs(geom.vScale);
-    textDiv.dataset.canvasWidth = geom.canvasWidth * geom.hScale;
+    textDiv.dataset.canvasWidth = geom.canvasWidth * Math.abs(geom.hScale);
     textDiv.dataset.fontName = geom.fontName;
+    textDiv.dataset.angle = geom.angle * (180 / Math.PI);
 
     textDiv.style.fontSize = fontHeight + 'px';
     textDiv.style.fontFamily = geom.fontFamily;
-    textDiv.style.left = geom.x + 'px';
-    textDiv.style.top = (geom.y - fontHeight) + 'px';
+    textDiv.style.left = (geom.x + (fontHeight * Math.sin(geom.angle))) + 'px';
+    textDiv.style.top = (geom.y - (fontHeight * Math.cos(geom.angle))) + 'px';
 
     // The content of the div is set in the `setTextContent` function.