1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-20 15:18:08 +02:00

Merge remote-tracking branch 'mozilla/master' into textsearch-1

Conflicts:
	src/core.js
	src/fonts.js
This commit is contained in:
notmasteryet 2012-01-22 13:56:56 -06:00
commit 1ac24dbc01
53 changed files with 6051 additions and 1127 deletions

View file

@ -5,11 +5,16 @@
// Checking if the typed arrays are supported
(function checkTypedArrayCompatibility() {
if (typeof Uint8Array !== 'undefined')
if (typeof Uint8Array !== 'undefined') {
// some mobile version might not support Float64Array
if (typeof Float64Array === 'undefined')
window.Float64Array = Float32Array;
return;
}
function subarray(start, end) {
return this.slice(start, end);
return new TypedArray(this.slice(start, end));
}
function setArrayOffset(array, offset) {
@ -46,6 +51,8 @@
window.Uint32Array = TypedArray;
window.Int32Array = TypedArray;
window.Uint16Array = TypedArray;
window.Float32Array = TypedArray;
window.Float64Array = TypedArray;
})();
// Object.create() ?

View file

@ -15,6 +15,7 @@ body {
/* === Toolbar === */
#controls {
background-color: #eee;
background: -o-linear-gradient(bottom,#eee 0%,#fff 100%);
background: -moz-linear-gradient(center bottom, #eee 0%, #fff 100%);
background: -webkit-gradient(linear, left bottom, left top, color-stop(0.0, #ddd), color-stop(1.0, #fff));
border-bottom: 1px solid #666;
@ -82,6 +83,7 @@ span#info {
bottom: 18px;
left: -290px;
transition: left 0.25s ease-in-out 1s;
-o-transition: left 0.25s ease-in-out 1s;
-moz-transition: left 0.25s ease-in-out 1s;
-webkit-transition: left 0.25s ease-in-out 1s;
z-index: 1;
@ -90,6 +92,7 @@ span#info {
#sidebar:hover {
left: 0px;
transition: left 0.25s ease-in-out 0s;
-o-transition: left 0.25s ease-in-out 0s;
-moz-transition: left 0.25s ease-in-out 0s;
-webkit-transition: left 0.25s ease-in-out 0s;
}
@ -365,7 +368,7 @@ canvas {
color: black;
padding: 3px;
margin: 3px;
white-space: pre;
width: 98%;
}
.clearBoth {

View file

@ -26,6 +26,7 @@
<script type="text/javascript" src="../src/stream.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/jpx.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="viewer.js"></script>
@ -67,10 +68,11 @@
<option value="0.75">75%</option>
<option value="1">100%</option>
<option value="1.25">125%</option>
<option value="1.5" selected="selected">150%</option>
<option value="1.5">150%</option>
<option value="2">200%</option>
<option id="pageWidthOption" value="page-width">Page Width</option>
<option id="pageFitOption" value="page-fit">Page Fit</option>
<option id="pageAutoOption" value="auto" selected="selected">Auto</option>
</select>
<div class="separator"></div>
@ -113,7 +115,7 @@
</button>
</div>
<div class="clearBoth"></div>
<div id="errorMoreInfo" hidden='true'></div>
<textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea>
</div>
<div id="sidebar">

View file

@ -4,7 +4,7 @@
'use strict';
var kDefaultURL = 'compressed.tracemonkey-pldi-09.pdf';
var kDefaultScale = 1.5;
var kDefaultScale = 'auto';
var kDefaultScaleDelta = 1.1;
var kCacheSize = 20;
var kCssUnits = 96.0 / 72.0;
@ -33,6 +33,9 @@ var RenderingQueue = (function RenderingQueueClosure() {
RenderingQueue.prototype = {
enqueueDraw: function RenderingQueueEnqueueDraw(item) {
if (!item.drawingRequired())
return; // as no redraw required, no need for queueing.
if ('rendering' in item)
return; // is already in the queue
@ -146,9 +149,13 @@ var PDFView = {
pages: [],
thumbnails: [],
currentScale: 0,
currentScaleValue: null,
initialBookmark: document.location.hash.substring(1),
setScale: function pdfViewSetScale(val, resetAutoSettings) {
if (val == this.currentScale)
return;
var pages = this.pages;
for (var i = 0; i < pages.length; i++)
pages[i].update(val * kCssUnits);
@ -169,6 +176,7 @@ var PDFView = {
return;
var scale = parseFloat(value);
this.currentScaleValue = value;
if (scale) {
this.setScale(scale, true);
return;
@ -187,6 +195,10 @@ var PDFView = {
this.setScale(
Math.min(pageWidthScale, pageHeightScale), resetAutoSettings);
}
if ('auto' == value)
this.setScale(Math.min(1.0, pageWidthScale), resetAutoSettings);
selectScaleOption(value);
},
zoomIn: function pdfViewZoomIn() {
@ -337,13 +349,14 @@ var PDFView = {
};
moreInfoButton.removeAttribute('hidden');
lessInfoButton.setAttribute('hidden', 'true');
errorMoreInfo.innerHTML = 'PDF.JS Build: ' + PDFJS.build + '\n';
errorMoreInfo.value = 'PDF.JS Build: ' + PDFJS.build + '\n';
if (moreInfo) {
errorMoreInfo.innerHTML += 'Message: ' + moreInfo.message;
errorMoreInfo.value += 'Message: ' + moreInfo.message;
if (moreInfo.stack)
errorMoreInfo.innerHTML += '\n' + 'Stack: ' + moreInfo.stack;
errorMoreInfo.value += '\n' + 'Stack: ' + moreInfo.stack;
}
errorMoreInfo.rows = errorMoreInfo.value.split('\n').length - 1;
},
progress: function pdfViewProgress(level) {
@ -357,6 +370,7 @@ var PDFView = {
// when page is painted, using the image as thumbnail base
pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
thumbnailView.setImage(pageView.canvas);
preDraw();
};
}
@ -428,6 +442,10 @@ var PDFView = {
this.switchSidebarView('outline');
}
// Reset the current scale, as otherwise the page's scale might not get
// updated if the zoom level stayed the same.
this.currentScale = 0;
this.currentScaleValue = null;
if (this.initialBookmark) {
this.setHash(this.initialBookmark);
this.initialBookmark = null;
@ -435,7 +453,7 @@ var PDFView = {
else if (storedHash)
this.setHash(storedHash);
else {
this.setScale(scale || kDefaultScale, true);
this.parseScale(scale || kDefaultScale, true);
this.page = 1;
}
@ -525,8 +543,16 @@ var PDFView = {
if ('zoom' in params) {
var zoomArgs = params.zoom.split(','); // scale,left,top
// building destination array
// If the zoom value, it has to get divided by 100. If it is a string,
// it should stay as it is.
var zoomArg = zoomArgs[0];
var zoomArgNumber = parseFloat(zoomArg);
if (zoomArgNumber)
zoomArg = zoomArgNumber / 100;
var dest = [null, {name: 'XYZ'}, (zoomArgs[1] | 0),
(zoomArgs[2] | 0), (zoomArgs[0] | 0) / 100];
(zoomArgs[2] | 0), zoomArg];
var currentPage = this.pages[pageNumber - 1];
currentPage.scrollIntoView(dest);
} else
@ -813,8 +839,12 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
}, 0);
};
this.drawingRequired = function() {
return !div.hasChildNodes();
};
this.draw = function pageviewDraw(callback) {
if (div.hasChildNodes()) {
if (!this.drawingRequired()) {
this.updateStats();
callback();
return;
@ -826,9 +856,13 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
div.appendChild(canvas);
this.canvas = canvas;
var textLayer = document.createElement('div');
textLayer.className = 'textLayer';
div.appendChild(textLayer);
var textLayerDiv = null;
if (!PDFJS.disableTextLayer) {
textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer';
div.appendChild(textLayerDiv);
}
var textLayer = textLayerDiv ? new TextLayerBuilder(textLayerDiv) : null;
var scale = this.scale;
canvas.width = pageWidth * scale;
@ -923,6 +957,10 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
return ctx;
}
this.drawingRequired = function thumbnailViewDrawingRequired() {
return !this.hasImage;
};
this.draw = function thumbnailViewDraw(callback) {
if (this.hasImage) {
callback();
@ -985,6 +1023,86 @@ var DocumentOutlineView = function documentOutlineView(outline) {
}
};
var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
this.textLayerDiv = textLayerDiv;
this.beginLayout = function textLayerBuilderBeginLayout() {
this.textDivs = [];
this.textLayerQueue = [];
};
this.endLayout = function textLayerBuilderEndLayout() {
var self = this;
var textDivs = this.textDivs;
var textLayerDiv = this.textLayerDiv;
var renderTimer = null;
var renderingDone = false;
var renderInterval = 0;
var resumeInterval = 500; // in ms
// Render the text layer, one div at a time
function renderTextLayer() {
if (textDivs.length === 0) {
clearInterval(renderTimer);
renderingDone = true;
return;
}
var textDiv = textDivs.shift();
if (textDiv.dataset.textLength > 0) {
textLayerDiv.appendChild(textDiv);
if (textDiv.dataset.textLength > 1) { // avoid div by zero
// Adjust div width (via letterSpacing) to match canvas text
// Due to the .offsetWidth calls, this is slow
// This needs to come after appending to the DOM
textDiv.style.letterSpacing =
((textDiv.dataset.canvasWidth - textDiv.offsetWidth) /
(textDiv.dataset.textLength - 1)) + 'px';
}
} // textLength > 0
}
renderTimer = setInterval(renderTextLayer, renderInterval);
// Stop rendering when user scrolls. Resume after XXX milliseconds
// of no scroll events
var scrollTimer = null;
function textLayerOnScroll() {
if (renderingDone) {
window.removeEventListener('scroll', textLayerOnScroll, false);
return;
}
// Immediately pause rendering
clearInterval(renderTimer);
clearTimeout(scrollTimer);
scrollTimer = setTimeout(function textLayerScrollTimer() {
// Resume rendering
renderTimer = setInterval(renderTextLayer, renderInterval);
}, resumeInterval);
}; // textLayerOnScroll
window.addEventListener('scroll', textLayerOnScroll, false);
}; // endLayout
this.appendText = function textLayerBuilderAppendText(text,
fontName, fontSize) {
var textDiv = document.createElement('div');
// vScale and hScale already contain the scaling to pixel units
var fontHeight = fontSize * text.geom.vScale;
textDiv.dataset.canvasWidth = text.canvasWidth * text.geom.hScale;
textDiv.style.fontSize = fontHeight + 'px';
textDiv.style.fontFamily = fontName || 'sans-serif';
textDiv.style.left = text.geom.x + 'px';
textDiv.style.top = (text.geom.y - fontHeight) + 'px';
textDiv.textContent = text.str;
textDiv.dataset.textLength = text.length;
this.textDivs.push(textDiv);
};
};
window.addEventListener('load', function webViewerLoad(evt) {
var params = document.location.search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
@ -992,7 +1110,7 @@ window.addEventListener('load', function webViewerLoad(evt) {
params[unescape(param[0])] = unescape(param[1]);
}
var scale = ('scale' in params) ? params.scale : kDefaultScale;
var scale = ('scale' in params) ? params.scale : 0;
PDFView.open(params.file || kDefaultURL, parseFloat(scale));
if (!window.File || !window.FileReader || !window.FileList || !window.Blob)
@ -1001,7 +1119,10 @@ window.addEventListener('load', function webViewerLoad(evt) {
document.getElementById('fileInput').value = null;
if ('disableWorker' in params)
PDFJS.disableWorker = params['disableWorker'] === 'true' ? true : false;
PDFJS.disableWorker = (params['disableWorker'] === 'true');
if ('disableTextLayer' in params)
PDFJS.disableTextLayer = (params['disableTextLayer'] === 'true');
var sidebarScrollView = document.getElementById('sidebarScrollView');
sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true);
@ -1011,26 +1132,64 @@ window.addEventListener('unload', function webViewerUnload(evt) {
window.scrollTo(0, 0);
}, true);
/**
* Render the next not yet visible page already such that it is
* hopefully ready once the user scrolls to it.
*/
function preDraw() {
var pages = PDFView.pages;
var visible = PDFView.getVisiblePages();
var last = visible[visible.length - 1];
// PageView.id is the actual page number, which is + 1 compared
// to the index in `pages`. That means, pages[last.id] is the next
// PageView instance.
if (pages[last.id] && pages[last.id].drawingRequired()) {
renderingQueue.enqueueDraw(pages[last.id]);
return;
}
// If there is nothing to draw on the next page, maybe the user
// is scrolling up, so, let's try to render the next page *before*
// the first visible page
if (pages[visible[0].id - 2]) {
renderingQueue.enqueueDraw(pages[visible[0].id - 2]);
}
}
function updateViewarea() {
var visiblePages = PDFView.getVisiblePages();
var pageToDraw;
for (var i = 0; i < visiblePages.length; i++) {
var page = visiblePages[i];
renderingQueue.enqueueDraw(PDFView.pages[page.id - 1]);
var pageObj = PDFView.pages[page.id - 1];
pageToDraw |= pageObj.drawingRequired();
renderingQueue.enqueueDraw(pageObj);
}
if (!visiblePages.length)
return;
// If there is no need to draw a page that is currenlty visible, preDraw the
// next page the user might scroll to.
if (!pageToDraw) {
preDraw();
}
updateViewarea.inProgress = true; // used in "set page"
var currentId = PDFView.page;
var firstPage = visiblePages[0];
PDFView.page = firstPage.id;
updateViewarea.inProgress = false;
var currentScale = PDFView.currentScale;
var currentScaleValue = PDFView.currentScaleValue;
var normalizedScaleValue = currentScaleValue == currentScale ?
currentScale * 100 : currentScaleValue;
var kViewerTopMargin = 52;
var pageNumber = firstPage.id;
var pdfOpenParams = '#page=' + pageNumber;
pdfOpenParams += '&zoom=' + Math.round(PDFView.currentScale * 100);
pdfOpenParams += '&zoom=' + normalizedScaleValue;
var currentPage = PDFView.pages[pageNumber - 1];
var topLeft = currentPage.getPagePoint(window.pageXOffset,
window.pageYOffset - firstPage.y - kViewerTopMargin);
@ -1039,7 +1198,7 @@ function updateViewarea() {
var store = PDFView.store;
store.set('exists', true);
store.set('page', pageNumber);
store.set('zoom', Math.round(PDFView.currentScale * 100));
store.set('zoom', normalizedScaleValue);
store.set('scrollLeft', Math.round(topLeft.x));
store.set('scrollTop', Math.round(topLeft.y));
@ -1075,7 +1234,8 @@ window.addEventListener('webkitTransitionEnd', updateThumbViewArea, true);
window.addEventListener('resize', function webViewerResize(evt) {
if (document.getElementById('pageWidthOption').selected ||
document.getElementById('pageFitOption').selected)
document.getElementById('pageFitOption').selected ||
document.getElementById('pageAutoOption').selected)
PDFView.parseScale(document.getElementById('scaleSelect').value);
updateViewarea();
});
@ -1112,20 +1272,9 @@ window.addEventListener('change', function webViewerChange(evt) {
document.getElementById('download').setAttribute('hidden', 'true');
}, true);
window.addEventListener('scalechange', function scalechange(evt) {
var customScaleOption = document.getElementById('customScaleOption');
customScaleOption.selected = false;
if (!evt.resetAutoSettings &&
(document.getElementById('pageWidthOption').selected ||
document.getElementById('pageFitOption').selected)) {
updateViewarea();
return;
}
function selectScaleOption(value) {
var options = document.getElementById('scaleSelect').options;
var predefinedValueFound = false;
var value = '' + evt.scale;
for (var i = 0; i < options.length; i++) {
var option = options[i];
if (option.value != value) {
@ -1135,7 +1284,22 @@ window.addEventListener('scalechange', function scalechange(evt) {
option.selected = true;
predefinedValueFound = true;
}
return predefinedValueFound;
}
window.addEventListener('scalechange', function scalechange(evt) {
var customScaleOption = document.getElementById('customScaleOption');
customScaleOption.selected = false;
if (!evt.resetAutoSettings &&
(document.getElementById('pageWidthOption').selected ||
document.getElementById('pageFitOption').selected ||
document.getElementById('pageAutoOption').selected)) {
updateViewarea();
return;
}
var predefinedValueFound = selectScaleOption('' + evt.scale);
if (!predefinedValueFound) {
customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%';
customScaleOption.selected = true;