diff --git a/fonts.js b/fonts.js
index 80651d224..9d8a9e806 100644
--- a/fonts.js
+++ b/fonts.js
@@ -34,65 +34,89 @@ var kDisableFonts = false;
* http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65
*/
-var kScalePrecision = 40;
-var Fonts = {
- _active: null,
+var Fonts = (function () {
+ var kScalePrecision = 40;
+ var fonts = Object.create(null);
+ var ctx = document.createElement("canvas").getContext("2d");
+ ctx.scale(1 / kScalePrecision, 1);
- get active() {
- return this._active;
- },
+ function Font(name, data, properties) {
+ this.name = name;
+ this.data = data;
+ this.properties = properties;
+ this.loading = true;
+ this.charsCache = Object.create(null);
+ this.sizes = [];
+ }
- setActive: function fonts_setActive(name, size) {
- this._active = this[name];
- this.ctx.font = (size * kScalePrecision) + 'px "' + name + '"';
- },
+ var current;
+ var charsCache;
+ var measureCache;
- charsToUnicode: function fonts_chars2Unicode(chars) {
- var active = this._active;
- if (!active)
- return chars;
+ return {
+ registerFont: function fonts_registerFont(fontName, data, properties) {
+ fonts[fontName] = new Font(fontName, data, properties);
+ },
+ blacklistFont: function fonts_blacklistFont(fontName) {
+ registerFont(fontName, null, {});
+ markLoaded(fontName);
+ },
+ lookup: function fonts_lookup(fontName) {
+ return fonts[fontName];
+ },
+ setActive: function fonts_setActive(fontName, size) {
+ current = fonts[fontName];
+ charsCache = current.charsCache;
+ var sizes = current.sizes;
+ if (!(measureCache = sizes[size]))
+ measureCache = sizes[size] = Object.create(null);
+ ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"';
+ },
+ charsToUnicode: function fonts_chars2Unicode(chars) {
+ if (!charsCache)
+ return chars;
- // if we translated this string before, just grab it from the cache
- var str = active.cache[chars];
- if (str)
- return str;
+ // if we translated this string before, just grab it from the cache
+ var str = charsCache[chars];
+ if (str)
+ return str;
- // translate the string using the font's encoding
- var encoding = active.properties.encoding;
- if (!encoding)
- return chars;
+ // translate the string using the font's encoding
+ var encoding = current.properties.encoding;
+ if (!encoding)
+ return chars;
- str = "";
- for (var i = 0; i < chars.length; ++i) {
- var charcode = chars.charCodeAt(i);
- var unicode = encoding[charcode];
+ str = "";
+ for (var i = 0; i < chars.length; ++i) {
+ var charcode = chars.charCodeAt(i);
+ var unicode = encoding[charcode];
- // Check if the glyph has already been converted
- if (!IsNum(unicode))
+ // Check if the glyph has already been converted
+ if (!IsNum(unicode))
unicode = encoding[unicode] = GlyphsUnicode[unicode.name];
- // Handle surrogate pairs
- if (unicode > 0xFFFF) {
- str += String.fromCharCode(unicode & 0xFFFF);
- unicode >>= 16;
+ // Handle surrogate pairs
+ if (unicode > 0xFFFF) {
+ str += String.fromCharCode(unicode & 0xFFFF);
+ unicode >>= 16;
+ }
+ str += String.fromCharCode(unicode);
}
- str += String.fromCharCode(unicode);
+
+ // Enter the translated string into the cache
+ return charsCache[chars] = str;
+ },
+ measureText: function fonts_measureText(text) {
+ var width;
+ if (measureCache && (width = measureCache[text]))
+ return width;
+ width = ctx.measureText(text).width / kScalePrecision;
+ if (measureCache)
+ measureCache[text] = width;
+ return width;
}
-
- // Enter the translated string into the cache
- return active.cache[chars] = str;
- },
-
- get ctx() {
- var ctx = document.createElement("canvas").getContext("2d");
- ctx.scale(1 / kScalePrecision, 1);
- return shadow(this, "ctx", ctx);
- },
-
- measureText: function fonts_measureText(text) {
- return this.ctx.measureText(text).width / kScalePrecision;
}
-};
+})();
var FontLoader = {
bind: function(fonts, callback) {
@@ -101,7 +125,7 @@ var FontLoader = {
function checkFontsLoaded() {
for (var i = 0; i < fonts.length; i++) {
var font = fonts[i];
- if (Fonts[font.name].loading) {
+ if (Fonts.lookup(font.name).loading) {
return false;
}
}
@@ -115,11 +139,11 @@ var FontLoader = {
for (var i = 0; i < fonts.length; i++) {
var font = fonts[i];
- if (!Fonts[font.name]) {
+ if (!Fonts.lookup(font.name)) {
var obj = new Font(font.name, font.file, font.properties);
var str = "";
- var data = Fonts[font.name].data;
+ var data = Fonts.lookup(font.name).data;
var length = data.length;
for (var j = 0; j < length; j++)
str += String.fromCharCode(data[j]);
@@ -152,8 +176,8 @@ var Font = (function () {
this.encoding = properties.encoding;
// If the font has already been decoded simply return it
- if (Fonts[name]) {
- this.font = Fonts[name].data;
+ if (Fonts.lookup(name)) {
+ this.font = Fonts.lookup(name).data;
return;
}
fontCount++;
@@ -162,12 +186,7 @@ var Font = (function () {
// If the font is to be ignored, register it like an already loaded font
// to avoid the cost of waiting for it be be loaded by the platform.
if (properties.ignore || kDisableFonts) {
- Fonts[name] = {
- data: file,
- loading: false,
- properties: {},
- cache: Object.create(null)
- }
+ Fonts.blacklistFont(name);
return;
}
@@ -194,13 +213,7 @@ var Font = (function () {
break;
}
this.data = data;
-
- Fonts[name] = {
- data: data,
- properties: properties,
- loading: true,
- cache: Object.create(null)
- };
+ Fonts.registerFont(name, data, properties);
};
function stringToArray(str) {
@@ -854,7 +867,7 @@ var Font = (function () {
src += ' var fontName="'+ fontName +'";\n';
src += ' window.onload = function () {\n'
src += ' var Fonts = top.document.defaultView.Fonts;\n';
- src += ' var font = Fonts[fontName];\n';
+ src += ' var font = Fonts.lookup(fontName);\n';
src += ' font.loading = false;\n';
src += ' var doc = top.document;\n';
src += ' var evt = doc.createEvent("Events");\n';
diff --git a/multi_page_viewer.js b/multi_page_viewer.js
index d60e96cb2..66357716e 100644
--- a/multi_page_viewer.js
+++ b/multi_page_viewer.js
@@ -29,11 +29,15 @@ var PDFViewer = {
scale: 1.0,
pageWidth: function(page) {
- return page.mediaBox[2] * PDFViewer.scale;
+ var pdfToCssUnitsCoef = 96.0 / 72.0;
+ var width = (page.mediaBox[2] - page.mediaBox[0]);
+ return width * PDFViewer.scale * pdfToCssUnitsCoef;
},
pageHeight: function(page) {
- return page.mediaBox[3] * PDFViewer.scale;
+ var pdfToCssUnitsCoef = 96.0 / 72.0;
+ var height = (page.mediaBox[3] - page.mediaBox[1]);
+ return height * PDFViewer.scale * pdfToCssUnitsCoef;
},
lastPagesDrawn: [],
@@ -106,10 +110,11 @@ var PDFViewer = {
canvas.id = 'thumbnail' + num;
canvas.mozOpaque = true;
- // Canvas dimensions must be specified in CSS pixels. CSS pixels
- // are always 96 dpi. These dimensions are 8.5in x 11in at 96dpi.
- canvas.width = 104;
- canvas.height = 134;
+ var pageWidth = PDFViewer.pageWidth(page);
+ var pageHeight = PDFViewer.pageHeight(page);
+ var thumbScale = Math.min(104 / pageWidth, 134 / pageHeight);
+ canvas.width = pageWidth * thumbScale;
+ canvas.height = pageHeight * thumbScale;
div.appendChild(canvas);
var ctx = canvas.getContext('2d');
@@ -168,8 +173,6 @@ var PDFViewer = {
canvas.id = 'page' + num;
canvas.mozOpaque = true;
- // Canvas dimensions must be specified in CSS pixels. CSS pixels
- // are always 96 dpi. These dimensions are 8.5in x 11in at 96dpi.
canvas.width = PDFViewer.pageWidth(page);
canvas.height = PDFViewer.pageHeight(page);
div.appendChild(canvas);
@@ -260,6 +263,12 @@ var PDFViewer = {
openURL: function(url) {
PDFViewer.url = url;
document.title = url;
+
+ if (this.thumbsLoadingInterval) {
+ // cancel thumbs loading operations
+ clearInterval(this.thumbsLoadingInterval);
+ this.thumbsLoadingInterval = null;
+ }
var req = new XMLHttpRequest();
req.open('GET', url);
@@ -276,7 +285,9 @@ var PDFViewer = {
req.send(null);
},
-
+
+ thumbsLoadingInterval: null,
+
readPDF: function(data) {
while (PDFViewer.element.hasChildNodes()) {
PDFViewer.element.removeChild(PDFViewer.element.firstChild);
@@ -298,12 +309,22 @@ var PDFViewer = {
PDFViewer.drawPage(1);
document.location.hash = 1;
- setTimeout(function() {
- for (var i = 1; i <= PDFViewer.numberOfPages; i++) {
- PDFViewer.createThumbnail(i);
- PDFViewer.drawThumbnail(i);
+ // slowly loading the thumbs (few per second)
+ // first time we are loading more images than subsequent
+ var currentPageIndex = 1, imagesToLoad = 15;
+ this.thumbsLoadingInterval = setInterval((function() {
+ while (imagesToLoad-- > 0) {
+ if (currentPageIndex > PDFViewer.numberOfPages) {
+ clearInterval(this.thumbsLoadingInterval);
+ this.thumbsLoadingInterval = null;
+ return;
+ }
+ PDFViewer.createThumbnail(currentPageIndex);
+ PDFViewer.drawThumbnail(currentPageIndex);
+ ++currentPageIndex;
}
- }, 500);
+ imagesToLoad = 3; // next time loading less images
+ }).bind(this), 500);
}
PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';
diff --git a/test/test_slave.html b/test/test_slave.html
index 8564b52b4..3180418fa 100644
--- a/test/test_slave.html
+++ b/test/test_slave.html
@@ -4,6 +4,7 @@
+