Skip to content

Commit ce17e94

Browse files
committed
Merge branch 'master' of https://github.com/andreasgal/pdf.js
2 parents 9b67a1e + be6397f commit ce17e94

File tree

11 files changed

+169
-116
lines changed

11 files changed

+169
-116
lines changed

fonts.js

Lines changed: 83 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -34,65 +34,89 @@ var kDisableFonts = false;
3434
* http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65
3535
*/
3636

37-
var kScalePrecision = 40;
38-
var Fonts = {
39-
_active: null,
37+
var Fonts = (function () {
38+
var kScalePrecision = 40;
39+
var fonts = Object.create(null);
40+
var ctx = document.createElement("canvas").getContext("2d");
41+
ctx.scale(1 / kScalePrecision, 1);
4042

41-
get active() {
42-
return this._active;
43-
},
44-
45-
setActive: function fonts_setActive(name, size) {
46-
this._active = this[name];
47-
this.ctx.font = (size * kScalePrecision) + 'px "' + name + '"';
48-
},
49-
50-
charsToUnicode: function fonts_chars2Unicode(chars) {
51-
var active = this._active;
52-
if (!active)
53-
return chars;
54-
55-
// if we translated this string before, just grab it from the cache
56-
var str = active.cache[chars];
57-
if (str)
58-
return str;
59-
60-
// translate the string using the font's encoding
61-
var encoding = active.properties.encoding;
62-
if (!encoding)
63-
return chars;
43+
function Font(name, data, properties) {
44+
this.name = name;
45+
this.data = data;
46+
this.properties = properties;
47+
this.loading = true;
48+
this.charsCache = Object.create(null);
49+
this.sizes = [];
50+
}
6451

65-
str = "";
66-
for (var i = 0; i < chars.length; ++i) {
67-
var charcode = chars.charCodeAt(i);
68-
var unicode = encoding[charcode];
52+
var current;
53+
var charsCache;
54+
var measureCache;
6955

70-
// Check if the glyph has already been converted
71-
if (!IsNum(unicode))
56+
return {
57+
registerFont: function fonts_registerFont(fontName, data, properties) {
58+
fonts[fontName] = new Font(fontName, data, properties);
59+
},
60+
blacklistFont: function fonts_blacklistFont(fontName) {
61+
registerFont(fontName, null, {});
62+
markLoaded(fontName);
63+
},
64+
lookup: function fonts_lookup(fontName) {
65+
return fonts[fontName];
66+
},
67+
setActive: function fonts_setActive(fontName, size) {
68+
current = fonts[fontName];
69+
charsCache = current.charsCache;
70+
var sizes = current.sizes;
71+
if (!(measureCache = sizes[size]))
72+
measureCache = sizes[size] = Object.create(null);
73+
ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"';
74+
},
75+
charsToUnicode: function fonts_chars2Unicode(chars) {
76+
if (!charsCache)
77+
return chars;
78+
79+
// if we translated this string before, just grab it from the cache
80+
var str = charsCache[chars];
81+
if (str)
82+
return str;
83+
84+
// translate the string using the font's encoding
85+
var encoding = current.properties.encoding;
86+
if (!encoding)
87+
return chars;
88+
89+
str = "";
90+
for (var i = 0; i < chars.length; ++i) {
91+
var charcode = chars.charCodeAt(i);
92+
var unicode = encoding[charcode];
93+
94+
// Check if the glyph has already been converted
95+
if (!IsNum(unicode))
7296
unicode = encoding[unicode] = GlyphsUnicode[unicode.name];
7397

74-
// Handle surrogate pairs
75-
if (unicode > 0xFFFF) {
76-
str += String.fromCharCode(unicode & 0xFFFF);
77-
unicode >>= 16;
98+
// Handle surrogate pairs
99+
if (unicode > 0xFFFF) {
100+
str += String.fromCharCode(unicode & 0xFFFF);
101+
unicode >>= 16;
102+
}
103+
str += String.fromCharCode(unicode);
78104
}
79-
str += String.fromCharCode(unicode);
80-
}
81-
82-
// Enter the translated string into the cache
83-
return active.cache[chars] = str;
84-
},
85105

86-
get ctx() {
87-
var ctx = document.createElement("canvas").getContext("2d");
88-
ctx.scale(1 / kScalePrecision, 1);
89-
return shadow(this, "ctx", ctx);
90-
},
91-
92-
measureText: function fonts_measureText(text) {
93-
return this.ctx.measureText(text).width / kScalePrecision;
106+
// Enter the translated string into the cache
107+
return charsCache[chars] = str;
108+
},
109+
measureText: function fonts_measureText(text) {
110+
var width;
111+
if (measureCache && (width = measureCache[text]))
112+
return width;
113+
width = ctx.measureText(text).width / kScalePrecision;
114+
if (measureCache)
115+
measureCache[text] = width;
116+
return width;
117+
}
94118
}
95-
};
119+
})();
96120

97121
var FontLoader = {
98122
bind: function(fonts) {
@@ -101,8 +125,8 @@ var FontLoader = {
101125

102126
for (var i = 0; i < fonts.length; i++) {
103127
var font = fonts[i];
104-
if (Fonts[font.name]) {
105-
ready = ready && !Fonts[font.name].loading;
128+
if (Fonts.lookup(font.name)) {
129+
ready = ready && !Fonts.lookup(font.name).loading;
106130
continue;
107131
}
108132

@@ -111,7 +135,7 @@ var FontLoader = {
111135
var obj = new Font(font.name, font.file, font.properties);
112136

113137
var str = "";
114-
var data = Fonts[font.name].data;
138+
var data = Fonts.lookup(font.name).data;
115139
var length = data.length;
116140
for (var j = 0; j < length; j++)
117141
str += String.fromCharCode(data[j]);
@@ -272,8 +296,8 @@ var Font = (function () {
272296
this.encoding = properties.encoding;
273297

274298
// If the font has already been decoded simply return it
275-
if (Fonts[name]) {
276-
this.font = Fonts[name].data;
299+
if (Fonts.lookup(name)) {
300+
this.font = Fonts.lookup(name).data;
277301
return;
278302
}
279303
fontCount++;
@@ -282,12 +306,7 @@ var Font = (function () {
282306
// If the font is to be ignored, register it like an already loaded font
283307
// to avoid the cost of waiting for it be be loaded by the platform.
284308
if (properties.ignore || kDisableFonts) {
285-
Fonts[name] = {
286-
data: file,
287-
loading: false,
288-
properties: {},
289-
cache: Object.create(null)
290-
}
309+
Fonts.blacklistFont(name);
291310
return;
292311
}
293312

@@ -314,13 +333,7 @@ var Font = (function () {
314333
break;
315334
}
316335
this.data = data;
317-
318-
Fonts[name] = {
319-
data: data,
320-
properties: properties,
321-
loading: true,
322-
cache: Object.create(null)
323-
};
336+
Fonts.registerFont(name, data, properties);
324337
};
325338

326339
function stringToArray(str) {
@@ -1027,7 +1040,7 @@ var Font = (function () {
10271040
}
10281041

10291042
window.clearInterval(interval);
1030-
Fonts[fontName].loading = false;
1043+
Fonts.lookup(fontName).loading = false;
10311044
this.start = 0;
10321045
if (callback) {
10331046
callback();

multi_page_viewer.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ span {
181181
width: 200px;
182182
top: 62px;
183183
bottom: 18px;
184-
left: -170px;
184+
left: -140px;
185185
transition: left 0.25s ease-in-out 1s;
186186
-moz-transition: left 0.25s ease-in-out 1s;
187187
-webkit-transition: left 0.25s ease-in-out 1s;

multi_page_viewer.js

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,15 @@ var PDFViewer = {
2929
scale: 1.0,
3030

3131
pageWidth: function(page) {
32-
return page.mediaBox[2] * PDFViewer.scale;
32+
var pdfToCssUnitsCoef = 96.0 / 72.0;
33+
var width = (page.mediaBox[2] - page.mediaBox[0]);
34+
return width * PDFViewer.scale * pdfToCssUnitsCoef;
3335
},
3436

3537
pageHeight: function(page) {
36-
return page.mediaBox[3] * PDFViewer.scale;
38+
var pdfToCssUnitsCoef = 96.0 / 72.0;
39+
var height = (page.mediaBox[3] - page.mediaBox[1]);
40+
return height * PDFViewer.scale * pdfToCssUnitsCoef;
3741
},
3842

3943
lastPagesDrawn: [],
@@ -106,10 +110,11 @@ var PDFViewer = {
106110
canvas.id = 'thumbnail' + num;
107111
canvas.mozOpaque = true;
108112

109-
// Canvas dimensions must be specified in CSS pixels. CSS pixels
110-
// are always 96 dpi. These dimensions are 8.5in x 11in at 96dpi.
111-
canvas.width = 104;
112-
canvas.height = 134;
113+
var pageWidth = PDFViewer.pageWidth(page);
114+
var pageHeight = PDFViewer.pageHeight(page);
115+
var thumbScale = Math.min(104 / pageWidth, 134 / pageHeight);
116+
canvas.width = pageWidth * thumbScale;
117+
canvas.height = pageHeight * thumbScale;
113118
div.appendChild(canvas);
114119

115120
var ctx = canvas.getContext('2d');
@@ -175,8 +180,6 @@ var PDFViewer = {
175180
canvas.id = 'page' + num;
176181
canvas.mozOpaque = true;
177182

178-
// Canvas dimensions must be specified in CSS pixels. CSS pixels
179-
// are always 96 dpi. These dimensions are 8.5in x 11in at 96dpi.
180183
canvas.width = PDFViewer.pageWidth(page);
181184
canvas.height = PDFViewer.pageHeight(page);
182185
div.appendChild(canvas);
@@ -216,7 +219,6 @@ var PDFViewer = {
216219

217220
if (PDFViewer.pdf) {
218221
for (i = 1; i <= PDFViewer.numberOfPages; i++) {
219-
PDFViewer.createThumbnail(i);
220222
PDFViewer.createPage(i);
221223
}
222224
}
@@ -249,7 +251,10 @@ var PDFViewer = {
249251
PDFViewer.pageNumber = num;
250252
PDFViewer.pageNumberInput.value = PDFViewer.pageNumber;
251253
PDFViewer.willJumpToPage = true;
252-
254+
255+
if (document.location.hash.substr(1) == PDFViewer.pageNumber)
256+
// Force a "scroll event" to redraw
257+
setTimeout(window.onscroll, 0);
253258
document.location.hash = PDFViewer.pageNumber;
254259

255260
PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';
@@ -272,6 +277,12 @@ var PDFViewer = {
272277
openURL: function(url) {
273278
PDFViewer.url = url;
274279
document.title = url;
280+
281+
if (this.thumbsLoadingInterval) {
282+
// cancel thumbs loading operations
283+
clearInterval(this.thumbsLoadingInterval);
284+
this.thumbsLoadingInterval = null;
285+
}
275286

276287
var req = new XMLHttpRequest();
277288
req.open('GET', url);
@@ -288,7 +299,9 @@ var PDFViewer = {
288299

289300
req.send(null);
290301
},
291-
302+
303+
thumbsLoadingInterval: null,
304+
292305
readPDF: function(data) {
293306
while (PDFViewer.element.hasChildNodes()) {
294307
PDFViewer.element.removeChild(PDFViewer.element.firstChild);
@@ -310,12 +323,22 @@ var PDFViewer = {
310323
PDFViewer.drawPage(1);
311324
document.location.hash = 1;
312325

313-
setTimeout(function() {
314-
for (var i = 1; i <= PDFViewer.numberOfPages; i++) {
315-
PDFViewer.createThumbnail(i);
316-
PDFViewer.drawThumbnail(i);
326+
// slowly loading the thumbs (few per second)
327+
// first time we are loading more images than subsequent
328+
var currentPageIndex = 1, imagesToLoad = 15;
329+
this.thumbsLoadingInterval = setInterval((function() {
330+
while (imagesToLoad-- > 0) {
331+
if (currentPageIndex > PDFViewer.numberOfPages) {
332+
clearInterval(this.thumbsLoadingInterval);
333+
this.thumbsLoadingInterval = null;
334+
return;
335+
}
336+
PDFViewer.createThumbnail(currentPageIndex);
337+
PDFViewer.drawThumbnail(currentPageIndex);
338+
++currentPageIndex;
317339
}
318-
}, 500);
340+
imagesToLoad = 3; // next time loading less images
341+
}).bind(this), 500);
319342
}
320343

321344
PDFViewer.previousPageButton.className = (PDFViewer.pageNumber === 1) ? 'disabled' : '';

pdf.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3811,23 +3811,21 @@ var CanvasGraphics = (function() {
38113811
if (fontDescriptor && fontDescriptor.num) {
38123812
var fontDescriptor = this.xref.fetchIfRef(fontDescriptor);
38133813
fontName = fontDescriptor.get("FontName").name.replace("+", "_");
3814-
Fonts.setActive(fontName, size);
38153814
}
38163815

38173816
if (!fontName) {
38183817
// TODO: fontDescriptor is not available, fallback to default font
3819-
this.current.fontSize = size;
3820-
this.ctx.font = this.current.fontSize + 'px sans-serif';
3821-
Fonts.setActive("sans-serif", this.current.fontSize);
3822-
return;
3818+
fontName = "sans-serif";
38233819
}
38243820

38253821
this.current.fontName = fontName;
38263822
this.current.fontSize = size;
38273823

3828-
this.ctx.font = this.current.fontSize + 'px "' + fontName + '"';
38293824
if (this.ctx.$setFont) {
3830-
this.ctx.$setFont(fontName);
3825+
this.ctx.$setFont(fontName, size);
3826+
} else {
3827+
this.ctx.font = size + 'px "' + fontName + '"';
3828+
Fonts.setActive(fontName, size);
38313829
}
38323830
},
38333831
setTextRenderingMode: function(mode) {

test/test_slave.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<style type="text/css"></style>
55
<script type="text/javascript" src="/pdf.js"></script>
66
<script type="text/javascript" src="/fonts.js"></script>
7+
<script type="text/javascript" src="/crypto.js"></script>
78
<script type="text/javascript" src="/glyphlist.js"></script>
89
<script type="application/javascript">
910
var appPath, browser, canvas, currentTask, currentTaskIdx, failure, manifest, numPages, pdfDoc, stdout;
@@ -103,11 +104,12 @@
103104
}
104105

105106
try {
107+
var pdfToCssUnitsCoef = 96.0 / 72.0;
106108
// using mediaBox for the canvas size
107-
var wTwips = (currentPage.mediaBox[2] - currentPage.mediaBox[0]);
108-
var hTwips = (currentPage.mediaBox[3] - currentPage.mediaBox[1]);
109-
canvas.width = wTwips * 96.0 / 72.0;
110-
canvas.height = hTwips * 96.0 / 72.0;
109+
var pageWidth = (currentPage.mediaBox[2] - currentPage.mediaBox[0]);
110+
var pageHeight = (currentPage.mediaBox[3] - currentPage.mediaBox[1]);
111+
canvas.width = pageWidth * pdfToCssUnitsCoef;
112+
canvas.height = pageHeight * pdfToCssUnitsCoef;
111113
clear(ctx);
112114
} catch(e) {
113115
failure = 'page setup: '+ e.toString();

0 commit comments

Comments
 (0)