[Pkg-javascript-commits] [pdf.js] 31/115: Better "text" testing.

David Prévot taffit at moszumanska.debian.org
Wed Dec 16 20:03:11 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository pdf.js.

commit bd7f121c8300b75aba4a21d5ef6022baa00b4eac
Author: Yury Delendik <ydelendik at mozilla.com>
Date:   Thu Nov 19 11:03:52 2015 -0600

    Better "text" testing.
---
 test/driver.js           | 176 +++++++++++++++++++++++------------------------
 test/test_manifest.json  |   6 --
 test/text_layer_test.css |  38 ++++++++++
 web/viewer.css           |  22 +++++-
 4 files changed, 147 insertions(+), 95 deletions(-)

diff --git a/test/driver.js b/test/driver.js
index c6c295f..c41ec70 100644
--- a/test/driver.js
+++ b/test/driver.js
@@ -22,80 +22,71 @@ var PDF_TO_CSS_UNITS = 96.0 / 72.0;
 /**
  * @class
  */
-var NullTextLayerBuilder = (function NullTextLayerBuilderClosure() {
-  /**
-   * @constructs NullTextLayerBuilder
-   */
-  function NullTextLayerBuilder() {}
-
-  NullTextLayerBuilder.prototype = {
-    beginLayout: function NullTextLayerBuilder_BeginLayout() {},
-    endLayout: function NullTextLayerBuilder_EndLayout() {},
-    appendText: function NullTextLayerBuilder_AppendText() {}
-  };
+var rasterizeTextLayer = (function rasterizeTextLayerClosure() {
+  var SVG_NS = 'http://www.w3.org/2000/svg';
 
-  return NullTextLayerBuilder;
-})();
-
-/**
- * @class
- */
-var SimpleTextLayerBuilder = (function SimpleTextLayerBuilderClosure() {
-  /**
-   * @constructs SimpleTextLayerBuilder
-   */
-  function SimpleTextLayerBuilder(ctx, viewport) {
-    this.ctx = ctx;
-    this.viewport = viewport;
-    this.textCounter = 0;
-
-    // clear canvas
-    ctx.save();
-    ctx.fillStyle = 'rgb(255,255,255)';
-    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-    ctx.restore();
+  var textLayerStylePromise = null;
+  function getTextLayerStyle() {
+    if (textLayerStylePromise) {
+      return textLayerStylePromise;
+    }
+    textLayerStylePromise = new Promise(function (resolve) {
+      var xhr = new XMLHttpRequest();
+      xhr.open('GET', './text_layer_test.css');
+      xhr.onload = function () {
+        resolve(xhr.responseText);
+      };
+      xhr.send(null);
+    });
+    return textLayerStylePromise;
   }
 
-  SimpleTextLayerBuilder.prototype = {
-    appendText: function SimpleTextLayerBuilder_AppendText(geom, styles) {
-      var style = styles[geom.fontName];
-      var ctx = this.ctx, viewport = this.viewport;
-      var tx = PDFJS.Util.transform(this.viewport.transform, geom.transform);
-      var angle = Math.atan2(tx[1], tx[0]);
-      var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3]));
-      var fontAscent = (style.ascent ? style.ascent * fontHeight :
-        (style.descent ? (1 + style.descent) * fontHeight : fontHeight));
-
-      ctx.save();
-      ctx.beginPath();
-      ctx.strokeStyle = 'red';
-      ctx.fillStyle = 'yellow';
-      ctx.translate(tx[4] + (fontAscent * Math.sin(angle)),
-                    tx[5] - (fontAscent * Math.cos(angle)));
-      ctx.rotate(angle);
-      ctx.rect(0, 0, geom.width * viewport.scale, geom.height * viewport.scale);
-      ctx.stroke();
-      ctx.fill();
-      ctx.restore();
-      ctx.font = fontHeight + 'px ' + style.fontFamily;
-      ctx.fillStyle = 'black';
-      ctx.fillText(geom.str, tx[4], tx[5]);
-
-      this.textCounter++;
-    },
-
-    setTextContent:
-        function SimpleTextLayerBuilder_SetTextContent(textContent) {
-      this.ctx.save();
-      var textItems = textContent.items;
-      for (var i = 0, ii = textItems.length; i < ii; i++) {
-        this.appendText(textItems[i], textContent.styles);
-      }
-      this.ctx.restore();
-    }
-  };
+  function rasterizeTextLayer(ctx, viewport, textContent) {
+    return new Promise(function (resolve) {
+      // Building SVG with size of the viewport.
+      var svg = document.createElementNS(SVG_NS, 'svg:svg');
+      svg.setAttribute('width', viewport.width + 'px');
+      svg.setAttribute('height', viewport.height + 'px');
+      // items are transformed to have 1px font size
+      svg.setAttribute('font-size', 1);
+
+      // Adding element to host our HTML (style + text layer div).
+      var foreignObject = document.createElementNS(SVG_NS, 'svg:foreignObject');
+      foreignObject.setAttribute('x', '0');
+      foreignObject.setAttribute('y', '0');
+      foreignObject.setAttribute('width', viewport.width + 'px');
+      foreignObject.setAttribute('height', viewport.height + 'px');
+      var style = document.createElement('style');
+      var stylePromise = getTextLayerStyle();
+      foreignObject.appendChild(style);
+      var div = document.createElement('div');
+      div.className = 'textLayer';
+      foreignObject.appendChild(div);
+
+      // Rendering text layer as HTML.
+      var task = PDFJS.renderTextLayer({
+        textContent: textContent,
+        container: div,
+        viewport: viewport
+      });
+      Promise.all([stylePromise, task.promise]).then(function (results) {
+        style.textContent = results[0];
+        svg.appendChild(foreignObject);
+
+        // We need to have UTF-8 encoded XML.
+        var svg_xml = unescape(encodeURIComponent(
+          (new XMLSerializer()).serializeToString(svg)));
+        var img = new Image();
+        img.src = 'data:image/svg+xml;base64,' + btoa(svg_xml);
+        img.onload = function () {
+          ctx.drawImage(img, 0, 0);
+          resolve();
+        };
+      });
+    });
+  }
 
-  return SimpleTextLayerBuilder;
+  return rasterizeTextLayer;
 })();
 
 /**
@@ -328,35 +319,44 @@ var Driver = (function DriverClosure() {
             self.canvas.height = viewport.height;
             self._clearCanvas();
 
-            var drawContext, textLayerBuilder;
-            var resolveInitPromise;
-            var initPromise = new Promise(function (resolve) {
-              resolveInitPromise = resolve;
-            });
+            var textLayerCanvas;
+            var initPromise;
             if (task.type === 'text') {
               // Using a dummy canvas for PDF context drawing operations
-              if (!self.dummyCanvas) {
-                self.dummyCanvas = document.createElement('canvas');
+              textLayerCanvas = self.textLayerCanvas;
+              if (!textLayerCanvas) {
+                textLayerCanvas = document.createElement('canvas');
+                self.textLayerCanvas = textLayerCanvas;
               }
-              drawContext = self.dummyCanvas.getContext('2d');
+              textLayerCanvas.width = viewport.width;
+              textLayerCanvas.height = viewport.height;
+              var textLayerContext = textLayerCanvas.getContext('2d');
+              textLayerContext.clearRect(0, 0,
+                textLayerCanvas.width, textLayerCanvas.height);
               // The text builder will draw its content on the test canvas
-              textLayerBuilder = new SimpleTextLayerBuilder(ctx, viewport);
-
-              page.getTextContent().then(function(textContent) {
-                textLayerBuilder.setTextContent(textContent);
-                resolveInitPromise();
+              initPromise = page.getTextContent().then(function(textContent) {
+                return rasterizeTextLayer(textLayerContext, viewport,
+                                          textContent);
               });
             } else {
-              drawContext = ctx;
-              textLayerBuilder = new NullTextLayerBuilder();
-              resolveInitPromise();
+              textLayerCanvas = null;
+              initPromise = Promise.resolve();
             }
             var renderContext = {
-              canvasContext: drawContext,
+              canvasContext: ctx,
               viewport: viewport
             };
             var completeRender = (function(error) {
-              page.destroy();
+              // if text layer is present, compose it on top of the page
+              if (textLayerCanvas) {
+                ctx.save();
+                ctx.globalCompositeOperation = 'screen';
+                ctx.fillStyle = 'rgb(128, 255, 128)'; // making it green
+                ctx.fillRect(0, 0, viewport.width, viewport.height);
+                ctx.restore();
+                ctx.drawImage(textLayerCanvas, 0, 0);
+              }
+              page.cleanup();
               task.stats = page.stats;
               page.stats = new StatTimer();
               self._snapshot(task, error);
diff --git a/test/test_manifest.json b/test/test_manifest.json
index d478031..1bb299c 100644
--- a/test/test_manifest.json
+++ b/test/test_manifest.json
@@ -323,12 +323,6 @@
       "lastPage": 1,
       "about": "The same file as issue2337."
     },
-    {  "id": "thuluthfont-text",
-       "file": "pdfs/ThuluthFeatures.pdf",
-       "md5": "b7e18bf7a3d6a9c82aefa12d721072fc",
-       "rounds": 1,
-       "type": "text"
-    },
     {  "id": "freeculture",
        "file": "pdfs/freeculture.pdf",
        "md5": "dcdf3a8268e6a18938a42d5149efcfca",
diff --git a/test/text_layer_test.css b/test/text_layer_test.css
new file mode 100644
index 0000000..ed62e6c
--- /dev/null
+++ b/test/text_layer_test.css
@@ -0,0 +1,38 @@
+/* Copyright 2015 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Used in 'text' tests */
+
+.textLayer {
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  bottom: 0;
+}
+.textLayer > div {
+  position: absolute;
+  white-space: pre;
+  -webkit-transform-origin: 0% 0%;
+  -moz-transform-origin: 0% 0%;
+  -o-transform-origin: 0% 0%;
+  -ms-transform-origin: 0% 0%;
+  transform-origin: 0% 0%;
+  border: solid 1px rgba(255, 0, 0, 0.5);
+  background-color: rgba(255, 255, 32, 0.1);
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
diff --git a/web/viewer.css b/web/viewer.css
index b012631..b782684 100644
--- a/web/viewer.css
+++ b/web/viewer.css
@@ -1515,7 +1515,27 @@ html[dir='rtl'] #documentPropertiesOverlay .row > * {
   font-size: 10px;
 }
 
-#viewer.textLayer-visible .textLayer > div,
+#viewer.textLayer-visible .textLayer {
+  opacity: 1.0;
+}
+
+#viewer.textLayer-visible .canvasWrapper {
+  background-color: rgb(128,255,128);
+}
+
+#viewer.textLayer-visible .canvasWrapper canvas {
+  mix-blend-mode: screen;
+}
+
+#viewer.textLayer-visible .textLayer > div {
+  background-color: rgba(255, 255, 0, 0.1);
+  color: black;
+  border: solid 1px rgba(255, 0, 0, 0.5);
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+
 #viewer.textLayer-hover .textLayer > div:hover {
   background-color: white;
   color: black;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git



More information about the Pkg-javascript-commits mailing list