]> git.parisson.com Git - pdf.js.git/commitdiff
Fix
authorJulian Viereck <julian.viereck@gmail.com>
Sat, 10 Sep 2011 01:14:42 +0000 (18:14 -0700)
committerJulian Viereck <julian.viereck@gmail.com>
Thu, 15 Sep 2011 20:16:03 +0000 (13:16 -0700)
worker/boot_processor.js [new file with mode: 0644]
worker/canvas.js [deleted file]
worker/client.js [deleted file]
worker/font.js [deleted file]

diff --git a/worker/boot_processor.js b/worker/boot_processor.js
new file mode 100644 (file)
index 0000000..241870c
--- /dev/null
@@ -0,0 +1,18 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+importScripts('console.js');
+importScripts('message_handler.js');
+importScripts('../pdf.js');
+importScripts('../fonts.js');
+importScripts('../crypto.js');
+importScripts('../glyphlist.js');
+importScripts('handler.js');
+
+// Listen for messages from the main thread.
+var pdfDoc = null;
+
+var handler = new MessageHandler("worker", this);
+WorkerHandler.setup(handler);
diff --git a/worker/canvas.js b/worker/canvas.js
deleted file mode 100644 (file)
index 5a9237d..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-
-'use strict';
-
-var JpegStreamProxyCounter = 0;
-// WebWorker Proxy for JpegStream.
-var JpegStreamProxy = (function() {
-  function constructor(bytes, dict) {
-    this.id = JpegStreamProxyCounter++;
-    this.dict = dict;
-
-    // Tell the main thread to create an image.
-    postMessage({
-      action: 'jpeg_stream',
-      data: {
-        id: this.id,
-        raw: bytesToString(bytes)
-      }
-    });
-  }
-
-  constructor.prototype = {
-    getImage: function() {
-      return this;
-    },
-    getChar: function() {
-      error('internal error: getChar is not valid on JpegStream');
-    }
-  };
-
-  return constructor;
-})();
-
-// Really simple GradientProxy. There is currently only one active gradient at
-// the time, meaning you can't create a gradient, create a second one and then
-// use the first one again. As this isn't used in pdf.js right now, it's okay.
-function GradientProxy(cmdQueue, x0, y0, x1, y1) {
-  cmdQueue.push(['$createLinearGradient', [x0, y0, x1, y1]]);
-  this.addColorStop = function(i, rgba) {
-    cmdQueue.push(['$addColorStop', [i, rgba]]);
-  }
-}
-
-// Really simple PatternProxy.
-var patternProxyCounter = 0;
-function PatternProxy(cmdQueue, object, kind) {
-  this.id = patternProxyCounter++;
-
-  if (!(object instanceof CanvasProxy)) {
-    throw 'unkown type to createPattern';
-  }
-
-  // Flush the object here to ensure it's available on the main thread.
-  // TODO: Make some kind of dependency management, such that the object
-  // gets flushed only if needed.
-  object.flush();
-  cmdQueue.push(['$createPatternFromCanvas', [this.id, object.id, kind]]);
-}
-
-var canvasProxyCounter = 0;
-function CanvasProxy(width, height) {
-  this.id = canvasProxyCounter++;
-
-  // The `stack` holds the rendering calls and gets flushed to the main thead.
-  var cmdQueue = this.cmdQueue = [];
-
-  // Dummy context that gets exposed.
-  var ctx = {};
-  this.getContext = function(type) {
-    if (type != '2d') {
-      throw 'CanvasProxy can only provide a 2d context.';
-    }
-    return ctx;
-  }
-
-  // Expose only the minimum of the canvas object - there is no dom to do
-  // more here.
-  this.width = width;
-  this.height = height;
-  ctx.canvas = this;
-
-  // Setup function calls to `ctx`.
-  var ctxFunc = [
-  'createRadialGradient',
-  'arcTo',
-  'arc',
-  'fillText',
-  'strokeText',
-  'createImageData',
-  'drawWindow',
-  'save',
-  'restore',
-  'scale',
-  'rotate',
-  'translate',
-  'transform',
-  'setTransform',
-  'clearRect',
-  'fillRect',
-  'strokeRect',
-  'beginPath',
-  'closePath',
-  'moveTo',
-  'lineTo',
-  'quadraticCurveTo',
-  'bezierCurveTo',
-  'rect',
-  'fill',
-  'stroke',
-  'clip',
-  'measureText',
-  'isPointInPath',
-
-  // These functions are necessary to track the rendering currentX state.
-  // The exact values can be computed on the main thread only, as the
-  // worker has no idea about text width.
-  '$setCurrentX',
-  '$addCurrentX',
-  '$saveCurrentX',
-  '$restoreCurrentX',
-  '$showText',
-  '$setFont'
-  ];
-
-  function buildFuncCall(name) {
-    return function() {
-      // console.log("funcCall", name)
-      cmdQueue.push([name, Array.prototype.slice.call(arguments)]);
-    }
-  }
-  var name;
-  for (var i = 0; i < ctxFunc.length; i++) {
-    name = ctxFunc[i];
-    ctx[name] = buildFuncCall(name);
-  }
-
-  // Some function calls that need more work.
-
-  ctx.createPattern = function(object, kind) {
-    return new PatternProxy(cmdQueue, object, kind);
-  }
-
-  ctx.createLinearGradient = function(x0, y0, x1, y1) {
-    return new GradientProxy(cmdQueue, x0, y0, x1, y1);
-  }
-
-  ctx.getImageData = function(x, y, w, h) {
-    return {
-      width: w,
-      height: h,
-      data: Uint8ClampedArray(w * h * 4)
-    };
-  }
-
-  ctx.putImageData = function(data, x, y, width, height) {
-    cmdQueue.push(['$putImageData', [data, x, y, width, height]]);
-  }
-
-  ctx.drawImage = function(image, x, y, width, height,
-                           sx, sy, swidth, sheight) {
-    if (image instanceof CanvasProxy) {
-      // Send the image/CanvasProxy to the main thread.
-      image.flush();
-      cmdQueue.push(['$drawCanvas', [image.id, x, y, sx, sy, swidth, sheight]]);
-    } else if (image instanceof JpegStreamProxy) {
-      cmdQueue.push(['$drawImage', [image.id, x, y, sx, sy, swidth, sheight]]);
-    } else {
-      throw 'unkown type to drawImage';
-    }
-  }
-
-  // Setup property access to `ctx`.
-  var ctxProp = {
-    // "canvas"
-    'globalAlpha': '1',
-    'globalCompositeOperation': 'source-over',
-    'strokeStyle': '#000000',
-    'fillStyle': '#000000',
-    'lineWidth': '1',
-    'lineCap': 'butt',
-    'lineJoin': 'miter',
-    'miterLimit': '10',
-    'shadowOffsetX': '0',
-    'shadowOffsetY': '0',
-    'shadowBlur': '0',
-    'shadowColor': 'rgba(0, 0, 0, 0)',
-    'font': '10px sans-serif',
-    'textAlign': 'start',
-    'textBaseline': 'alphabetic',
-    'mozTextStyle': '10px sans-serif',
-    'mozImageSmoothingEnabled': 'true'
-  };
-
-  function buildGetter(name) {
-    return function() {
-      return ctx['$' + name];
-    }
-  }
-
-  function buildSetter(name) {
-    return function(value) {
-      cmdQueue.push(['$', name, value]);
-      return ctx['$' + name] = value;
-    }
-  }
-
-  // Setting the value to `stroke|fillStyle` needs special handling, as it
-  // might gets an gradient/pattern.
-  function buildSetterStyle(name) {
-    return function(value) {
-      if (value instanceof GradientProxy) {
-        cmdQueue.push(['$' + name + 'Gradient']);
-      } else if (value instanceof PatternProxy) {
-        cmdQueue.push(['$' + name + 'Pattern', [value.id]]);
-      } else {
-        cmdQueue.push(['$', name, value]);
-        return ctx['$' + name] = value;
-      }
-    }
-  }
-
-  for (var name in ctxProp) {
-    ctx['$' + name] = ctxProp[name];
-    ctx.__defineGetter__(name, buildGetter(name));
-
-    // Special treatment for `fillStyle` and `strokeStyle`: The passed style
-    // might be a gradient. Need to check for that.
-    if (name == 'fillStyle' || name == 'strokeStyle') {
-      ctx.__defineSetter__(name, buildSetterStyle(name));
-    } else {
-      ctx.__defineSetter__(name, buildSetter(name));
-    }
-  }
-}
-
-/**
-* Sends the current cmdQueue of the CanvasProxy over to the main thread and
-* resets the cmdQueue.
-*/
-CanvasProxy.prototype.flush = function() {
-  postMessage({
-    action: 'canvas_proxy_cmd_queue',
-    data: {
-      id: this.id,
-      cmdQueue: this.cmdQueue,
-      width: this.width,
-      height: this.height
-    }
-  });
-  this.cmdQueue.length = 0;
-};
diff --git a/worker/client.js b/worker/client.js
deleted file mode 100644 (file)
index a20a417..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-
-'use strict';
-
-if (typeof console.time == 'undefined') {
-  var consoleTimer = {};
-  console.time = function(name) {
-    consoleTimer[name] = Date.now();
-  };
-
-  console.timeEnd = function(name) {
-    var time = consoleTimer[name];
-    if (time == null) {
-      throw 'Unkown timer name ' + name;
-    }
-    this.log('Timer:', name, Date.now() - time);
-  };
-}
-
-function FontWorker() {
-  this.worker = new Worker('worker/font.js');
-  this.fontsWaiting = 0;
-  this.fontsWaitingCallbacks = [];
-
-  // Listen to the WebWorker for data and call actionHandler on it.
-  this.worker.onmessage = function(event) {
-    var data = event.data;
-    var actionHandler = this.actionHandler;
-    if (data.action in actionHandler) {
-      actionHandler[data.action].call(this, data.data);
-    } else {
-      throw 'Unkown action from worker: ' + data.action;
-    }
-  }.bind(this);
-
-  this.$handleFontLoadedCallback = this.handleFontLoadedCallback.bind(this);
-}
-
-FontWorker.prototype = {
-  handleFontLoadedCallback: function() {
-    // Decrease the number of fonts wainting to be loaded.
-    this.fontsWaiting--;
-    // If all fonts are available now, then call all the callbacks.
-    if (this.fontsWaiting == 0) {
-      var callbacks = this.fontsWaitingCallbacks;
-      for (var i = 0; i < callbacks.length; i++) {
-        callbacks[i]();
-      }
-      this.fontsWaitingCallbacks.length = 0;
-    }
-  },
-
-  actionHandler: {
-    'log': function(data) {
-      console.log.apply(console, data);
-    },
-
-    'fonts': function(data) {
-      // console.log("got processed fonts from worker", Object.keys(data));
-      for (name in data) {
-        // Update the encoding property.
-        var font = Fonts.lookup(name);
-        font.properties = {
-          encoding: data[name].encoding
-        };
-
-        // Call `Font.prototype.bindDOM` to make the font get loaded
-        // on the page.
-        Font.prototype.bindDOM.call(
-          font,
-          data[name].str,
-          // IsLoadedCallback.
-          this.$handleFontLoadedCallback
-        );
-      }
-    }
-  },
-
-  ensureFonts: function(data, callback) {
-    var font;
-    var notLoaded = [];
-    for (var i = 0; i < data.length; i++) {
-      font = data[i];
-      if (Fonts[font.name]) {
-        continue;
-      }
-
-      // Register the font but don't pass in any real data. The idea is to
-      // store as less data as possible to reduce memory usage.
-      Fonts.registerFont(font.name, Object.create(null), Object.create(null));
-
-      // Mark this font to be handled later.
-      notLoaded.push(font);
-      // Increate the number of fonts to wait for.
-      this.fontsWaiting++;
-    }
-
-    console.time('ensureFonts');
-    // If there are fonts, that need to get loaded, tell the FontWorker to get
-    // started and push the callback on the waiting-callback-stack.
-    if (notLoaded.length != 0) {
-      console.log('fonts -> FontWorker');
-      // Send the worker the fonts to work on.
-      this.worker.postMessage({
-        action: 'fonts',
-        data: notLoaded
-      });
-      if (callback) {
-        this.fontsWaitingCallbacks.push(callback);
-      }
-    }
-    // All fonts are present? Well, then just call the callback if there is one.
-    else {
-      if (callback) {
-        callback();
-      }
-    }
-  }
-};
-
-function WorkerPDFDoc(canvas) {
-  var timer = null;
-
-  this.ctx = canvas.getContext('2d');
-  this.canvas = canvas;
-  this.worker = new Worker('worker/pdf.js');
-  this.fontWorker = new FontWorker();
-  this.waitingForFonts = false;
-  this.waitingForFontsCallback = [];
-
-  this.numPage = 1;
-  this.numPages = null;
-
-  var imagesList = {};
-  var canvasList = {
-    0: canvas
-  };
-  var patternList = {};
-  var gradient;
-
-  var currentX = 0;
-  var currentXStack = [];
-
-  var ctxSpecial = {
-    '$setCurrentX': function(value) {
-      currentX = value;
-    },
-
-    '$addCurrentX': function(value) {
-      currentX += value;
-    },
-
-    '$saveCurrentX': function() {
-      currentXStack.push(currentX);
-    },
-
-    '$restoreCurrentX': function() {
-      currentX = currentXStack.pop();
-    },
-
-    '$showText': function(y, text) {
-      text = Fonts.charsToUnicode(text);
-      this.translate(currentX, -1 * y);
-      this.fillText(text, 0, 0);
-      currentX += this.measureText(text).width;
-    },
-
-    '$putImageData': function(imageData, x, y) {
-      var imgData = this.getImageData(0, 0, imageData.width, imageData.height);
-
-      // Store the .data property to avaid property lookups.
-      var imageRealData = imageData.data;
-      var imgRealData = imgData.data;
-
-      // Copy over the imageData.
-      var len = imageRealData.length;
-      while (len--)
-      imgRealData[len] = imageRealData[len];
-
-      this.putImageData(imgData, x, y);
-    },
-
-    '$drawImage': function(id, x, y, sx, sy, swidth, sheight) {
-      var image = imagesList[id];
-      if (!image) {
-        throw 'Image not found: ' + id;
-      }
-      this.drawImage(image, x, y, image.width, image.height,
-        sx, sy, swidth, sheight);
-    },
-
-    '$drawCanvas': function(id, x, y, sx, sy, swidth, sheight) {
-      var canvas = canvasList[id];
-      if (!canvas) {
-        throw 'Canvas not found';
-      }
-      if (sheight != null) {
-        this.drawImage(canvas, x, y, canvas.width, canvas.height,
-          sx, sy, swidth, sheight);
-      } else {
-        this.drawImage(canvas, x, y, canvas.width, canvas.height);
-      }
-    },
-
-    '$createLinearGradient': function(x0, y0, x1, y1) {
-      gradient = this.createLinearGradient(x0, y0, x1, y1);
-    },
-
-    '$createPatternFromCanvas': function(patternId, canvasId, kind) {
-      var canvas = canvasList[canvasId];
-      if (!canvas) {
-        throw 'Canvas not found';
-      }
-      patternList[patternId] = this.createPattern(canvas, kind);
-    },
-
-    '$addColorStop': function(i, rgba) {
-      gradient.addColorStop(i, rgba);
-    },
-
-    '$fillStyleGradient': function() {
-      this.fillStyle = gradient;
-    },
-
-    '$fillStylePattern': function(id) {
-      var pattern = patternList[id];
-      if (!pattern) {
-        throw 'Pattern not found';
-      }
-      this.fillStyle = pattern;
-    },
-
-    '$strokeStyleGradient': function() {
-      this.strokeStyle = gradient;
-    },
-
-    '$strokeStylePattern': function(id) {
-      var pattern = patternList[id];
-      if (!pattern) {
-        throw 'Pattern not found';
-      }
-      this.strokeStyle = pattern;
-    },
-
-    '$setFont': function(name, size) {
-      this.font = size + 'px "' + name + '"';
-      Fonts.setActive(name, size);
-    }
-  };
-
-  function renderProxyCanvas(canvas, cmdQueue) {
-    var ctx = canvas.getContext('2d');
-    var cmdQueueLength = cmdQueue.length;
-    for (var i = 0; i < cmdQueueLength; i++) {
-      var opp = cmdQueue[i];
-      if (opp[0] == '$') {
-        ctx[opp[1]] = opp[2];
-      } else if (opp[0] in ctxSpecial) {
-        ctxSpecial[opp[0]].apply(ctx, opp[1]);
-      } else {
-        ctx[opp[0]].apply(ctx, opp[1]);
-      }
-    }
-  }
-
-  /**
-  * Functions to handle data sent by the WebWorker.
-  */
-  var actionHandler = {
-    'log': function(data) {
-      console.log.apply(console, data);
-    },
-
-    'pdf_num_pages': function(data) {
-      this.numPages = parseInt(data);
-      if (this.loadCallback) {
-        this.loadCallback();
-      }
-    },
-
-    'font': function(data) {
-      var base64 = window.btoa(data.raw);
-
-      // Add the @font-face rule to the document
-      var url = 'url(data:' + data.mimetype + ';base64,' + base64 + ');';
-      var rule = ("@font-face { font-family:'" + data.fontName +
-                  "';src:" + url + '}');
-      var styleSheet = document.styleSheets[0];
-      styleSheet.insertRule(rule, styleSheet.cssRules.length);
-
-      // Just adding the font-face to the DOM doesn't make it load. It
-      // seems it's loaded once Gecko notices it's used. Therefore,
-      // add a div on the page using the loaded font.
-      var div = document.createElement('div');
-      var style = 'font-family:"' + data.fontName +
-        '";position: absolute;top:-99999;left:-99999;z-index:-99999';
-      div.setAttribute('style', style);
-      document.body.appendChild(div);
-    },
-
-    'setup_page': function(data) {
-      var size = data.split(',');
-      var canvas = this.canvas, ctx = this.ctx;
-      canvas.width = parseInt(size[0]);
-      canvas.height = parseInt(size[1]);
-    },
-
-    'fonts': function(data) {
-      this.waitingForFonts = true;
-      this.fontWorker.ensureFonts(data, function() {
-        this.waitingForFonts = false;
-        var callbacks = this.waitingForFontsCallback;
-        for (var i = 0; i < callbacks.length; i++) {
-          callbacks[i]();
-        }
-        this.waitingForFontsCallback.length = 0;
-      }.bind(this));
-    },
-
-    'jpeg_stream': function(data) {
-      var img = new Image();
-      img.src = 'data:image/jpeg;base64,' + window.btoa(data.raw);
-      imagesList[data.id] = img;
-    },
-
-    'canvas_proxy_cmd_queue': function(data) {
-        var id = data.id;
-        var cmdQueue = data.cmdQueue;
-
-        // Check if there is already a canvas with the given id. If not,
-        // create a new canvas.
-        if (!canvasList[id]) {
-          var newCanvas = document.createElement('canvas');
-          newCanvas.width = data.width;
-          newCanvas.height = data.height;
-          canvasList[id] = newCanvas;
-        }
-
-        var renderData = function() {
-          if (id == 0) {
-            console.time('main canvas rendering');
-            var ctx = this.ctx;
-            ctx.save();
-            ctx.fillStyle = 'rgb(255, 255, 255)';
-            ctx.fillRect(0, 0, canvas.width, canvas.height);
-            ctx.restore();
-          }
-          renderProxyCanvas(canvasList[id], cmdQueue);
-          if (id == 0) {
-            console.timeEnd('main canvas rendering');
-            console.timeEnd('>>> total page display time:');
-          }
-        }.bind(this);
-
-        if (this.waitingForFonts) {
-          if (id == 0) {
-            console.log('want to render, but not all fonts are there', id);
-            this.waitingForFontsCallback.push(renderData);
-          } else {
-            // console.log("assume canvas doesn't have fonts", id);
-            renderData();
-          }
-        } else {
-          renderData();
-        }
-    }
-  };
-
-  // Listen to the WebWorker for data and call actionHandler on it.
-  this.worker.onmessage = function(event) {
-    var data = event.data;
-    if (data.action in actionHandler) {
-      actionHandler[data.action].call(this, data.data);
-    } else {
-      throw 'Unkown action from worker: ' + data.action;
-    }
-  }.bind(this);
-}
-
-WorkerPDFDoc.prototype.open = function(url, callback) {
-  var req = new XMLHttpRequest();
-  req.open('GET', url);
-  req.mozResponseType = req.responseType = 'arraybuffer';
-  req.expected = (document.URL.indexOf('file:') == 0) ? 0 : 200;
-  req.onreadystatechange = function() {
-    if (req.readyState == 4 && req.status == req.expected) {
-      var data = req.mozResponseArrayBuffer || req.mozResponse ||
-      req.responseArrayBuffer || req.response;
-
-      this.loadCallback = callback;
-      this.worker.postMessage(data);
-      this.showPage(this.numPage);
-    }
-  }.bind(this);
-  req.send(null);
-};
-
-WorkerPDFDoc.prototype.showPage = function(numPage) {
-  this.numPage = parseInt(numPage);
-  console.log('=== start rendering page ' + numPage + ' ===');
-  console.time('>>> total page display time:');
-  this.worker.postMessage(numPage);
-  if (this.onChangePage) {
-    this.onChangePage(numPage);
-  }
-};
-
-WorkerPDFDoc.prototype.nextPage = function() {
-  if (this.numPage == this.numPages) return;
-  this.showPage(++this.numPage);
-};
-
-WorkerPDFDoc.prototype.prevPage = function() {
-  if (this.numPage == 1) return;
-  this.showPage(--this.numPage);
-};
diff --git a/worker/font.js b/worker/font.js
deleted file mode 100644 (file)
index 549b731..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-
-'use strict';
-
-importScripts('console.js');
-
-importScripts('../pdf.js');
-importScripts('../fonts.js');
-importScripts('../glyphlist.js');
-
-function fontDataToString(font) {
-  // Doing postMessage on objects make them lose their "shape". This adds the
-  // "shape" for all required objects agains, such that the encoding works as
-  // expected.
-  var fontFileDict = new Dict();
-  fontFileDict.map = font.file.dict.map;
-
-  var fontFile = new Stream(font.file.bytes, font.file.start,
-                            font.file.end - font.file.start, fontFileDict);
-  font.file = new FlateStream(fontFile);
-
-  // This will encode the font.
-  var fontObj = new Font(font.name, font.file, font.properties);
-
-  // Create string that is used for css later.
-  var str = '';
-  var data = fontObj.data;
-  var length = data.length;
-  for (var j = 0; j < length; j++)
-    str += String.fromCharCode(data[j]);
-
-  return {
-    str: str,
-    encoding: font.properties.encoding
-  };
-}
-
-/**
-* Functions to handle data sent by the MainThread.
-*/
-var actionHandler = {
-  'fonts': function(data) {
-    var fontData;
-    var result = {};
-    for (var i = 0; i < data.length; i++) {
-      fontData = data[i];
-      result[fontData.name] = fontDataToString(fontData);
-    }
-
-    postMessage({
-      action: 'fonts',
-      data: result
-    });
-  }
-};
-
-// Listen to the MainThread for data and call actionHandler on it.
-this.onmessage = function(event) {
-  var data = event.data;
-  if (data.action in actionHandler) {
-    actionHandler[data.action].call(this, data.data);
-  } else {
-    throw 'Unkown action from worker: ' + data.action;
-  }
-};