From 7d1cddf371c968ec03bc116e4af273971ca2dcdc Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 8 Dec 2011 21:18:04 -0800
Subject: [PATCH] Add ability to fast track natively supported jpegs.

---
 src/canvas.js    | 17 +++++++++++++++++
 src/core.js      |  4 ++++
 src/evaluator.js | 35 ++++++++++++++++++++---------------
 src/image.js     | 24 ++++++++++++++++++------
 src/stream.js    |  2 --
 5 files changed, 59 insertions(+), 23 deletions(-)

diff --git a/src/canvas.js b/src/canvas.js
index 128f4fbc9..5ec9435c7 100644
--- a/src/canvas.js
+++ b/src/canvas.js
@@ -1036,6 +1036,23 @@ var CanvasGraphics = (function canvasGraphics() {
       this.restore();
     },
 
+    paintJpegXObject: function canvasGraphicsPaintJpegXObject(objId, w, h) {
+      var domImage = this.objs.get(objId);
+      if (!domImage) {
+        error('Dependent image isn\'t ready yet');
+      }
+
+      this.save();
+
+      var ctx = this.ctx;
+      // scale the image to the unit square
+      ctx.scale(1 / w, -1 / h);
+
+      ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
+                    0, -h, w, h);
+
+      this.restore();
+    },
     paintImageMaskXObject: function canvasGraphicsPaintImageMaskXObject(
                              imgArray, inverseDecode, width, height) {
       function applyStencilMask(buffer, inverseDecode) {
diff --git a/src/core.js b/src/core.js
index 29bc56e32..cbe4d0fa5 100644
--- a/src/core.js
+++ b/src/core.js
@@ -563,6 +563,10 @@ var PDFDoc = (function pdfDoc() {
         var type = data[1];
 
         switch (type) {
+          case 'JpegStream':
+            var imageData = data[2];
+            loadJpegStream(id, imageData, this.objs);
+            break;
           case 'Image':
             var imageData = data[2];
             this.objs.resolve(id, imageData);
diff --git a/src/evaluator.js b/src/evaluator.js
index a53d15c50..cb46d1b3b 100644
--- a/src/evaluator.js
+++ b/src/evaluator.js
@@ -208,26 +208,31 @@ var PartialEvaluator = (function partialEvaluator() {
         // of image processing can be done here.
         var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
         insertDependency([objId]);
-        fn = 'paintImageXObject';
         args = [objId, w, h];
-        var resolve = (function(objId) {
-          return function resolve(data) {
-            handler.send('obj', [objId, 'Image', data]);
-          };
-        })(objId);
 
+        var softMask = dict.get('SMask', 'IM') || false;
+        if (!softMask && image instanceof JpegStream && image.isNative) {
+          // These JPEGs don't need any more processing so we can just send it.
+          fn = 'paintJpegXObject';
+          handler.send('obj', [objId, 'JpegStream', image.getIR()]);
+          return;
+        }
+
+        fn = 'paintImageXObject';
         var imageObj = new PDFImage(xref, resources, image, inline, handler);
 
-        imageObj.ready(function() {
-          var imgData = {
-            width: w,
-            height: h,
-            data: new Uint8Array(w * h * 4)
+        imageObj.ready((function() {
+          return function(data) {
+            var imgData = {
+              width: w,
+              height: h,
+              data: new Uint8Array(w * h * 4)
+            };
+            var pixels = imgData.data;
+            imageObj.fillRgbaBuffer(pixels, imageObj.decode);
+            handler.send('obj', [objId, 'Image', imgData]);
           };
-          var pixels = imgData.data;
-          imageObj.fillRgbaBuffer(pixels, imageObj.decode);
-          resolve(imgData);
-        });
+        })(objId));
       }
 
       uniquePrefix = uniquePrefix || '';
diff --git a/src/image.js b/src/image.js
index c1eaf1c8f..7b9b12c18 100644
--- a/src/image.js
+++ b/src/image.js
@@ -151,6 +151,8 @@ var PDFImage = (function pdfImage() {
       var buf = new Uint8Array(width * height);
 
       if (smask) {
+        if (!smask.isReady())
+          error('Soft mask is not ready.');
         var sw = smask.width;
         var sh = smask.height;
         if (sw != this.width || sh != this.height)
@@ -168,8 +170,7 @@ var PDFImage = (function pdfImage() {
     applyStencilMask: function applyStencilMask(buffer, inverseDecode) {
       var width = this.width, height = this.height;
       var bitStrideLength = (width + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(bitStrideLength * height);
+      var imgArray = this.getImageBytes(bitStrideLength * height);
       var imgArrayPos = 0;
       var i, j, mask, buf;
       // removing making non-masked pixels transparent
@@ -197,8 +198,7 @@ var PDFImage = (function pdfImage() {
 
       // rows start at byte boundary;
       var rowBytes = (width * numComps * bpc + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(height * rowBytes);
+      var imgArray = this.getImageBytes(height * rowBytes);
 
       var comps = this.colorSpace.getRgbBuffer(
         this.getComponents(imgArray, decodeMap), bpc);
@@ -225,8 +225,7 @@ var PDFImage = (function pdfImage() {
 
       // rows start at byte boundary;
       var rowBytes = (width * numComps * bpc + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(height * rowBytes);
+      var imgArray = this.getImageBytes(height * rowBytes);
 
       var comps = this.getComponents(imgArray);
       var length = width * height;
@@ -234,6 +233,12 @@ var PDFImage = (function pdfImage() {
       for (var i = 0; i < length; ++i)
         buffer[i] = comps[i];
     },
+    getImageBytes: function getImageBytes(length) {
+      if (!this.isReady())
+        error('Image is not ready to be read.');
+      this.image.reset();
+      return this.image.getBytes(length);
+    },
     isReady: function isReady() {
       return this.imageReady && this.smaskReady;
     },
@@ -250,3 +255,10 @@ var PDFImage = (function pdfImage() {
   };
   return constructor;
 })();
+function loadJpegStream(id, imageData, objs) {
+  var img = new Image();
+  img.onload = (function jpegImageLoaderOnload() {
+    objs.resolve(id, img);
+  });
+  img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
+}
diff --git a/src/stream.js b/src/stream.js
index e4732d87a..559fb2ca2 100644
--- a/src/stream.js
+++ b/src/stream.js
@@ -804,8 +804,6 @@ var JpegStream = (function jpegStream() {
 
     this.colorTransform = -1;
 
-    this.bytes = bytes;
-
     if (isAdobeImage(bytes)) {
       // when bug 674619 land, let's check if browser can do
       // normal cmyk and then we won't have to the following