Merge branch 'master' of github.com:xavier114fch/pdf.js

This commit is contained in:
Xavier Fung 2012-07-12 16:43:50 +08:00
commit 45fb395d38
32 changed files with 2041 additions and 356 deletions

View File

@ -25,6 +25,7 @@
<script type="text/javascript" src="../../src/worker.js"></script> <script type="text/javascript" src="../../src/worker.js"></script>
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script> <script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
<script type="text/javascript" src="../../src/jpx.js"></script> <script type="text/javascript" src="../../src/jpx.js"></script>
<script type="text/javascript" src="../../src/jbig2.js"></script>
<script type="text/javascript"> <script type="text/javascript">
// Specify the main script used to create a new PDF.JS web worker. // Specify the main script used to create a new PDF.JS web worker.

View File

@ -25,6 +25,7 @@
<script type="text/javascript" src="../../src/worker.js"></script> <script type="text/javascript" src="../../src/worker.js"></script>
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script> <script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
<script type="text/javascript" src="../../src/jpx.js"></script> <script type="text/javascript" src="../../src/jpx.js"></script>
<script type="text/javascript" src="../../src/jbig2.js"></script>
<script type="text/javascript"> <script type="text/javascript">
// Specify the main script used to create a new PDF.JS web worker. // Specify the main script used to create a new PDF.JS web worker.

View File

@ -26,6 +26,16 @@
<em:maxVersion>2.12a1</em:maxVersion> <em:maxVersion>2.12a1</em:maxVersion>
</Description> </Description>
</em:targetApplication> </em:targetApplication>
<!-- Android -->
<em:targetApplication>
<Description>
<em:id>{aa3c5121-dab2-40e2-81ca-7ea25febc110}</em:id>
<em:minVersion>11.0</em:minVersion>
<em:maxVersion>16.0a1</em:maxVersion>
</Description>
</em:targetApplication>
<em:bootstrap>true</em:bootstrap> <em:bootstrap>true</em:bootstrap>
<em:creator>Mozilla</em:creator> <em:creator>Mozilla</em:creator>
<em:description>Uses HTML5 to display PDF files directly in Firefox.</em:description> <em:description>Uses HTML5 to display PDF files directly in Firefox.</em:description>

View File

@ -78,8 +78,6 @@ page_scale_auto=Automatic Zoom
page_scale_actual=Actual Size page_scale_actual=Actual Size
# Loading indicator messages # Loading indicator messages
# LOCALIZATION NOTE (error_line): "{{percent}}" will be replaced with a percentage
loading=Loading… {{percent}}%
loading_error_indicator=Error loading_error_indicator=Error
loading_error=An error occurred while loading the PDF. loading_error=An error occurred while loading the PDF.

8
l10n/es/metadata.inc Normal file
View File

@ -0,0 +1,8 @@
<em:localized>
<Description>
<em:locale>es</em:locale>
<em:name>Visor de PDF</em:name>
<em:description>Usa HTML5 para mostrar archivos PDF directamente en Firefox.</em:description>
</Description>
</em:localized>

89
l10n/es/viewer.properties Normal file
View File

@ -0,0 +1,89 @@
# Main toolbar buttons (tooltips and alt text for images)
previous.title=Página anterior
previous_label=Anterior
next.title=Página siguiente
next_label=Siguiente
# LOCALIZATION NOTE (page_label, page_of):
# These strings are concatenated to form the "Page: X of Y" string.
# Do not translate "{{pageCount}}", it will be substituted with a number
# representing the total number of pages.
page_label=Página:
page_of=de {{pageCount}}
zoom_out.title=Reducir
zoom_out_label=Reducir
zoom_in.title=Ampliar
zoom_in_label=Ampliar
zoom.title=Ampliación
print.title=Imprimir
print_label=Imprimir
open_file.title=Abrir archivo
open_file_label=Abrir
download.title=Descargar
download_label=Descargar
bookmark.title=Vista actual (copiar o abrir en una ventana nueva)
bookmark_label=Vista actual
# Tooltips and alt text for side panel toolbar buttons
# (the _label strings are alt text for the buttons, the .title strings are
# tooltips)
toggle_slider.title=Alternar deslizador
toggle_slider_label=Alternar deslizador
outline.title=Mostrar esquema del documento
outline_label=Esquema del documento
thumbs.title=Mostrar miniaturas
thumbs_label=Miniaturas
search_panel.title=Buscar en el documento
search_panel_label=Buscar
# Document outline messages
no_outline=No hay un esquema disponible
# Thumbnails panel item (tooltip and alt text for images)
# LOCALIZATION NOTE (thumb_page_title): "{{page}}" will be replaced by the page
# number.
thumb_page_title=Página {{page}}
# LOCALIZATION NOTE (thumb_page_canvas): "{{page}}" will be replaced by the page
# number.
thumb_page_canvas=Miniatura de la página {{page}}
# Search panel button title and messages
search=Buscar
search_terms_not_found=(No encontrado)
# Error panel labels
error_more_info=Más información
error_less_info=Menos información
error_close=Cerrar
# LOCALIZATION NOTE (error_build): "{{build}}" will be replaced by the PDF.JS
# build ID.
error_build=Compilación de PDF.JS: {{build}}
# LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an
# english string describing the error.
error_message=Mensaje: {{message}}
# LOCALIZATION NOTE (error_stack): "{{stack}}" will be replaced with a stack
# trace.
error_stack=Pila: {{stack}}
# LOCALIZATION NOTE (error_file): "{{file}}" will be replaced with a filename
error_file=Archivo: {{file}}
# LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number
error_line=Línea: {{line}}
rendering_error=Ocurrió un error al renderizar la página.
# Predefined zoom values
page_scale_width=Anchura de página
page_scale_fit=Ajustar a la página
page_scale_auto=Ampliación automática
page_scale_actual=Tamaño real
# Loading indicator messages
loading_error_indicator=Error
loading_error=Ocurrió un error al cargar el PDF.
# LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip.
# "{{type}}" will be replaced with an annotation type from a list defined in
# the PDF spec (32000-1:2008 Table 169 Annotation types).
# Some common types are e.g.: "Check", "Text", "Comment", "Note"
text_annotation_type=[Anotación {{type}}]
request_password=El PDF está protegido con una contraseña:

View File

@ -0,0 +1,3 @@
# Chrome notification bar messages and buttons
unsupported_feature=Dit PDF document wordt misschien niet goed getoond.
open_with_different_viewer=Bekijk in ander programma

8
l10n/nl/metadata.inc Normal file
View File

@ -0,0 +1,8 @@
<em:localized>
<Description>
<em:locale>nl</em:locale>
<em:name>PDF Viewer</em:name>
<em:description>Gebruikt HTML5 om PDF bestanden direct in de browser te openen.</em:description>
</Description>
</em:localized>

89
l10n/nl/viewer.properties Normal file
View File

@ -0,0 +1,89 @@
# Main toolbar buttons (tooltips and alt text for images)
previous.title=Vorige pagina
previous_label=Vorige
next.title=Volgende pagina
next_label=Volgende
# LOCALIZATION NOTE (page_label, page_of):
# These strings are concatenated to form the "Page: X of Y" string.
# Do not translate "{{pageCount}}", it will be substituted with a number
# representing the total number of pages.
page_label=Pagina:
page_of=van {{pageCount}}
zoom_out.title=Zoom uit
zoom_out_label=Zoom uit
zoom_in.title=Zoom in
zoom_in_label=Zoom in
zoom.title=Zoom
print.title=Print
print_label=Print
open_file.title=Open bestand
open_file_label=Open
download.title=Download
download_label=Download
bookmark.title=Huidige beeld (kopieer of open in nieuw venster)
bookmark_label=Huidige beeld
# Tooltips and alt text for side panel toolbar buttons
# (the _label strings are alt text for the buttons, the .title strings are
# tooltips)
toggle_slider.title=Zijbalk tonen
toggle_slider_label=Zijbalk tonen
outline.title=Toon document structuur
outline_label=Document structuur
thumbs.title=Toon miniaturen
thumbs_label=Miniaturen
search_panel.title=Doorzoek document
search_panel_label=Zoek
# Document outline messages
no_outline=Geen structuur beschikbaar
# Thumbnails panel item (tooltip and alt text for images)
# LOCALIZATION NOTE (thumb_page_title): "{{page}}" will be replaced by the page
# number.
thumb_page_title=Pagina {{page}}
# LOCALIZATION NOTE (thumb_page_canvas): "{{page}}" will be replaced by the page
# number.
thumb_page_canvas=Miniatuur van pagina {{page}}
# Search panel button title and messages
search=Zoek
search_terms_not_found=(Niet gevonden)
# Error panel labels
error_more_info=Meer informatie
error_less_info=Minder informatie
error_close=Sluiten
# LOCALIZATION NOTE (error_build): "{{build}}" will be replaced by the PDF.JS
# build ID.
error_build=PDF.JS Build: {{build}}
# LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an
# english string describing the error.
error_message=Bericht: {{message}}
# LOCALIZATION NOTE (error_stack): "{{stack}}" will be replaced with a stack
# trace.
error_stack=Stapel: {{stack}}
# LOCALIZATION NOTE (error_file): "{{file}}" will be replaced with a filename
error_file=Bestand: {{file}}
# LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number
error_line=Regel: {{line}}
rendering_error=Er heeft zich een probleem voorgedaan bij het optekenen van de pagina.
# Predefined zoom values
page_scale_width=Paginabreedte
page_scale_fit=Pagina passend
page_scale_auto=Automatische Zoom
page_scale_actual=Werkelijke grootte
# Loading indicator messages
loading_error_indicator=Fout
loading_error=Er heeft zich een fout voorgedaan bij het laden van de PDF.
# LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip.
# "{{type}}" will be replaced with an annotation type from a list defined in
# the PDF spec (32000-1:2008 Table 169 Annotation types).
# Some common types are e.g.: "Check", "Text", "Comment", "Note"
text_annotation_type=[{{type}} Annotation]
request_password=PDF is beveiligd door een wachtwoord:

View File

@ -0,0 +1,3 @@
# Chrome notification bar messages and buttons
unsupported_feature=Denna PDF kanske inte visas korrekt.
open_with_different_viewer=Öppna med annan pdf-visare.

View File

@ -1,45 +1,89 @@
bookmark.title=Aktuell vy (visa eller öppna i nytt fönster) # Main toolbar buttons (tooltips and alt text for images)
previous.title=Föregående sida previous.title=Föregående sida
previous_label=Föregående
next.title=Nästa sida next.title=Nästa sida
print.title=Skriv ut next_label=Nästa
download.title=Ladda ner
# LOCALIZATION NOTE (page_label, page_of):
# These strings are concatenated to form the "Page: X of Y" string.
# Do not translate "{{pageCount}}", it will be substituted with a number
# representing the total number of pages.
page_label=Sida:
page_of=av {{pageCount}}
zoom_out.title=Zooma ut zoom_out.title=Zooma ut
zoom_out_label=Zooma ut
zoom_in.title=Zooma in zoom_in.title=Zooma in
zoom_in_label=Zooma in
zoom.title=Zooma
print.title=Skriv ut
print_label=Skriv ut
open_file.title=Öppna fil
open_file_label=Öppna
download.title=Ladda ner
download_label=Ladda ner
bookmark.title=Aktuell vy (kopiera eller öppna i nytt fönster)
bookmark_label=Aktuell vy
# Tooltips and alt text for side panel toolbar buttons
# (the _label strings are alt text for the buttons, the .title strings are
# tooltips)
toggle_slider.title=Visa/Dölj panel
toggle_slider_label=Visa/Dölj panel
outline.title=Visa dokumentdisposition
outline_label=Dokumentdisposition
thumbs.title=Visa miniatyrer
thumbs_label=Miniatyrer
search_panel.title=Sök i dokumentet
search_panel_label=Sök
# Document outline messages
no_outline=Ingen dokumentdisposition tillgänglig
# Thumbnails panel item (tooltip and alt text for images)
# LOCALIZATION NOTE (thumb_page_title): "{{page}}" will be replaced by the page
# number.
thumb_page_title=Sida {{page}}
# LOCALIZATION NOTE (thumb_page_canvas): "{{page}}" will be replaced by the page
# number.
thumb_page_canvas=Miniatyr av sida {{page}}
# Search panel button title and messages
search=Hitta
search_terms_not_found=(hittades inte)
# Error panel labels
error_more_info=Mer information error_more_info=Mer information
error_less_info=Mindre information error_less_info=Mindre information
error_close=Stäng error_close=Stäng
error_build=PDF.JS bygge: {{build}} # LOCALIZATION NOTE (error_build): "{{build}}" will be replaced by the PDF.JS
# build ID.
error_build=PDF.JS Bygge: {{build}}
# LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an
# english string describing the error.
error_message=Meddelande: {{message}} error_message=Meddelande: {{message}}
# LOCALIZATION NOTE (error_stack): "{{stack}}" will be replaced with a stack
# trace.
error_stack=Stack: {{stack}} error_stack=Stack: {{stack}}
# LOCALIZATION NOTE (error_file): "{{file}}" will be replaced with a filename
error_file=Fil: {{file}} error_file=Fil: {{file}}
# LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number
error_line=Rad: {{line}} error_line=Rad: {{line}}
rendering_error=Ett fel inträffade när sidan renderades.
# Predefined zoom values
page_scale_width=Sidbredd page_scale_width=Sidbredd
page_scale_fit=Passa sida page_scale_fit=Passa sida
page_scale_auto=Automatisk zoom page_scale_auto=Automatisk Zoom
page_scale_actual=Faktisk storlek page_scale_actual=Faktisk storlek
toggle_slider.title=Visa/Dölj panel
thumbs.title=Visa miniatyrer # Loading indicator messages
outline.title=Visa dokumentdisposition
loading=Laddar... {{percent}}%
loading_error_indicator=Fel loading_error_indicator=Fel
loading_error=Ett fel inträffade när PDF dokumentet laddades. loading_error=Ett fel inträffade när PDFen skulle laddas.
rendering_error=Ett fel inträffade när PDF dokumentet renderades.
page_label=Sida: # LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip.
page_of=av {{pageCount}} # "{{type}}" will be replaced with an annotation type from a list defined in
no_outline=Ingen dokumentdisposition tillgänglig # the PDF spec (32000-1:2008 Table 169 Annotation types).
open_file.title=Öppna fil # Some common types are e.g.: "Check", "Text", "Comment", "Note"
text_annotation_type=[{{type}} Annotering] text_annotation_type=[{{type}} Annotering]
toggle_slider_label=Visa/Dölj panel request_password=PDFen är skyddad av lösenord:
thumbs_label=Miniatyrer
outline_label=Disposition
bookmark_label=Aktuell vy
previous_label=Föregående
next_label=Nästa
print_label=Skriv ut
download_label=Ladda ner
zoom_out_label=Zooma ut
zoom_in_label=Zooma in
zoom.title=Zooma
thumb_page_title=Sida {{page}}
thumb_page_canvas=Miniatyr av sida {{page}}
request_password=PDF dokumentet är skyddat av ett lösenord:

View File

@ -166,6 +166,7 @@ target.bundle = function() {
'worker.js', 'worker.js',
'../external/jpgjs/jpg.js', '../external/jpgjs/jpg.js',
'jpx.js', 'jpx.js',
'jbig2.js',
'bidi.js', 'bidi.js',
'metadata.js']; 'metadata.js'];

View File

@ -18,7 +18,9 @@
* @return {Promise} A promise that is resolved with {PDFDocumentProxy} object. * @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
*/ */
PDFJS.getDocument = function getDocument(source) { PDFJS.getDocument = function getDocument(source) {
var url, data, headers, password, parameters = {}; var url, data, headers, password, parameters = {}, workerInitializedPromise,
workerReadyPromise, transport;
if (typeof source === 'string') { if (typeof source === 'string') {
url = source; url = source;
} else if (isArrayBuffer(source)) { } else if (isArrayBuffer(source)) {
@ -37,8 +39,9 @@ PDFJS.getDocument = function getDocument(source) {
'string or a parameter object'); 'string or a parameter object');
} }
var promise = new PDFJS.Promise(); workerInitializedPromise = new PDFJS.Promise();
var transport = new WorkerTransport(promise); workerReadyPromise = new PDFJS.Promise();
transport = new WorkerTransport(workerInitializedPromise, workerReadyPromise);
if (data) { if (data) {
// assuming the data is array, instantiating directly from it // assuming the data is array, instantiating directly from it
transport.sendData(data, parameters); transport.sendData(data, parameters);
@ -48,24 +51,31 @@ PDFJS.getDocument = function getDocument(source) {
{ {
url: url, url: url,
progress: function getPDFProgress(evt) { progress: function getPDFProgress(evt) {
if (evt.lengthComputable) if (evt.lengthComputable) {
promise.progress({ workerReadyPromise.progress({
loaded: evt.loaded, loaded: evt.loaded,
total: evt.total total: evt.total
}); });
}
}, },
error: function getPDFError(e) { error: function getPDFError(e) {
promise.reject('Unexpected server response of ' + workerReadyPromise.reject('Unexpected server response of ' +
e.target.status + '.'); e.target.status + '.');
}, },
headers: headers headers: headers
}, },
function getPDFLoad(data) { function getPDFLoad(data) {
transport.sendData(data, parameters); // sometimes the pdf has finished downloading before the web worker-test
// has finished. In that case the rendering of the final pdf would cause
// errors. We have to wait for the WorkerTransport to finalize worker-
// support detection
workerInitializedPromise.then(function workerInitialized() {
transport.sendData(data, parameters);
});
}); });
} }
return promise; return workerReadyPromise;
}; };
/** /**
@ -234,7 +244,11 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
* { * {
* canvasContext(required): A 2D context of a DOM Canvas object., * canvasContext(required): A 2D context of a DOM Canvas object.,
* textLayer(optional): An object that has beginLayout, endLayout, and * textLayer(optional): An object that has beginLayout, endLayout, and
* appendText functions. * appendText functions.,
* continueCallback(optional): A function that will be called each time
* the rendering is paused. To continue
* rendering call the function that is the
* first argument to the callback.
* }. * }.
* @return {Promise} A promise that is resolved when the page finishes * @return {Promise} A promise that is resolved when the page finishes
* rendering. * rendering.
@ -270,6 +284,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
else else
promise.resolve(); promise.resolve();
}; };
var continueCallback = params.continueCallback;
// Once the operatorList and fonts are loaded, do the actual rendering. // Once the operatorList and fonts are loaded, do the actual rendering.
this.displayReadyPromise.then( this.displayReadyPromise.then(
@ -282,7 +297,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
var gfx = new CanvasGraphics(params.canvasContext, var gfx = new CanvasGraphics(params.canvasContext,
this.objs, params.textLayer); this.objs, params.textLayer);
try { try {
this.display(gfx, params.viewport, complete); this.display(gfx, params.viewport, complete, continueCallback);
} catch (e) { } catch (e) {
complete(e); complete(e);
} }
@ -340,7 +355,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
/** /**
* For internal use only. * For internal use only.
*/ */
display: function PDFPageProxy_display(gfx, viewport, callback) { display: function PDFPageProxy_display(gfx, viewport, callback,
continueCallback) {
var stats = this.stats; var stats = this.stats;
stats.time('Rendering'); stats.time('Rendering');
@ -356,10 +372,16 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
stepper.nextBreakPoint = stepper.getNextBreakPoint(); stepper.nextBreakPoint = stepper.getNextBreakPoint();
} }
var continueWrapper;
if (continueCallback)
continueWrapper = function() { continueCallback(next); }
else
continueWrapper = next;
var self = this; var self = this;
function next() { function next() {
startIdx = startIdx = gfx.executeOperatorList(operatorList, startIdx,
gfx.executeOperatorList(operatorList, startIdx, next, stepper); continueWrapper, stepper);
if (startIdx == length) { if (startIdx == length) {
gfx.endDrawing(); gfx.endDrawing();
stats.timeEnd('Rendering'); stats.timeEnd('Rendering');
@ -367,7 +389,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
if (callback) callback(); if (callback) callback();
} }
} }
next(); continueWrapper();
}, },
/** /**
* @return {Promise} That is resolved with the a {string} that is the text * @return {Promise} That is resolved with the a {string} that is the text
@ -414,8 +436,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
* For internal use only. * For internal use only.
*/ */
var WorkerTransport = (function WorkerTransportClosure() { var WorkerTransport = (function WorkerTransportClosure() {
function WorkerTransport(promise) { function WorkerTransport(workerInitializedPromise, workerReadyPromise) {
this.workerReadyPromise = promise; this.workerReadyPromise = workerReadyPromise;
this.objs = new PDFObjects(); this.objs = new PDFObjects();
this.pageCache = []; this.pageCache = [];
@ -459,6 +481,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
globalScope.PDFJS.disableWorker = true; globalScope.PDFJS.disableWorker = true;
this.setupFakeWorker(); this.setupFakeWorker();
} }
workerInitializedPromise.resolve();
}.bind(this)); }.bind(this));
var testObj = new Uint8Array(1); var testObj = new Uint8Array(1);
@ -474,6 +497,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
// Thus, we fallback to a faked worker. // Thus, we fallback to a faked worker.
globalScope.PDFJS.disableWorker = true; globalScope.PDFJS.disableWorker = true;
this.setupFakeWorker(); this.setupFakeWorker();
workerInitializedPromise.resolve();
} }
WorkerTransport.prototype = { WorkerTransport.prototype = {
destroy: function WorkerTransport_destroy() { destroy: function WorkerTransport_destroy() {

View File

@ -1097,6 +1097,40 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
} }
} }
} }
function rescaleImage(pixels, widthScale, heightScale) {
var scaledWidth = Math.ceil(width / widthScale);
var scaledHeight = Math.ceil(height / heightScale);
var itemsSum = new Uint32Array(scaledWidth * scaledHeight * 4);
var itemsCount = new Uint32Array(scaledWidth * scaledHeight);
for (var i = 0, position = 0; i < height; i++) {
var lineOffset = (0 | (i / heightScale)) * scaledWidth;
for (var j = 0; j < width; j++) {
var countOffset = lineOffset + (0 | (j / widthScale));
var sumOffset = countOffset << 2;
itemsSum[sumOffset] += pixels[position];
itemsSum[sumOffset + 1] += pixels[position + 1];
itemsSum[sumOffset + 2] += pixels[position + 2];
itemsSum[sumOffset + 3] += pixels[position + 3];
itemsCount[countOffset]++;
position += 4;
}
}
var tmpCanvas = createScratchCanvas(scaledWidth, scaledHeight);
var tmpCtx = tmpCanvas.getContext('2d');
var imgData = tmpCtx.getImageData(0, 0, scaledWidth, scaledHeight);
pixels = imgData.data;
for (var i = 0, j = 0, ii = scaledWidth * scaledHeight; i < ii; i++) {
var count = itemsCount[i];
pixels[j] = itemsSum[j] / count;
pixels[j + 1] = itemsSum[j + 1] / count;
pixels[j + 2] = itemsSum[j + 2] / count;
pixels[j + 3] = itemsSum[j + 3] / count;
j += 4;
}
tmpCtx.putImageData(imgData, 0, 0);
return tmpCanvas;
}
this.save(); this.save();
@ -1119,8 +1153,19 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
applyStencilMask(pixels, inverseDecode); applyStencilMask(pixels, inverseDecode);
tmpCtx.putImageData(imgData, 0, 0); var currentTransform = ctx.mozCurrentTransformInverse;
ctx.drawImage(tmpCanvas, 0, -h); var widthScale = Math.max(Math.abs(currentTransform[0]), 1);
var heightScale = Math.max(Math.abs(currentTransform[3]), 1);
if (widthScale >= 2 || heightScale >= 2) {
// canvas does not resize well large images to small -- using simple
// algorithm to perform pre-scaling
tmpCanvas = rescaleImage(imgData.data, widthScale, heightScale);
ctx.scale(widthScale, heightScale);
ctx.drawImage(tmpCanvas, 0, -h / heightScale);
} else {
tmpCtx.putImageData(imgData, 0, 0);
ctx.drawImage(tmpCanvas, 0, -h);
}
this.restore(); this.restore();
}, },

View File

@ -226,8 +226,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
insertDependency([objId]); insertDependency([objId]);
args = [objId, w, h]; args = [objId, w, h];
var softMask = dict.get('SMask', 'IM') || false; var softMask = dict.get('SMask', 'SM') || false;
if (!softMask && image instanceof JpegStream && var mask = dict.get('Mask') || false;
if (!softMask && !mask && image instanceof JpegStream &&
image.isNativelySupported(xref, resources)) { image.isNativelySupported(xref, resources)) {
// These JPEGs don't need any more processing so we can just send it. // These JPEGs don't need any more processing so we can just send it.
fn = 'paintJpegXObject'; fn = 'paintJpegXObject';

View File

@ -532,7 +532,7 @@ var FontLoader = {
// XXX we should have a time-out here too, and maybe fire // XXX we should have a time-out here too, and maybe fire
// pdfjsFontLoadFailed? // pdfjsFontLoadFailed?
var src = '<!DOCTYPE HTML><html><head>'; var src = '<!DOCTYPE HTML><html><head><meta charset="utf-8">';
src += '<style type="text/css">'; src += '<style type="text/css">';
for (var i = 0, ii = rules.length; i < ii; ++i) { for (var i = 0, ii = rules.length; i < ii; ++i) {
src += rules[i]; src += rules[i];
@ -3104,9 +3104,13 @@ var Font = (function FontClosure() {
window.btoa(data) + ');'); window.btoa(data) + ');');
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}'; var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}';
var styleElement = document.createElement('style'); var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
document.documentElement.getElementsByTagName('head')[0].appendChild( if (!styleElement) {
styleElement); styleElement = document.createElement('style');
styleElement.id = 'PDFJS_FONT_STYLE_TAG';
document.documentElement.getElementsByTagName('head')[0].appendChild(
styleElement);
}
var styleSheet = styleElement.sheet; var styleSheet = styleElement.sheet;
styleSheet.insertRule(rule, styleSheet.cssRules.length); styleSheet.insertRule(rule, styleSheet.cssRules.length);
@ -4359,8 +4363,10 @@ var CFFParser = (function CFFParserClosure() {
// DirectWrite does not like CID fonts data. Trying to convert/flatten // DirectWrite does not like CID fonts data. Trying to convert/flatten
// the font data and remove CID properties. // the font data and remove CID properties.
if (cff.fdArray.length !== 1) if (cff.fdArray.length !== 1) {
error('Unable to normalize CID font in CFF data'); warn('Unable to normalize CID font in CFF data -- using font as is');
return cff;
}
var fontDict = cff.fdArray[0]; var fontDict = cff.fdArray[0];
fontDict.setByKey(17, topDict.getByName('CharStrings')); fontDict.setByKey(17, topDict.getByName('CharStrings'));

View File

@ -33,7 +33,7 @@ var PDFImage = (function PDFImageClosure() {
// Clamp the value to the range // Clamp the value to the range
return value < 0 ? 0 : value > max ? max : value; return value < 0 ? 0 : value > max ? max : value;
} }
function PDFImage(xref, res, image, inline, smask) { function PDFImage(xref, res, image, inline, smask, mask) {
this.image = image; this.image = image;
if (image.getParams) { if (image.getParams) {
// JPX/JPEG2000 streams directly contain bits per component // JPX/JPEG2000 streams directly contain bits per component
@ -94,12 +94,10 @@ var PDFImage = (function PDFImageClosure() {
} }
} }
var mask = dict.get('Mask'); if (smask) {
if (mask) {
TODO('masked images');
} else if (smask) {
this.smask = new PDFImage(xref, res, smask, false); this.smask = new PDFImage(xref, res, smask, false);
} else if (mask) {
this.mask = new PDFImage(xref, res, mask, false);
} }
} }
/** /**
@ -110,21 +108,36 @@ var PDFImage = (function PDFImageClosure() {
res, image, inline) { res, image, inline) {
var imageDataPromise = new Promise(); var imageDataPromise = new Promise();
var smaskPromise = new Promise(); var smaskPromise = new Promise();
var maskPromise = new Promise();
// The image data and smask data may not be ready yet, wait till both are // The image data and smask data may not be ready yet, wait till both are
// resolved. // resolved.
Promise.all([imageDataPromise, smaskPromise]).then(function(results) { Promise.all([imageDataPromise, smaskPromise, maskPromise]).then(
var imageData = results[0], smaskData = results[1]; function(results) {
var image = new PDFImage(xref, res, imageData, inline, smaskData); var imageData = results[0], smaskData = results[1], maskData = results[2];
var image = new PDFImage(xref, res, imageData, inline, smaskData,
maskData);
callback(image); callback(image);
}); });
handleImageData(handler, xref, res, image, imageDataPromise); handleImageData(handler, xref, res, image, imageDataPromise);
var smask = image.dict.get('SMask'); var smask = image.dict.get('SMask');
if (smask) var mask = image.dict.get('Mask');
if (smask) {
handleImageData(handler, xref, res, smask, smaskPromise); handleImageData(handler, xref, res, smask, smaskPromise);
else maskPromise.resolve(null);
} else {
smaskPromise.resolve(null); smaskPromise.resolve(null);
if (mask && isStream(mask)) {
handleImageData(handler, xref, res, mask, maskPromise);
} else if (mask) {
TODO('handle color key masking');
maskPromise.resolve(null);
} else {
maskPromise.resolve(null);
}
}
}; };
/** /**
@ -268,6 +281,7 @@ var PDFImage = (function PDFImageClosure() {
}, },
getOpacity: function PDFImage_getOpacity(width, height) { getOpacity: function PDFImage_getOpacity(width, height) {
var smask = this.smask; var smask = this.smask;
var mask = this.mask;
var originalWidth = this.width; var originalWidth = this.width;
var originalHeight = this.height; var originalHeight = this.height;
var buf; var buf;
@ -278,7 +292,20 @@ var PDFImage = (function PDFImageClosure() {
buf = new Uint8Array(sw * sh); buf = new Uint8Array(sw * sh);
smask.fillGrayBuffer(buf); smask.fillGrayBuffer(buf);
if (sw != width || sh != height) if (sw != width || sh != height)
buf = PDFImage.resize(buf, smask.bps, 1, sw, sh, width, height); buf = PDFImage.resize(buf, smask.bpc, 1, sw, sh, width, height);
} else if (mask) {
var sw = mask.width;
var sh = mask.height;
buf = new Uint8Array(sw * sh);
mask.numComps = 1;
mask.fillGrayBuffer(buf);
// Need to invert values in buffer
for (var i = 0, ii = sw * sh; i < ii; ++i)
buf[i] = 255 - buf[i];
if (sw != width || sh != height)
buf = PDFImage.resize(buf, mask.bpc, 1, sw, sh, width, height);
} else { } else {
buf = new Uint8Array(width * height); buf = new Uint8Array(width * height);
for (var i = 0, ii = width * height; i < ii; ++i) for (var i = 0, ii = width * height; i < ii; ++i)

1061
src/jbig2.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -254,8 +254,7 @@ var JpxImage = (function JpxImageClosure() {
cod.selectiveArithmeticCodingBypass || cod.selectiveArithmeticCodingBypass ||
cod.resetContextProbabilities || cod.resetContextProbabilities ||
cod.terminationOnEachCodingPass || cod.terminationOnEachCodingPass ||
cod.verticalyStripe || cod.predictableTermination || cod.verticalyStripe || cod.predictableTermination)
cod.segmentationSymbolUsed)
throw 'Unsupported COD options: ' + uneval(cod); throw 'Unsupported COD options: ' + uneval(cod);
if (context.mainHeader) if (context.mainHeader)
@ -832,7 +831,8 @@ var JpxImage = (function JpxImageClosure() {
return position; return position;
} }
function copyCoefficients(coefficients, x0, y0, width, height, function copyCoefficients(coefficients, x0, y0, width, height,
delta, mb, codeblocks, transformation) { delta, mb, codeblocks, transformation,
segmentationSymbolUsed) {
var r = 0.5; // formula (E-6) var r = 0.5; // formula (E-6)
for (var i = 0, ii = codeblocks.length; i < ii; ++i) { for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
var codeblock = codeblocks[i]; var codeblock = codeblocks[i];
@ -876,6 +876,8 @@ var JpxImage = (function JpxImageClosure() {
break; break;
case 2: case 2:
bitModel.runCleanupPass(); bitModel.runCleanupPass();
if (segmentationSymbolUsed)
bitModel.checkSegmentationSymbol();
break; break;
} }
currentCodingpassType = (currentCodingpassType + 1) % 3; currentCodingpassType = (currentCodingpassType + 1) % 3;
@ -912,6 +914,7 @@ var JpxImage = (function JpxImageClosure() {
var scalarExpounded = quantizationParameters.scalarExpounded; var scalarExpounded = quantizationParameters.scalarExpounded;
var guardBits = quantizationParameters.guardBits; var guardBits = quantizationParameters.guardBits;
var transformation = codingStyleParameters.transformation; var transformation = codingStyleParameters.transformation;
var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
var precision = context.components[c].precision; var precision = context.components[c].precision;
var subbandCoefficients = []; var subbandCoefficients = [];
@ -942,7 +945,8 @@ var JpxImage = (function JpxImageClosure() {
var coefficients = new Float32Array(width * height); var coefficients = new Float32Array(width * height);
copyCoefficients(coefficients, subband.tbx0, subband.tby0, copyCoefficients(coefficients, subband.tbx0, subband.tby0,
width, height, delta, mb, subband.codeblocks, transformation); width, height, delta, mb, subband.codeblocks, transformation,
segmentationSymbolUsed);
subbandCoefficients.push({ subbandCoefficients.push({
width: width, width: width,
@ -1645,6 +1649,14 @@ var JpxImage = (function JpxImageClosure() {
} }
} }
} }
},
checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() {
var decoder = this.decoder;
var cx = this.uniformContext;
var symbol = (decoder.readBit(cx) << 3) | (decoder.readBit(cx) << 2) |
(decoder.readBit(cx) << 1) | decoder.readBit(cx);
if (symbol != 0xA)
throw 'Invalid segmentation symbol';
} }
}; };

View File

@ -253,7 +253,8 @@ var Parser = (function ParserClosure() {
return new RunLengthStream(stream); return new RunLengthStream(stream);
} }
if (name == 'JBIG2Decode') { if (name == 'JBIG2Decode') {
error('JBIG2 image format is not currently supprted.'); var bytes = stream.getBytes(length);
return new Jbig2Stream(bytes, stream.dict);
} }
warn('filter "' + name + '" not supported yet'); warn('filter "' + name + '" not supported yet');
return stream; return stream;

View File

@ -979,6 +979,50 @@ var JpxStream = (function JpxStreamClosure() {
return JpxStream; return JpxStream;
})(); })();
/**
* For JBIG2's we use a library to decode these images and
* the stream behaves like all the other DecodeStreams.
*/
var Jbig2Stream = (function Jbig2StreamClosure() {
function Jbig2Stream(bytes, dict) {
this.dict = dict;
this.bytes = bytes;
DecodeStream.call(this);
}
Jbig2Stream.prototype = Object.create(DecodeStream.prototype);
Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) {
if (this.bufferLength)
return;
var jbig2Image = new Jbig2Image();
var chunks = [], decodeParams = this.dict.get('DecodeParms');
if (decodeParams && decodeParams.has('JBIG2Globals')) {
var globalsStream = decodeParams.get('JBIG2Globals');
var globals = globalsStream.getBytes();
chunks.push({data: globals, start: 0, end: globals.length});
}
chunks.push({data: this.bytes, start: 0, end: this.bytes.length});
var data = jbig2Image.parseChunks(chunks);
var dataLength = data.length;
// JBIG2 had black as 1 and white as 0, inverting the colors
for (var i = 0; i < dataLength; i++)
data[i] ^= 0xFF;
this.buffer = data;
this.bufferLength = dataLength;
};
Jbig2Stream.prototype.getChar = function Jbig2Stream_getChar() {
error('internal error: getChar is not valid on Jbig2Stream');
};
return Jbig2Stream;
})();
var DecryptStream = (function DecryptStreamClosure() { var DecryptStream = (function DecryptStreamClosure() {
function DecryptStream(str, decrypt) { function DecryptStream(str, decrypt) {
this.str = str; this.str = str;

View File

@ -24,6 +24,7 @@ var files = [
'stream.js', 'stream.js',
'worker.js', 'worker.js',
'jpx.js', 'jpx.js',
'jbig2.js',
'bidi.js', 'bidi.js',
'../external/jpgjs/jpg.js' '../external/jpgjs/jpg.js'
]; ];

View File

@ -0,0 +1 @@
http://www.maxims6n.bget.ru/book3/viewer/t4.pdf

View File

@ -0,0 +1 @@
http://www.freepatentsonline.com/pdf/documents/uspt/D661/USD661296/USD661296S1.pdf

View File

@ -589,6 +589,14 @@
"link": true, "link": true,
"type": "eq" "type": "eq"
}, },
{ "id": "issue1810",
"file": "pdfs/issue1810.pdf",
"md5": "b173a9dfb7bf00e1a298c6e8cb95c03e",
"rounds": 1,
"pageLimit": 3,
"link": true,
"type": "eq"
},
{ "id": "issue1597", { "id": "issue1597",
"file": "pdfs/issue1597.pdf", "file": "pdfs/issue1597.pdf",
"md5": "a5ebef467fd6e2fc0aeb56c9eb725ae3", "md5": "a5ebef467fd6e2fc0aeb56c9eb725ae3",
@ -608,5 +616,13 @@
"md5": "cbc1988e4803f647fa83467a85f0e231", "md5": "cbc1988e4803f647fa83467a85f0e231",
"rounds": 1, "rounds": 1,
"type": "eq" "type": "eq"
},
{ "id": "issue1796",
"file": "pdfs/issue1796.pdf",
"md5": "9b9b60dc2a4cc3ea05932785d71304fe",
"rounds": 1,
"pageLimit": 2,
"link": true,
"type": "eq"
} }
] ]

View File

@ -24,6 +24,7 @@
<script type="text/javascript" src="/src/worker.js"></script> <script type="text/javascript" src="/src/worker.js"></script>
<script type="text/javascript" src="/external/jpgjs/jpg.js"></script> <script type="text/javascript" src="/external/jpgjs/jpg.js"></script>
<script type="text/javascript" src="/src/jpx.js"></script> <script type="text/javascript" src="/src/jpx.js"></script>
<script type="text/javascript" src="/src/jbig2.js"></script>
<script type="text/javascript" src="/src/bidi.js"></script> <script type="text/javascript" src="/src/bidi.js"></script>
<script type="text/javascript" src="driver.js"></script> <script type="text/javascript" src="driver.js"></script>

View File

@ -6,6 +6,16 @@
// Checking if the typed arrays are supported // Checking if the typed arrays are supported
(function checkTypedArrayCompatibility() { (function checkTypedArrayCompatibility() {
if (typeof Uint8Array !== 'undefined') { if (typeof Uint8Array !== 'undefined') {
// some mobile versions do not support subarray (e.g. safari 5 / iOS)
if (typeof Uint8Array.prototype.subarray === 'undefined') {
Uint8Array.prototype.subarray = function subarray(start, end) {
return new Uint8Array(this.slice(start, end));
};
Float32Array.prototype.subarray = function subarray(start, end) {
return new Float32Array(this.slice(start, end));
};
}
// some mobile version might not support Float64Array // some mobile version might not support Float64Array
if (typeof Float64Array === 'undefined') if (typeof Float64Array === 'undefined')
window.Float64Array = Float32Array; window.Float64Array = Float32Array;
@ -69,8 +79,17 @@
// Object.defineProperty() ? // Object.defineProperty() ?
(function checkObjectDefinePropertyCompatibility() { (function checkObjectDefinePropertyCompatibility() {
if (typeof Object.defineProperty !== 'undefined') if (typeof Object.defineProperty !== 'undefined') {
return; // some browsers (e.g. safari) cannot use defineProperty() on DOM objects
// and thus the native version is not sufficient
var definePropertyPossible = true;
try {
Object.defineProperty(new Image(), 'id', { value: 'test' });
} catch (e) {
definePropertyPossible = false;
}
if (definePropertyPossible) return;
}
Object.defineProperty = function objectDefineProperty(obj, name, def) { Object.defineProperty = function objectDefineProperty(obj, name, def) {
delete obj[name]; delete obj[name];

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 B

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 503 B

View File

@ -11,7 +11,13 @@ body {
height: 100%; height: 100%;
background-color: #404040; background-color: #404040;
background-image: url(images/texture.png); background-image: url(images/texture.png);
font-family: Segoe UI, Verdana, sans-serif; }
body,
input,
button,
select {
font: message-box;
} }
.hidden { .hidden {
@ -54,19 +60,31 @@ html[dir='rtl'] .innerCenter {
bottom: 0; bottom: 0;
width: 200px; width: 200px;
visibility: hidden; visibility: hidden;
-moz-transition-duration: 200ms;
-moz-transition-timing-function: ease;
-webkit-transition-duration: 200ms; -webkit-transition-duration: 200ms;
-webkit-transition-timing-function: ease; -webkit-transition-timing-function: ease;
-moz-transition-duration: 200ms;
-moz-transition-timing-function: ease;
-ms-transition-duration: 200ms;
-ms-transition-timing-function: ease;
-o-transition-duration: 200ms;
-o-transition-timing-function: ease;
transition-duration: 200ms;
transition-timing-function: ease;
} }
html[dir='ltr'] #sidebarContainer { html[dir='ltr'] #sidebarContainer {
-moz-transition-property: left;
-webkit-transition-property: left; -webkit-transition-property: left;
-moz-transition-property: left;
-ms-transition-property: left;
-o-transition-property: left;
transition-property: left;
left: -200px; left: -200px;
} }
html[dir='rtl'] #sidebarContainer { html[dir='rtl'] #sidebarContainer {
-moz-transition-property: right;
-webkit-transition-property: right; -webkit-transition-property: right;
-ms-transition-property: right;
-o-transition-property: right;
transition-property: right;
right: -200px; right: -200px;
} }
@ -87,19 +105,31 @@ html[dir='rtl'] #outerContainer.sidebarOpen > #sidebarContainer {
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
-moz-transition-duration: 200ms;
-moz-transition-timing-function: ease;
-webkit-transition-duration: 200ms; -webkit-transition-duration: 200ms;
-webkit-transition-timing-function: ease; -webkit-transition-timing-function: ease;
-moz-transition-duration: 200ms;
-moz-transition-timing-function: ease;
-ms-transition-duration: 200ms;
-ms-transition-timing-function: ease;
-o-transition-duration: 200ms;
-o-transition-timing-function: ease;
transition-duration: 200ms;
transition-timing-function: ease;
} }
html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer { html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer {
-moz-transition-property: left;
-webkit-transition-property: left; -webkit-transition-property: left;
-moz-transition-property: left;
-ms-transition-property: left;
-o-transition-property: left;
transition-property: left;
left: 200px; left: 200px;
} }
html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer { html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer {
-moz-transition-property: right;
-webkit-transition-property: right; -webkit-transition-property: right;
-moz-transition-property: right;
-ms-transition-property: right;
-o-transition-property: right;
transition-property: right;
right: 200px; right: 200px;
} }
@ -146,11 +176,17 @@ html[dir='rtl'] #sidebarContent {
#toolbarSidebar { #toolbarSidebar {
width: 200px; width: 200px;
height: 32px; height: 29px;
background-image: url(images/texture.png),
-webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
background-image: url(images/texture.png), background-image: url(images/texture.png),
-moz-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); -moz-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
background-image: url(images/texture.png), background-image: url(images/texture.png),
-webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); -ms-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
background-image: url(images/texture.png),
-o-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
background-image: url(images/texture.png),
linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
box-shadow: inset -2px 0 0 hsla(0,0%,100%,.08), box-shadow: inset -2px 0 0 hsla(0,0%,100%,.08),
inset 0 1px 1px hsla(0,0%,0%,.15), inset 0 1px 1px hsla(0,0%,0%,.15),
inset 0 -1px 0 hsla(0,0%,100%,.05), inset 0 -1px 0 hsla(0,0%,100%,.05),
@ -161,10 +197,16 @@ html[dir='rtl'] #sidebarContent {
#toolbarViewer { #toolbarViewer {
position: relative; position: relative;
height: 32px; height: 32px;
background-image: url(images/texture.png),
-webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
background-image: url(images/texture.png), background-image: url(images/texture.png),
-moz-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); -moz-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
background-image: url(images/texture.png), background-image: url(images/texture.png),
-webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); -ms-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
background-image: url(images/texture.png),
-o-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
background-image: url(images/texture.png),
linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
border-left: 1px solid hsla(0,0%,0%,.5); border-left: 1px solid hsla(0,0%,0%,.5);
box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08), box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08),
inset 0 1px 1px hsla(0,0%,0%,.15), inset 0 1px 1px hsla(0,0%,0%,.15),
@ -242,28 +284,48 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton {
margin-right:0; margin-right:0;
} }
.splitToolbarButton.toggled .toolbarButton {
margin: 0;
}
.splitToolbarButton:hover > .toolbarButton, .splitToolbarButton:hover > .toolbarButton,
.splitToolbarButton:focus > .toolbarButton, .splitToolbarButton:focus > .toolbarButton,
.splitToolbarButton.toggled > .toolbarButton { .splitToolbarButton.toggled > .toolbarButton,
.toolbarButton.textButton {
background-color: hsla(0,0%,0%,.12); background-color: hsla(0,0%,0%,.12);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box; background-clip: padding-box;
border: 1px solid hsla(0,0%,0%,.35); border: 1px solid hsla(0,0%,0%,.35);
border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.15) inset, 0 0 1px hsla(0,0%,100%,.15) inset,
0 1px 0 hsla(0,0%,100%,.05); 0 1px 0 hsla(0,0%,100%,.05);
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: ease;
-webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-property: background-color, border-color, box-shadow;
-webkit-transition-duration: 150ms; -webkit-transition-duration: 150ms;
-webkit-transition-timing-function: ease; -webkit-transition-timing-function: ease;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: ease;
-ms-transition-property: background-color, border-color, box-shadow;
-ms-transition-duration: 150ms;
-ms-transition-timing-function: ease;
-o-transition-property: background-color, border-color, box-shadow;
-o-transition-duration: 150ms;
-o-transition-timing-function: ease;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
} }
.splitToolbarButton > .toolbarButton:hover, .splitToolbarButton > .toolbarButton:hover,
.splitToolbarButton > .toolbarButton:focus, .splitToolbarButton > .toolbarButton:focus,
.dropdownToolbarButton:hover { .dropdownToolbarButton:hover,
.toolbarButton.textButton:hover,
.toolbarButton.textButton:focus {
background-color: hsla(0,0%,0%,.2); background-color: hsla(0,0%,0%,.2);
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.15) inset, 0 0 1px hsla(0,0%,100%,.15) inset,
@ -308,12 +370,21 @@ html[dir='rtl'] .splitToolbarButtonSeparator {
padding: 12px 0; padding: 12px 0;
margin: 0; margin: 0;
box-shadow: 0 0 0 1px hsla(0,0%,100%,.03); box-shadow: 0 0 0 1px hsla(0,0%,100%,.03);
-moz-transition-property: padding;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: ease;
-webkit-transition-property: padding; -webkit-transition-property: padding;
-webkit-transition-duration: 10ms; -webkit-transition-duration: 10ms;
-webkit-transition-timing-function: ease; -webkit-transition-timing-function: ease;
-moz-transition-property: padding;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: ease;
-ms-transition-property: padding;
-ms-transition-duration: 10ms;
-ms-transition-timing-function: ease;
-o-transition-property: padding;
-o-transition-duration: 10ms;
-o-transition-timing-function: ease;
transition-property: padding;
transition-duration: 10ms;
transition-timing-function: ease;
} }
.toolbarButton, .toolbarButton,
@ -325,15 +396,26 @@ html[dir='rtl'] .splitToolbarButtonSeparator {
color: hsl(0,0%,95%); color: hsl(0,0%,95%);
font-size: 12px; font-size: 12px;
line-height: 14px; line-height: 14px;
-moz-user-select:none;
-webkit-user-select:none; -webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
/* Opera does not support user-select, use <... unselectable="on"> instead */
cursor: default; cursor: default;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: ease;
-webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-property: background-color, border-color, box-shadow;
-webkit-transition-duration: 150ms; -webkit-transition-duration: 150ms;
-webkit-transition-timing-function: ease; -webkit-transition-timing-function: ease;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 150ms;
-moz-transition-timing-function: ease;
-ms-transition-property: background-color, border-color, box-shadow;
-ms-transition-duration: 150ms;
-ms-transition-timing-function: ease;
-o-transition-property: background-color, border-color, box-shadow;
-o-transition-duration: 150ms;
-o-transition-timing-function: ease;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease;
} }
html[dir='ltr'] .toolbarButton, html[dir='ltr'] .toolbarButton,
@ -349,8 +431,11 @@ html[dir='rtl'] .dropdownToolbarButton {
.toolbarButton:focus, .toolbarButton:focus,
.dropdownToolbarButton { .dropdownToolbarButton {
background-color: hsla(0,0%,0%,.12); background-color: hsla(0,0%,0%,.12);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box; background-clip: padding-box;
border: 1px solid hsla(0,0%,0%,.35); border: 1px solid hsla(0,0%,0%,.35);
border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
@ -362,35 +447,59 @@ html[dir='rtl'] .dropdownToolbarButton {
.toolbarButton:hover:active, .toolbarButton:hover:active,
.dropdownToolbarButton:hover:active { .dropdownToolbarButton:hover:active {
background-color: hsla(0,0%,0%,.2); background-color: hsla(0,0%,0%,.2);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45); border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45);
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
0 0 1px hsla(0,0%,0%,.2) inset, 0 0 1px hsla(0,0%,0%,.2) inset,
0 1px 0 hsla(0,0%,100%,.05); 0 1px 0 hsla(0,0%,100%,.05);
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: linear;
-webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-property: background-color, border-color, box-shadow;
-webkit-transition-duration: 10ms; -webkit-transition-duration: 10ms;
-webkit-transition-timing-function: linear; -webkit-transition-timing-function: linear;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: linear;
-ms-transition-property: background-color, border-color, box-shadow;
-ms-transition-duration: 10ms;
-ms-transition-timing-function: linear;
-o-transition-property: background-color, border-color, box-shadow;
-o-transition-duration: 10ms;
-o-transition-timing-function: linear;
transition-property: background-color, border-color, box-shadow;
transition-duration: 10ms;
transition-timing-function: linear;
} }
.toolbarButton.toggled, .toolbarButton.toggled,
.splitToolbarButton.toggled > .toolbarButton.toggled { .splitToolbarButton.toggled > .toolbarButton.toggled {
background-color: hsla(0,0%,0%,.3); background-color: hsla(0,0%,0%,.3);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5); border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5);
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
0 0 1px hsla(0,0%,0%,.2) inset, 0 0 1px hsla(0,0%,0%,.2) inset,
0 1px 0 hsla(0,0%,100%,.05); 0 1px 0 hsla(0,0%,100%,.05);
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: linear;
-webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-property: background-color, border-color, box-shadow;
-webkit-transition-duration: 10ms; -webkit-transition-duration: 10ms;
-webkit-transition-timing-function: linear; -webkit-transition-timing-function: linear;
-moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 10ms;
-moz-transition-timing-function: linear;
-ms-transition-property: background-color, border-color, box-shadow;
-ms-transition-duration: 10ms;
-ms-transition-timing-function: linear;
-o-transition-property: background-color, border-color, box-shadow;
-o-transition-duration: 10ms;
-o-transition-timing-function: linear;
transition-property: background-color, border-color, box-shadow;
transition-duration: 10ms;
transition-timing-function: linear;
} }
.toolbarButton.toggled:hover:active, .toolbarButton.toggled:hover:active,
@ -417,8 +526,8 @@ html[dir='rtl'] .dropdownToolbarButton {
} }
.dropdownToolbarButton > select { .dropdownToolbarButton > select {
-moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */
min-width: 140px; min-width: 140px;
font-size: 12px; font-size: 12px;
color: hsl(0,0%,95%); color: hsl(0,0%,95%);
@ -460,8 +569,8 @@ html[dir='rtl'] .toolbarButton:first-child {
} }
.toolbarButtonFlexibleSpacer { .toolbarButtonFlexibleSpacer {
-moz-box-flex: 1;
-webkit-box-flex: 1; -webkit-box-flex: 1;
-moz-box-flex: 1;
min-width: 30px; min-width: 30px;
} }
@ -516,8 +625,8 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
} }
.toolbarButton.bookmark { .toolbarButton.bookmark {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
margin-top: 3px; margin-top: 3px;
padding-top: 4px; padding-top: 4px;
@ -544,8 +653,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
.toolbarField { .toolbarField {
min-width: 16px;
width: 32px;
padding: 3px 6px; padding: 3px 6px;
margin: 4px 0 4px 0; margin: 4px 0 4px 0;
border: 1px solid transparent; border: 1px solid transparent;
@ -560,7 +667,6 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
color: hsl(0,0%,95%); color: hsl(0,0%,95%);
font-size: 12px; font-size: 12px;
line-height: 14px; line-height: 14px;
text-align: right;
outline-style: none; outline-style: none;
-moz-transition-property: background-color, border-color, box-shadow; -moz-transition-property: background-color, border-color, box-shadow;
-moz-transition-duration: 150ms; -moz-transition-duration: 150ms;
@ -568,6 +674,8 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
} }
.toolbarField.pageNumber { .toolbarField.pageNumber {
min-width: 16px;
text-align: right;
width: 40px; width: 40px;
} }
@ -597,8 +705,8 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
font-size: 12px; font-size: 12px;
line-height: 14px; line-height: 14px;
text-align: left; text-align: left;
-moz-user-select:none;
-webkit-user-select:none; -webkit-user-select:none;
-moz-user-select:none;
cursor: default; cursor: default;
} }
@ -674,17 +782,19 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
bottom: 0; bottom: 0;
padding: 4px 4px 0; padding: 4px 4px 0;
overflow: auto; overflow: auto;
-moz-user-select:none;
-webkit-user-select:none; -webkit-user-select:none;
-moz-user-select:none;
} }
.outlineItem > .outlineItems { .outlineItem > .outlineItems {
margin-left: 20px; margin-left: 20px;
} }
.outlineItem > a { .outlineItem > a,
#searchResults > a {
text-decoration: none; text-decoration: none;
display: block; display: inline-block;
min-width: 95%;
height: 20px; height: 20px;
padding: 2px 0 0 10px; padding: 2px 0 0 10px;
margin-bottom: 1px; margin-bottom: 1px;
@ -697,7 +807,8 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
white-space: nowrap; white-space: nowrap;
} }
.outlineItem > a:hover { .outlineItem > a:hover,
#searchResults > a:hover {
background-color: hsla(0,0%,100%,.02); background-color: hsla(0,0%,100%,.02);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box; background-clip: padding-box;
@ -707,6 +818,23 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
color: hsla(0,0%,100%,.9); color: hsla(0,0%,100%,.9);
} }
.outlineItem.selected {
background-color: hsla(0,0%,100%,.08);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.1) inset,
0 0 1px hsla(0,0%,0%,.2);
color: hsla(0,0%,100%,1);
}
.noOutline,
.noResults {
font-size: 12px;
color: hsla(0,0%,100%,.8);
font-style: italic;
}
#searchScrollView { #searchScrollView {
position: absolute; position: absolute;
top: 10px; top: 10px;
@ -723,27 +851,26 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
} }
#searchToolbar > input { #searchToolbar > input {
margin-left: 8px; margin-left: 4px;
width: 130px; width: 124px;
}
#searchToolbar button {
width: auto;
margin: 0;
padding: 0 6px;
height: 22px;
} }
#searchResults { #searchResults {
overflow: auto; overflow: auto;
background-color: #fff;
position: absolute; position: absolute;
top: 30px; top: 30px;
bottom: 0px; bottom: 0px;
left: 0px; left: 0px;
right: 0; right: 0;
padding: 4px 4px 0;
font-size: smaller; font-size: smaller;
opacity: 0.7;
}
#searchResults a {
display: block;
white-space: pre;
text-decoration: none;
color: black;
} }
#sidebarControls { #sidebarControls {
@ -754,24 +881,6 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
bottom: 35px; bottom: 35px;
} }
.outlineItem.selected {
background-color: hsla(0,0%,100%,.08);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-clip: padding-box;
box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
0 0 1px hsla(0,0%,100%,.1) inset,
0 0 1px hsla(0,0%,0%,.2);
color: hsla(0,0%,100%,1);
}
.noOutline {
font-size: 12px;
color: hsla(0,0%,100%,.8);
font-style: italic;
}
canvas { canvas {
margin: auto; margin: auto;
display: block; display: block;
@ -784,9 +893,9 @@ canvas {
margin: 10px auto; margin: 10px auto;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
box-shadow: 0px 4px 10px #000;
-moz-box-shadow: 0px 4px 10px #000;
-webkit-box-shadow: 0px 4px 10px #000; -webkit-box-shadow: 0px 4px 10px #000;
-moz-box-shadow: 0px 4px 10px #000;
box-shadow: 0px 4px 10px #000;
background-color: white; background-color: white;
} }
@ -798,9 +907,9 @@ canvas {
.page > a:hover { .page > a:hover {
opacity: 0.2; opacity: 0.2;
background: #ff0; background: #ff0;
box-shadow: 0px 2px 10px #ff0;
-moz-box-shadow: 0px 2px 10px #ff0;
-webkit-box-shadow: 0px 2px 10px #ff0; -webkit-box-shadow: 0px 2px 10px #ff0;
-moz-box-shadow: 0px 2px 10px #ff0;
box-shadow: 0px 2px 10px #ff0;
} }
.loadingIcon { .loadingIcon {
@ -814,23 +923,33 @@ canvas {
} }
#loadingBox { #loadingBox {
margin: 100px 0; position: absolute;
top: 50%;
margin-top: -25px;
left: 0;
right: 0;
text-align: center; text-align: center;
color: #ddd; color: #ddd;
font-size: 14px; font-size: 14px;
} }
#loadingBar { #loadingBar {
background-color: #333;
display: inline-block; display: inline-block;
border: 1px solid black;
clear: both; clear: both;
margin: 0px; margin: 0px;
margin-top: 5px; margin-top: 5px;
line-height: 0; line-height: 0;
border-radius: 4px; border-radius: 2px;
width: 200px; width: 200px;
height: 25px; height: 25px;
background-color: hsla(0,0%,0%,.3);
background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
border: 1px solid #000;
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
0 0 1px hsla(0,0%,0%,.2) inset,
0 0 1px 1px rgba(255, 255, 255, 0.1);
} }
#loadingBar .progress { #loadingBar .progress {
@ -838,23 +957,23 @@ canvas {
float: left; float: left;
background: #666; background: #666;
background: -moz-linear-gradient(top, #999 0%, #666 50%, #999 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2b2b2), color-stop(100%,#898989));
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#999), color-stop(50%,#666), color-stop(100%,#999)); background: -webkit-linear-gradient(top, #b2b2b2 0%,#898989 100%);
background: -webkit-linear-gradient(top, #999 0%,#666 50%,#999 100%); background: -moz-linear-gradient(top, #b2b2b2 0%,#898989 100%);
background: -o-linear-gradient(top, #999 0%,#666 50%,#999 100%); background: -ms-linear-gradient(top, #b2b2b2 0%,#898989 100%);
background: -ms-linear-gradient(top, #999 0%,#666 50%,#999 100%); background: -o-linear-gradient(top, #b2b2b2 0%,#898989 100%);
background: linear-gradient(top, #999 0%,#666 50%,#999 100%); background: linear-gradient(top, #b2b2b2 0%,#898989 100%);
border-top-left-radius: 3px; border-top-left-radius: 2px;
border-bottom-left-radius: 3px; border-bottom-left-radius: 2px;
width: 0%; width: 0%;
height: 100%; height: 100%;
} }
#loadingBar .progress.full { #loadingBar .progress.full {
border-top-right-radius: 3px; border-top-right-radius: 2px;
border-bottom-right-radius: 3px; border-bottom-right-radius: 2px;
} }
.textLayer { .textLayer {
@ -896,9 +1015,9 @@ canvas {
padding: 0.2em; padding: 0.2em;
max-width: 20em; max-width: 20em;
background-color: #F1E47B; background-color: #F1E47B;
box-shadow: 0px 2px 10px #333;
-moz-box-shadow: 0px 2px 10px #333;
-webkit-box-shadow: 0px 2px 10px #333; -webkit-box-shadow: 0px 2px 10px #333;
-moz-box-shadow: 0px 2px 10px #333;
box-shadow: 0px 2px 10px #333;
} }
.annotComment > div > h1 { .annotComment > div > h1 {
@ -1008,9 +1127,9 @@ canvas {
.page { .page {
float: left; float: left;
display: none; display: none;
box-shadow: none;
-moz-box-shadow: none;
-webkit-box-shadow: none; -webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
} }
.page[data-loaded] { .page[data-loaded] {

View File

@ -35,6 +35,7 @@
<script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE --> <script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE --> <script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/jpx.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE --> <script type="text/javascript" src="../src/jpx.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/jbig2.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/bidi.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE --> <script type="text/javascript" src="../src/bidi.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE_CORE --> <script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="debugger.js"></script> <script type="text/javascript" src="debugger.js"></script>
@ -45,7 +46,7 @@
<div id="outerContainer"> <div id="outerContainer">
<div id="sidebarContainer"> <div id="sidebarContainer">
<div id="toolbarSidebar"> <div id="toolbarSidebar" class="splitToolbarButton toggled">
<button id="viewThumbnail" class="toolbarButton group toggled" title="Show Thumbnails" onclick="PDFView.switchSidebarView('thumbs')" tabindex="1" data-l10n-id="thumbs"> <button id="viewThumbnail" class="toolbarButton group toggled" title="Show Thumbnails" onclick="PDFView.switchSidebarView('thumbs')" tabindex="1" data-l10n-id="thumbs">
<span data-l10n-id="thumbs_label">Thumbnails</span> <span data-l10n-id="thumbs_label">Thumbnails</span>
</button> </button>
@ -63,8 +64,8 @@
</div> </div>
<div id="searchView" class="hidden"> <div id="searchView" class="hidden">
<div id="searchToolbar"> <div id="searchToolbar">
<input id="searchTermsInput" onkeydown='if (event.keyCode == 13) PDFView.search()'> <input id="searchTermsInput" class="toolbarField" onkeydown='if (event.keyCode == 13) PDFView.search()'>
<button id="searchButton" onclick='PDFView.search()' data-l10n-id="search">Find</button> <button id="searchButton" class="textButton toolbarButton" onclick='PDFView.search()' data-l10n-id="search">Find</button>
</div> </div>
<div id="searchResults"></div> <div id="searchResults"></div>
</div> </div>
@ -150,8 +151,8 @@
</div> </div>
<div id="loadingBox"> <div id="loadingBox">
<div id="loading" data-l10n-id="loading" data-l10n-args='{"percent": 0}'>Loading... 0%</div> <div id="loading"></div>
<div id="loadingBar"><div class="progress"></div></div> <div id="loadingBar"><div class="progress"></div></div>
</div> </div>
<div id="errorWrapper" hidden='true'> <div id="errorWrapper" hidden='true'>

View File

@ -14,6 +14,13 @@ var kMinScale = 0.25;
var kMaxScale = 4.0; var kMaxScale = 4.0;
var kImageDirectory = './images/'; var kImageDirectory = './images/';
var kSettingsMemory = 20; var kSettingsMemory = 20;
var RenderingStates = {
INITIAL: 0,
RUNNING: 1,
PAUSED: 2,
FINISHED: 3
};
var mozL10n = document.mozL10n || document.webL10n; var mozL10n = document.mozL10n || document.webL10n;
@ -83,36 +90,6 @@ var ProgressBar = (function ProgressBarClosure() {
return ProgressBar; return ProgressBar;
})(); })();
var RenderingQueue = (function RenderingQueueClosure() {
function RenderingQueue() {
this.items = [];
}
RenderingQueue.prototype = {
enqueueDraw: function RenderingQueueEnqueueDraw(item) {
if (!item.drawingRequired())
return; // as no redraw required, no need for queueing.
this.items.push(item);
if (this.items.length > 1)
return; // not first item
item.draw(this.continueExecution.bind(this));
},
continueExecution: function RenderingQueueContinueExecution() {
var item = this.items.shift();
if (this.items.length == 0)
return; // queue is empty
item = this.items[0];
item.draw(this.continueExecution.bind(this));
}
};
return RenderingQueue;
})();
var FirefoxCom = (function FirefoxComClosure() { var FirefoxCom = (function FirefoxComClosure() {
return { return {
/** /**
@ -246,7 +223,6 @@ var Settings = (function SettingsClosure() {
})(); })();
var cache = new Cache(kCacheSize); var cache = new Cache(kCacheSize);
var renderingQueue = new RenderingQueue();
var currentPageNumber = 1; var currentPageNumber = 1;
var PDFView = { var PDFView = {
@ -258,16 +234,48 @@ var PDFView = {
startedTextExtraction: false, startedTextExtraction: false,
pageText: [], pageText: [],
container: null, container: null,
thumbnailContainer: null,
initialized: false, initialized: false,
fellback: false, fellback: false,
pdfDocument: null, pdfDocument: null,
sidebarOpen: false,
pageViewScroll: null,
thumbnailViewScroll: null,
// called once when the document is loaded // called once when the document is loaded
initialize: function pdfViewInitialize() { initialize: function pdfViewInitialize() {
this.container = document.getElementById('viewerContainer'); var container = this.container = document.getElementById('viewerContainer');
this.pageViewScroll = {};
this.watchScroll(container, this.pageViewScroll, updateViewarea);
var thumbnailContainer = this.thumbnailContainer =
document.getElementById('thumbnailView');
this.thumbnailViewScroll = {};
this.watchScroll(thumbnailContainer, this.thumbnailViewScroll,
this.renderHighestPriority.bind(this));
this.initialized = true; this.initialized = true;
}, },
setScale: function pdfViewSetScale(val, resetAutoSettings) { // Helper function to keep track whether a div was scrolled up or down and
// then call a callback.
watchScroll: function pdfViewWatchScroll(viewAreaElement, state, callback) {
state.down = true;
state.lastY = viewAreaElement.scrollTop;
viewAreaElement.addEventListener('scroll', function webViewerScroll(evt) {
var currentY = viewAreaElement.scrollTop;
var lastY = state.lastY;
if (currentY > lastY)
state.down = true;
else if (currentY < lastY)
state.down = false;
// else do nothing and use previous value
state.lastY = currentY;
callback();
}, true);
},
setScale: function pdfViewSetScale(val, resetAutoSettings, noScroll) {
if (val == this.currentScale) if (val == this.currentScale)
return; return;
@ -275,7 +283,7 @@ var PDFView = {
for (var i = 0; i < pages.length; i++) for (var i = 0; i < pages.length; i++)
pages[i].update(val * kCssUnits); pages[i].update(val * kCssUnits);
if (this.currentScale != val) if (!noScroll && this.currentScale != val)
this.pages[this.page - 1].scrollIntoView(); this.pages[this.page - 1].scrollIntoView();
this.currentScale = val; this.currentScale = val;
@ -286,14 +294,14 @@ var PDFView = {
window.dispatchEvent(event); window.dispatchEvent(event);
}, },
parseScale: function pdfViewParseScale(value, resetAutoSettings) { parseScale: function pdfViewParseScale(value, resetAutoSettings, noScroll) {
if ('custom' == value) if ('custom' == value)
return; return;
var scale = parseFloat(value); var scale = parseFloat(value);
this.currentScaleValue = value; this.currentScaleValue = value;
if (scale) { if (scale) {
this.setScale(scale, true); this.setScale(scale, true, noScroll);
return; return;
} }
@ -305,22 +313,22 @@ var PDFView = {
currentPage.height * currentPage.scale / kCssUnits; currentPage.height * currentPage.scale / kCssUnits;
switch (value) { switch (value) {
case 'page-actual': case 'page-actual':
this.setScale(1, resetAutoSettings); scale = 1;
break; break;
case 'page-width': case 'page-width':
this.setScale(pageWidthScale, resetAutoSettings); scale = pageWidthScale;
break; break;
case 'page-height': case 'page-height':
this.setScale(pageHeightScale, resetAutoSettings); scale = pageHeightScale;
break; break;
case 'page-fit': case 'page-fit':
this.setScale( scale = Math.min(pageWidthScale, pageHeightScale);
Math.min(pageWidthScale, pageHeightScale), resetAutoSettings);
break; break;
case 'auto': case 'auto':
this.setScale(Math.min(1.0, pageWidthScale), resetAutoSettings); scale = Math.min(1.0, pageWidthScale);
break; break;
} }
this.setScale(scale, resetAutoSettings, noScroll);
selectScaleOption(value); selectScaleOption(value);
}, },
@ -394,7 +402,7 @@ var PDFView = {
self.loading = false; self.loading = false;
}, },
function getDocumentError(message, exception) { function getDocumentError(message, exception) {
if (exception.name === 'PasswordException') { if (exception && exception.name === 'PasswordException') {
if (exception.code === 'needpassword') { if (exception.code === 'needpassword') {
var promptString = mozL10n.get('request_password', null, var promptString = mozL10n.get('request_password', null,
'PDF is protected by a password:'); 'PDF is protected by a password:');
@ -598,10 +606,6 @@ var PDFView = {
progress: function pdfViewProgress(level) { progress: function pdfViewProgress(level) {
var percent = Math.round(level * 100); var percent = Math.round(level * 100);
var loadingIndicator = document.getElementById('loading');
loadingIndicator.textContent = mozL10n.get('loading', {percent: percent},
'Loading... {{percent}}%');
PDFView.loadingBar.percent = percent; PDFView.loadingBar.percent = percent;
}, },
@ -610,7 +614,6 @@ var PDFView = {
// when page is painted, using the image as thumbnail base // when page is painted, using the image as thumbnail base
pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() { pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
thumbnailView.setImage(pageView.canvas); thumbnailView.setImage(pageView.canvas);
preDraw();
}; };
} }
@ -621,6 +624,8 @@ var PDFView = {
var loadingBox = document.getElementById('loadingBox'); var loadingBox = document.getElementById('loadingBox');
loadingBox.setAttribute('hidden', 'true'); loadingBox.setAttribute('hidden', 'true');
var loadingIndicator = document.getElementById('loading');
loadingIndicator.textContent = '';
var thumbsView = document.getElementById('thumbnailView'); var thumbsView = document.getElementById('thumbnailView');
thumbsView.parentNode.scrollTop = 0; thumbsView.parentNode.scrollTop = 0;
@ -735,6 +740,88 @@ var PDFView = {
} }
}, },
renderHighestPriority: function pdfViewRenderHighestPriority() {
// Pages have a higher priority than thumbnails, so check them first.
var visiblePages = this.getVisiblePages();
var pageView = this.getHighestPriority(visiblePages, this.pages,
this.pageViewScroll.down);
if (pageView) {
this.renderView(pageView, 'page');
return;
}
// No pages needed rendering so check thumbnails.
if (this.sidebarOpen) {
var visibleThumbs = this.getVisibleThumbs();
var thumbView = this.getHighestPriority(visibleThumbs,
this.thumbnails,
this.thumbnailViewScroll.down);
if (thumbView)
this.renderView(thumbView, 'thumbnail');
}
},
getHighestPriority: function pdfViewGetHighestPriority(visibleViews, views,
scrolledDown) {
// The state has changed figure out which page has the highest priority to
// render next (if any).
// Priority:
// 1 visible pages
// 2 if last scrolled down page after the visible pages
// 2 if last scrolled up page before the visible pages
var numVisible = visibleViews.length;
if (numVisible === 0) {
info('No visible views.');
return false;
}
for (var i = 0; i < numVisible; ++i) {
var view = visibleViews[i].view;
if (!this.isViewFinshed(view))
return view;
}
// All the visible views have rendered, try to render next/previous pages.
if (scrolledDown) {
var lastVisible = visibleViews[visibleViews.length - 1];
var nextPageIndex = lastVisible.id;
// ID's start at 1 so no need to add 1.
if (views[nextPageIndex] && !this.isViewFinshed(views[nextPageIndex]))
return views[nextPageIndex];
} else {
var previousPageIndex = visibleViews[0].id - 2;
if (views[previousPageIndex] &&
!this.isViewFinshed(views[previousPageIndex]))
return views[previousPageIndex];
}
// Everything that needs to be rendered has been.
return false;
},
isViewFinshed: function pdfViewNeedsRendering(view) {
return view.renderingState === RenderingStates.FINISHED;
},
// Render a page or thumbnail view. This calls the appropriate function based
// on the views state. If the view is already rendered it will return false.
renderView: function pdfViewRender(view, type) {
var state = view.renderingState;
switch (state) {
case RenderingStates.FINISHED:
return false;
case RenderingStates.PAUSED:
PDFView.highestPriorityPage = type + view.id;
view.resume();
break;
case RenderingStates.RUNNING:
PDFView.highestPriorityPage = type + view.id;
break;
case RenderingStates.INITIAL:
PDFView.highestPriorityPage = type + view.id;
view.draw(this.renderHighestPriority.bind(this));
break;
}
return true;
},
search: function pdfViewStartSearch() { search: function pdfViewStartSearch() {
// Limit this function to run every <SEARCH_TIMEOUT>ms. // Limit this function to run every <SEARCH_TIMEOUT>ms.
var SEARCH_TIMEOUT = 250; var SEARCH_TIMEOUT = 250;
@ -792,8 +879,12 @@ var PDFView = {
pageFound = true; pageFound = true;
} }
if (!pageFound) { if (!pageFound) {
searchResults.textContent = mozL10n.get('search_terms_not_found', null, searchResults.textContent = '';
var noResults = document.createElement('div');
noResults.classList.add('noResults');
noResults.textContent = mozL10n.get('search_terms_not_found', null,
'(Not found)'); '(Not found)');
searchResults.appendChild(noResults);
} }
}, },
@ -854,7 +945,7 @@ var PDFView = {
outlineView.classList.add('hidden'); outlineView.classList.add('hidden');
searchView.classList.add('hidden'); searchView.classList.add('hidden');
updateThumbViewArea(); PDFView.renderHighestPriority();
break; break;
case 'outline': case 'outline':
@ -904,63 +995,39 @@ var PDFView = {
}, },
getVisiblePages: function pdfViewGetVisiblePages() { getVisiblePages: function pdfViewGetVisiblePages() {
var pages = this.pages; return this.getVisibleElements(this.container,
var kBottomMargin = 10; this.pages);
var kTopPadding = 30;
var visiblePages = [];
var currentHeight = kTopPadding + kBottomMargin;
var container = this.container;
// Add 1px to the scrolltop to give a little wiggle room if the math is off,
// this won't be needed if we calc current page number based off the middle
// of the screen instead of the top.
var containerTop = container.scrollTop + 1;
for (var i = 1; i <= pages.length; ++i) {
var page = pages[i - 1];
var pageHeight = page.height + kBottomMargin;
if (currentHeight + pageHeight > containerTop)
break;
currentHeight += pageHeight;
}
var containerBottom = containerTop + container.clientHeight;
for (; i <= pages.length && currentHeight < containerBottom; ++i) {
var singlePage = pages[i - 1];
visiblePages.push({ id: singlePage.id, y: currentHeight,
view: singlePage });
currentHeight += page.height + kBottomMargin;
}
return visiblePages;
}, },
getVisibleThumbs: function pdfViewGetVisibleThumbs() { getVisibleThumbs: function pdfViewGetVisibleThumbs() {
var thumbs = this.thumbnails; return this.getVisibleElements(this.thumbnailContainer,
var kBottomMargin = 15; this.thumbnails);
var visibleThumbs = []; },
var view = document.getElementById('thumbnailView'); // Generic helper to find out what elements are visible within a scroll pane.
var currentHeight = kBottomMargin; getVisibleElements: function pdfViewGetVisibleElements(scrollEl, views) {
var currentHeight = 0, view;
var top = scrollEl.scrollTop;
var top = view.scrollTop; for (var i = 1; i <= views.length; ++i) {
for (var i = 1; i <= thumbs.length; ++i) { view = views[i - 1];
var thumb = thumbs[i - 1]; currentHeight = view.el.offsetTop;
var thumbHeight = thumb.height * thumb.scaleY + kBottomMargin; if (currentHeight + view.el.clientHeight > top)
if (currentHeight + thumbHeight > top)
break; break;
currentHeight += view.el.clientHeight;
currentHeight += thumbHeight;
} }
var bottom = top + view.clientHeight; var visible = [];
for (; i <= thumbs.length && currentHeight < bottom; ++i) { var bottom = top + scrollEl.clientHeight;
var singleThumb = thumbs[i - 1]; for (; i <= views.length && currentHeight < bottom; ++i) {
visibleThumbs.push({ id: singleThumb.id, y: currentHeight, view = views[i - 1];
view: singleThumb }); currentHeight = view.el.offsetTop;
currentHeight += singleThumb.height * singleThumb.scaleY + kBottomMargin; visible.push({ id: view.id, y: currentHeight,
view: view });
currentHeight += view.el.clientHeight;
} }
return visibleThumbs; return visible;
}, },
// Helper function to parse query string (e.g. ?param1=value&parm2=...). // Helper function to parse query string (e.g. ?param1=value&parm2=...).
@ -985,10 +1052,13 @@ var PageView = function pageView(container, pdfPage, id, scale,
this.scale = scale || 1.0; this.scale = scale || 1.0;
this.viewport = this.pdfPage.getViewport(this.scale); this.viewport = this.pdfPage.getViewport(this.scale);
this.renderingState = RenderingStates.INITIAL;
this.resume = null;
var anchor = document.createElement('a'); var anchor = document.createElement('a');
anchor.name = '' + this.id; anchor.name = '' + this.id;
var div = document.createElement('div'); var div = this.el = document.createElement('div');
div.id = 'pageContainer' + this.id; div.id = 'pageContainer' + this.id;
div.className = 'page'; div.className = 'page';
@ -1001,6 +1071,9 @@ var PageView = function pageView(container, pdfPage, id, scale,
}; };
this.update = function pageViewUpdate(scale) { this.update = function pageViewUpdate(scale) {
this.renderingState = RenderingStates.INITIAL;
this.resume = null;
this.scale = scale || this.scale; this.scale = scale || this.scale;
var viewport = this.pdfPage.getViewport(this.scale); var viewport = this.pdfPage.getViewport(this.scale);
@ -1174,9 +1247,9 @@ var PageView = function pageView(container, pdfPage, id, scale,
} }
if (scale && scale !== PDFView.currentScale) if (scale && scale !== PDFView.currentScale)
PDFView.parseScale(scale, true); PDFView.parseScale(scale, true, true);
else if (PDFView.currentScale === kUnknownScale) else if (PDFView.currentScale === kUnknownScale)
PDFView.parseScale(kDefaultScale, true); PDFView.parseScale(kDefaultScale, true, true);
var boundingRect = [ var boundingRect = [
this.viewport.convertToViewportPoint(x, y), this.viewport.convertToViewportPoint(x, y),
@ -1203,16 +1276,11 @@ var PageView = function pageView(container, pdfPage, id, scale,
}, 0); }, 0);
}; };
this.drawingRequired = function() {
return !div.querySelector('canvas');
};
this.draw = function pageviewDraw(callback) { this.draw = function pageviewDraw(callback) {
if (!this.drawingRequired()) { if (this.renderingState !== RenderingStates.INITIAL)
this.updateStats(); error('Must be in new state before drawing');
callback();
return; this.renderingState = RenderingStates.RUNNING;
}
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
canvas.id = 'page' + this.id; canvas.id = 'page' + this.id;
@ -1242,6 +1310,8 @@ var PageView = function pageView(container, pdfPage, id, scale,
var self = this; var self = this;
function pageViewDrawCallback(error) { function pageViewDrawCallback(error) {
self.renderingState = RenderingStates.FINISHED;
if (self.loadingIconDiv) { if (self.loadingIconDiv) {
div.removeChild(self.loadingIconDiv); div.removeChild(self.loadingIconDiv);
delete self.loadingIconDiv; delete self.loadingIconDiv;
@ -1264,7 +1334,18 @@ var PageView = function pageView(container, pdfPage, id, scale,
var renderContext = { var renderContext = {
canvasContext: ctx, canvasContext: ctx,
viewport: this.viewport, viewport: this.viewport,
textLayer: textLayer textLayer: textLayer,
continueCallback: function pdfViewcContinueCallback(cont) {
if (PDFView.highestPriorityPage !== 'page' + self.id) {
self.renderingState = RenderingStates.PAUSED;
self.resume = function resumeCallback() {
self.renderingState = RenderingStates.RUNNING;
cont();
};
return;
}
cont();
}
}; };
this.pdfPage.render(renderContext).then( this.pdfPage.render(renderContext).then(
function pdfPageRenderCallback() { function pdfPageRenderCallback() {
@ -1307,7 +1388,7 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
var scaleX = this.scaleX = (canvasWidth / pageWidth); var scaleX = this.scaleX = (canvasWidth / pageWidth);
var scaleY = this.scaleY = (canvasHeight / pageHeight); var scaleY = this.scaleY = (canvasHeight / pageHeight);
var div = document.createElement('div'); var div = this.el = document.createElement('div');
div.id = 'thumbnailContainer' + id; div.id = 'thumbnailContainer' + id;
div.className = 'thumbnail'; div.className = 'thumbnail';
@ -1315,6 +1396,7 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
container.appendChild(anchor); container.appendChild(anchor);
this.hasImage = false; this.hasImage = false;
this.renderingState = RenderingStates.INITIAL;
function getPageDrawContext() { function getPageDrawContext() {
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
@ -1347,22 +1429,40 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
}; };
this.draw = function thumbnailViewDraw(callback) { this.draw = function thumbnailViewDraw(callback) {
if (this.renderingState !== RenderingStates.INITIAL)
error('Must be in new state before drawing');
this.renderingState = RenderingStates.RUNNING;
if (this.hasImage) { if (this.hasImage) {
callback(); callback();
return; return;
} }
var self = this;
var ctx = getPageDrawContext(); var ctx = getPageDrawContext();
var drawViewport = pdfPage.getViewport(scaleX); var drawViewport = pdfPage.getViewport(scaleX);
var renderContext = { var renderContext = {
canvasContext: ctx, canvasContext: ctx,
viewport: drawViewport viewport: drawViewport,
continueCallback: function(cont) {
if (PDFView.highestPriorityPage !== 'thumbnail' + self.id) {
self.renderingState = RenderingStates.PAUSED;
self.resume = function() {
self.renderingState = RenderingStates.RUNNING;
cont();
};
return;
}
cont();
}
}; };
pdfPage.render(renderContext).then( pdfPage.render(renderContext).then(
function pdfPageRenderCallback() { function pdfPageRenderCallback() {
self.renderingState = RenderingStates.FINISHED;
callback(); callback();
}, },
function pdfPageRenderError(error) { function pdfPageRenderError(error) {
self.renderingState = RenderingStates.FINISHED;
callback(); callback();
} }
); );
@ -1372,7 +1472,7 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
this.setImage = function thumbnailViewSetImage(img) { this.setImage = function thumbnailViewSetImage(img) {
if (this.hasImage || !img) if (this.hasImage || !img)
return; return;
this.renderingState = RenderingStates.FINISHED;
var ctx = getPageDrawContext(); var ctx = getPageDrawContext();
ctx.drawImage(img, 0, 0, img.width, img.height, ctx.drawImage(img, 0, 0, img.width, img.height,
0, 0, ctx.canvas.width, ctx.canvas.height); 0, 0, ctx.canvas.width, ctx.canvas.height);
@ -1614,9 +1714,6 @@ window.addEventListener('load', function webViewerLoad(evt) {
} }
}); });
var thumbsView = document.getElementById('thumbnailView');
thumbsView.addEventListener('scroll', updateThumbViewArea, true);
var mainContainer = document.getElementById('mainContainer'); var mainContainer = document.getElementById('mainContainer');
var outerContainer = document.getElementById('outerContainer'); var outerContainer = document.getElementById('outerContainer');
mainContainer.addEventListener('transitionend', function(e) { mainContainer.addEventListener('transitionend', function(e) {
@ -1633,56 +1730,19 @@ window.addEventListener('load', function webViewerLoad(evt) {
this.classList.toggle('toggled'); this.classList.toggle('toggled');
outerContainer.classList.add('sidebarMoving'); outerContainer.classList.add('sidebarMoving');
outerContainer.classList.toggle('sidebarOpen'); outerContainer.classList.toggle('sidebarOpen');
updateThumbViewArea(); PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen');
PDFView.renderHighestPriority();
}); });
PDFView.open(file, 0); PDFView.open(file, 0);
}, true); }, 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() { function updateViewarea() {
if (!PDFView.initialized) if (!PDFView.initialized)
return; return;
var visiblePages = PDFView.getVisiblePages(); var visiblePages = PDFView.getVisiblePages();
var pageToDraw;
for (var i = 0; i < visiblePages.length; i++) {
var page = visiblePages[i];
var pageObj = PDFView.pages[page.id - 1];
pageToDraw |= pageObj.drawingRequired(); PDFView.renderHighestPriority();
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" updateViewarea.inProgress = true; // used in "set page"
var currentId = PDFView.page; var currentId = PDFView.page;
@ -1713,29 +1773,6 @@ function updateViewarea() {
document.getElementById('viewBookmark').href = href; document.getElementById('viewBookmark').href = href;
} }
window.addEventListener('scroll', function webViewerScroll(evt) {
updateViewarea();
}, true);
var thumbnailTimer;
function updateThumbViewArea() {
// Only render thumbs after pausing scrolling for this amount of time
// (makes UI more responsive)
var delay = 50; // in ms
if (thumbnailTimer)
clearTimeout(thumbnailTimer);
thumbnailTimer = setTimeout(function() {
var visibleThumbs = PDFView.getVisibleThumbs();
for (var i = 0; i < visibleThumbs.length; i++) {
var thumb = visibleThumbs[i];
renderingQueue.enqueueDraw(PDFView.thumbnails[thumb.id - 1]);
}
}, delay);
}
window.addEventListener('resize', function webViewerResize(evt) { window.addEventListener('resize', function webViewerResize(evt) {
if (PDFView.initialized && if (PDFView.initialized &&
(document.getElementById('pageWidthOption').selected || (document.getElementById('pageWidthOption').selected ||
@ -1844,6 +1881,18 @@ window.addEventListener('pagechange', function pagechange(evt) {
document.getElementById('next').disabled = (page >= PDFView.pages.length); document.getElementById('next').disabled = (page >= PDFView.pages.length);
}, true); }, true);
// Firefox specific event, so that we can prevent browser from zooming
window.addEventListener('DOMMouseScroll', function(evt) {
if (evt.ctrlKey) {
evt.preventDefault();
var ticks = evt.detail;
var direction = (ticks > 0) ? 'zoomOut' : 'zoomIn';
for (var i = 0, length = Math.abs(ticks); i < length; i++)
PDFView[direction]();
}
}, false);
window.addEventListener('keydown', function keydown(evt) { window.addEventListener('keydown', function keydown(evt) {
var handled = false; var handled = false;
var cmd = (evt.ctrlKey ? 1 : 0) | var cmd = (evt.ctrlKey ? 1 : 0) |