Bug 852981 - Update pdf.js to version 0.7.390. r=bdahl

This commit is contained in:
Ryan VanderMeulen 2013-03-25 18:05:36 -04:00
parent f98ed9f89e
commit 977ac941d8
8 changed files with 506 additions and 135 deletions

View File

@ -1,4 +1,4 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 0.7.337
Current extension version is: 0.7.390

View File

@ -0,0 +1,155 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils, NetUtil, dump */
'use strict';
var EXPORTED_SYMBOLS = ['PdfRedirector'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const PDF_CONTENT_TYPE = 'application/pdf';
const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
function getDOMWindow(aChannel) {
var requestor = aChannel.notificationCallbacks ?
aChannel.notificationCallbacks :
aChannel.loadGroup.notificationCallbacks;
var win = requestor.getInterface(Components.interfaces.nsIDOMWindow);
return win;
}
function getObjectUrl(window) {
var url;
var element = window.frameElement;
var isOverlay = false;
var params = {};
if (element) {
var tagName = element.nodeName;
while (tagName != 'EMBED' && tagName != 'OBJECT') {
// plugin overlay skipping until the target plugin is found
isOverlay = true;
element = element.parentNode;
if (!element)
throw 'Plugin element is not found';
tagName = element.nodeName;
}
if (tagName == 'EMBED') {
for (var i = 0; i < element.attributes.length; ++i) {
params[element.attributes[i].localName] = element.attributes[i].value;
}
url = params.src;
} else {
for (var i = 0; i < element.childNodes.length; ++i) {
var paramElement = element.childNodes[i];
if (paramElement.nodeType != Ci.nsIDOMNode.ELEMENT_NODE ||
paramElement.nodeName != 'PARAM') {
continue;
}
params[paramElement.getAttribute('name')] =
paramElement.getAttribute('value');
}
var dataAttribute = element.getAttribute('data');
url = dataAttribute || params.movie || params.src;
}
}
if (!url) {
return url; // src is not specified
}
var element = window.frameElement;
// XXX base uri?
var baseUri = !element ? null :
Services.io.newURI(element.ownerDocument.location.href, null, null);
return Services.io.newURI(url, null, baseUri).spec;
}
function PdfRedirector() {
}
PdfRedirector.prototype = {
// properties required for XPCOM registration:
classID: Components.ID('{8cbfd8d0-2042-4976-b3ef-d9dee1efb975}'),
classDescription: 'pdf.js Redirector',
contractID:
'@mozilla.org/streamconv;1?from=application/x-moz-playpreview-pdfjs&to=*/*',
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIStreamConverter,
Ci.nsIStreamListener,
Ci.nsIRequestObserver
]),
// nsIStreamConverter::convert
convert: function(aFromStream, aFromType, aToType, aCtxt) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
// nsIStreamConverter::asyncConvertData
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
// Store the listener passed to us
this.listener = aListener;
},
// nsIStreamListener::onDataAvailable
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
// Do nothing since all the data loading is handled by the viewer.
},
// nsIRequestObserver::onStartRequest
onStartRequest: function(aRequest, aContext) {
// Setup the request so we can use it below.
aRequest.QueryInterface(Ci.nsIChannel);
// Cancel the request so the viewer can handle it.
aRequest.cancel(Cr.NS_BINDING_ABORTED);
var domWindow = getDOMWindow(aRequest);
var pdfUrl = getObjectUrl(domWindow);
if (!pdfUrl) {
Services.console.logStringMessage(
'PdfRedirector.js: PDF location is not specified for OBJECT/EMBED tag');
return;
}
// Create a new channel that is viewer loaded as a resource.
var ioService = Services.io;
var channel = ioService.newChannel(pdfUrl, null, null);
channel.loadGroup = aRequest.loadGroup;
channel.asyncOpen(this.listener, aContext);
},
// nsIRequestObserver::onStopRequest
onStopRequest: function(aRequest, aContext, aStatusCode) {
// Do nothing
}
};
var NSGetFactory = XPCOMUtils.generateNSGetFactory([PdfRedirector]);

View File

@ -337,6 +337,7 @@ ChromeActions.prototype = {
}, '*');
};
var self = this;
this.dataListener.oncomplete =
function ChromeActions_dataListenerComplete(data, errorCode) {
@ -346,7 +347,7 @@ ChromeActions.prototype = {
errorCode: errorCode
}, '*');
delete this.dataListener;
delete self.dataListener;
};
return true;
@ -385,21 +386,19 @@ ChromeActions.prototype = {
var message = getLocalizedString(strings, 'unsupported_feature');
var notificationBox = null;
// Multiple browser windows can be opened, finding one for notification box
var windowsEnum = Services.wm
.getZOrderDOMWindowEnumerator('navigator:browser', true);
while (windowsEnum.hasMoreElements()) {
var win = windowsEnum.getNext();
if (win.closed)
continue;
var browser = win.gBrowser.getBrowserForDocument(domWindow.top.document);
if (browser) {
// right window/browser is found, getting the notification box
notificationBox = win.gBrowser.getNotificationBox(browser);
break;
}
}
if (!notificationBox) {
try {
// Based on MDN's "Working with windows in chrome code"
var mainWindow = domWindow
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
var browser = mainWindow.gBrowser
.getBrowserForDocument(domWindow.top.document);
notificationBox = mainWindow.gBrowser.getNotificationBox(browser);
} catch (e) {
log('Unable to get a notification box for the fallback message');
return;
}

View File

@ -33,11 +33,15 @@ const PDF_CONTENT_TYPE = 'application/pdf';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://pdf.js.components/PdfStreamConverter.js');
Cu.import('resource://pdf.js.components/PdfRedirector.js');
let Svc = {};
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
'@mozilla.org/mime;1',
'nsIMIMEService');
XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost',
'@mozilla.org/plugin/host;1',
'nsIPluginHost');
function getBoolPref(aPref, aDefaultValue) {
try {
@ -55,8 +59,10 @@ function getIntPref(aPref, aDefaultValue) {
}
}
// Register/unregister a constructor as a component.
let Factory = {
// Factory that registers/unregisters a constructor as a component.
function Factory() {}
Factory.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
_targetConstructor: null,
@ -193,7 +199,14 @@ let PdfJs = {
if (this._registered)
return;
Factory.register(PdfStreamConverter);
this._pdfStreamConverterFactory = new Factory();
this._pdfStreamConverterFactory.register(PdfStreamConverter);
this._pdfRedirectorFactory = new Factory();
this._pdfRedirectorFactory.register(PdfRedirector);
Svc.pluginHost.registerPlayPreviewMimeType('application/pdf', true,
'data:application/x-moz-playpreview-pdfjs;,');
this._registered = true;
},
@ -201,7 +214,13 @@ let PdfJs = {
if (!this._registered)
return;
Factory.unregister();
this._pdfStreamConverterFactory.unregister();
delete this._pdfStreamConverterFactory;
this._pdfRedirectorFactory.unregister;
delete this._pdfRedirectorFactory;
Svc.pluginHost.unregisterPlayPreviewMimeType('application/pdf');
this._registered = false;
}
};

View File

@ -16,8 +16,8 @@
*/
var PDFJS = {};
PDFJS.version = '0.7.337';
PDFJS.build = 'f58aee1';
PDFJS.version = '0.7.390';
PDFJS.build = '921f321';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
@ -832,6 +832,23 @@ var Util = PDFJS.Util = (function UtilClosure() {
return [xt, yt];
};
// Applies the transform to the rectangle and finds the minimum axially
// aligned bounding box.
Util.getAxialAlignedBoundingBox =
function Util_getAxialAlignedBoundingBox(r, m) {
var p1 = Util.applyTransform(r, m);
var p2 = Util.applyTransform(r.slice(2, 4), m);
var p3 = Util.applyTransform([r[0], r[3]], m);
var p4 = Util.applyTransform([r[2], r[1]], m);
return [
Math.min(p1[0], p2[0], p3[0], p4[0]),
Math.min(p1[1], p2[1], p3[1], p4[1]),
Math.max(p1[0], p2[0], p3[0], p4[0]),
Math.max(p1[1], p2[1], p3[1], p4[1])
];
};
Util.inverseTransform = function Util_inverseTransform(m) {
var d = m[0] * m[3] - m[1] * m[2];
return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
@ -2260,6 +2277,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.objs = objs;
this.textLayer = textLayer;
this.imageLayer = imageLayer;
this.groupStack = [];
if (canvasCtx) {
addContextCurrentTransform(canvasCtx);
}
@ -2392,6 +2410,25 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
return tmpCanvas;
}
function copyCtxState(sourceCtx, destCtx) {
var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha',
'lineWidth', 'lineCap', 'lineJoin', 'miterLimit',
'globalCompositeOperation', 'font'];
for (var i = 0, ii = properties.length; i < ii; i++) {
var property = properties[i];
if (property in sourceCtx) {
destCtx[property] = sourceCtx[property];
}
}
if ('setLineDash' in sourceCtx) {
destCtx.setLineDash(sourceCtx.getLineDash());
destCtx.lineDashOffset = sourceCtx.lineDashOffset;
} else if ('mozDash' in sourceCtx) {
destCtx.mozDash = sourceCtx.mozDash;
destCtx.mozDashOffset = sourceCtx.mozDashOffset;
}
}
var LINE_CAP_STYLES = ['butt', 'round', 'square'];
var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
var NORMAL_CLIP = {};
@ -2596,6 +2633,22 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.current.fillAlpha = state[1];
this.ctx.globalAlpha = state[1];
break;
case 'BM':
if (value && value.name && (value.name !== 'Normal')) {
var mode = value.name.replace(/([A-Z])/g,
function(c) {
return '-' + c.toLowerCase();
}
).substring(1);
this.ctx.globalCompositeOperation = mode;
if (this.ctx.globalCompositeOperation !== mode) {
warn('globalCompositeOperation "' + mode +
'" is not supported');
}
} else {
this.ctx.globalCompositeOperation = 'source-over';
}
break;
}
}
},
@ -3008,7 +3061,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var character = glyph.fontChar;
var vmetric = glyph.vmetric || defaultVMetrics;
if (vertical) {
var vx = vmetric[1] * fontSize * current.fontMatrix[0];
var vx = glyph.vmetric ? vmetric[1] : glyph.width * 0.5;
vx = -vx * fontSize * current.fontMatrix[0];
var vy = vmetric[2] * fontSize * current.fontMatrix[0];
}
var width = vmetric ? -vmetric[0] : glyph.width;
@ -3083,7 +3137,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
geom.canvasWidth = canvasWidth;
if (vertical) {
var vmetric = font.defaultVMetrics;
geom.x -= vmetric[1] * fontSize * current.fontMatrix[0] /
geom.x += vmetric[1] * fontSize * current.fontMatrix[0] /
fontSizeScale * geom.hScale;
geom.y += vmetric[2] * fontSize * current.fontMatrix[0] /
fontSizeScale * geom.vScale;
@ -3144,7 +3198,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (vertical) {
var fontSizeScale = current.fontSizeScale;
var vmetric = font.defaultVMetrics;
geom.x -= vmetric[1] * fontSize * current.fontMatrix[0] /
geom.x += vmetric[1] * fontSize * current.fontMatrix[0] /
fontSizeScale * geom.hScale;
geom.y += vmetric[2] * fontSize * current.fontMatrix[0] /
fontSizeScale * geom.vScale;
@ -3365,6 +3419,89 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
} while (this.current.paintFormXObjectDepth >= depth);
},
beginGroup: function CanvasGraphics_beginGroup(group) {
this.save();
var currentCtx = this.ctx;
// TODO non-isolated groups - according to Rik at adobe non-isolated
// group results aren't usually that different and they even have tools
// that ignore this setting. Notes from Rik on implmenting:
// - When you encounter an transparency group, create a new canvas with
// the dimensions of the bbox
// - copy the content from the previous canvas to the new canvas
// - draw as usual
// - remove the backdrop alpha:
// alphaNew = 1 - (1 - alpha)/(1 - alphaBackdrop) with 'alpha' the alpha
// value of your transparency group and 'alphaBackdrop' the alpha of the
// backdrop
// - remove background color:
// colorNew = color - alphaNew *colorBackdrop /(1 - alphaNew)
if (!group.isolated) {
TODO('Support non-isolated groups.');
}
// TODO knockout - supposedly possible with the clever use of compositing
// modes.
if (group.knockout) {
TODO('Support knockout groups.');
}
var currentTransform = currentCtx.mozCurrentTransform;
if (group.matrix) {
currentCtx.transform.apply(currentCtx, group.matrix);
}
assert(group.bbox, 'Bounding box is required.');
// Based on the current transform figure out how big the bounding box
// will actually be.
var bounds = Util.getAxialAlignedBoundingBox(
group.bbox,
currentCtx.mozCurrentTransform);
// Use ceil in case we're between sizes so we don't create canvas that is
// too small.
var drawnWidth = Math.ceil(bounds[2] - bounds[0]);
var drawnHeight = Math.ceil(bounds[3] - bounds[1]);
var scratchCanvas = createScratchCanvas(drawnWidth, drawnHeight);
var groupCtx = scratchCanvas.getContext('2d');
addContextCurrentTransform(groupCtx);
// Since we created a new canvas that is just the size of the bounding box
// we have to translate the group ctx.
var offsetX = bounds[0];
var offsetY = bounds[1];
groupCtx.translate(-offsetX, -offsetY);
groupCtx.transform.apply(groupCtx, currentTransform);
// Setup the current ctx so when the group is popped we draw it the right
// location.
currentCtx.setTransform(1, 0, 0, 1, 0, 0);
currentCtx.translate(offsetX, offsetY);
// The transparency group inherits all off the current graphics state
// except the blend mode, soft mask, and alpha constants.
copyCtxState(currentCtx, groupCtx);
this.ctx = groupCtx;
this.setGState([
['SMask', 'None'],
['BM', 'Normal'],
['ca', 1],
['CA', 1]
]);
this.groupStack.push(currentCtx);
},
endGroup: function CanvasGraphics_endGroup(group) {
var groupCtx = this.ctx;
this.ctx = this.groupStack.pop();
// Turn off image smoothing to avoid sub pixel interpolation which can
// look kind of blurry for some pdfs.
if ('imageSmoothingEnabled' in this.ctx) {
this.ctx.imageSmoothingEnabled = false;
} else {
this.ctx.mozImageSmoothingEnabled = false;
}
this.ctx.drawImage(groupCtx.canvas, 0, 0);
this.restore();
},
paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
var domImage = this.objs.get(objId);
if (!domImage) {
@ -3920,7 +4057,7 @@ var Catalog = (function CatalogClosure() {
if (isStream(js)) {
js = bytesToString(js.getBytes());
}
javaScript.push(js);
javaScript.push(stringToPDFString(js));
}
}
return shadow(this, 'javaScript', javaScript);
@ -4385,6 +4522,9 @@ var NameTree = (function NameTreeClosure() {
while (queue.length > 0) {
var i, n;
var obj = xref.fetchIfRef(queue.shift());
if (!isDict(obj)) {
continue;
}
if (obj.has('Kids')) {
var kids = obj.get('Kids');
for (i = 0, n = kids.length; i < n; i++) {
@ -14652,6 +14792,60 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return loadedName;
}
function buildFormXObject(xobj, smask) {
var matrix = xobj.dict.get('Matrix');
var bbox = xobj.dict.get('BBox');
var group = xobj.dict.get('Group');
if (group) {
var groupOptions = {
matrix: matrix,
bbox: bbox,
smask: !!smask,
isolated: false,
knockout: false
};
var groupSubtype = group.get('S');
if (isName(groupSubtype) && groupSubtype.name === 'Transparency') {
groupOptions.isolated = group.get('I') || false;
groupOptions.knockout = group.get('K') || false;
// There is also a group colorspace, but since we put everything in
// RGB I'm not sure we need it.
}
fnArray.push('beginGroup');
argsArray.push([groupOptions]);
}
fnArray.push('paintFormXObjectBegin');
argsArray.push([matrix, bbox]);
// This adds the operatorList of the xObj to the current queue.
var depIdx = dependencyArray.length;
// Pass in the current `queue` object. That means the `fnArray`
// and the `argsArray` in this scope is reused and new commands
// are added to them.
self.getOperatorList(xobj,
xobj.dict.get('Resources') || resources,
dependencyArray, queue);
self.getOperatorList(xobj,
xobj.dict.get('Resources') || resources,
dependencyArray, queue);
// Add the dependencies that are required to execute the
// operatorList.
insertDependency(dependencyArray.slice(depIdx));
fnArray.push('paintFormXObjectEnd');
argsArray.push([]);
if (group) {
fnArray.push('endGroup');
argsArray.push([groupOptions]);
}
}
function buildPaintImageXObject(image, inline) {
var dict = image.dict;
var w = dict.get('Width', 'W');
@ -14825,28 +15019,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
);
if ('Form' == type.name) {
var matrix = xobj.dict.get('Matrix');
var bbox = xobj.dict.get('BBox');
fnArray.push('paintFormXObjectBegin');
argsArray.push([matrix, bbox]);
// This adds the operatorList of the xObj to the current queue.
var depIdx = dependencyArray.length;
// Pass in the current `queue` object. That means the `fnArray`
// and the `argsArray` in this scope is reused and new commands
// are added to them.
this.getOperatorList(xobj,
xobj.dict.get('Resources') || resources,
dependencyArray, queue);
// Add the dependencies that are required to execute the
// operatorList.
insertDependency(dependencyArray.slice(depIdx));
fn = 'paintFormXObjectEnd';
buildFormXObject(xobj);
args = [];
continue;
} else if ('Image' == type.name) {
buildPaintImageXObject(xobj, false);
} else {
@ -14905,6 +15080,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
case 'FL':
case 'CA':
case 'ca':
case 'BM':
gsStateObj.push([key, value]);
break;
case 'Font':
@ -14914,11 +15090,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
value[1]
]);
break;
case 'BM':
// We support the default so don't trigger the TODO.
if (!isName(value) || value.name != 'Normal')
TODO('graphic state operator ' + key);
break;
case 'SMask':
// We support the default so don't trigger the TODO.
if (!isName(value) || value.name != 'None')
@ -15459,7 +15630,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
if (properties.vertical) {
var vmetrics = dict.get('DW2') || [880, -1000];
defaultVMetrics = [vmetrics[1], vmetrics[1] / 2, vmetrics[0]];
defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]];
vmetrics = dict.get('W2');
if (vmetrics) {
for (var i = 0, ii = vmetrics.length; i < ii; i++) {
@ -16073,7 +16244,23 @@ var nonStdFontMap = {
'LucidaConsole': 'Courier',
'LucidaConsole-Bold': 'Courier-Bold',
'LucidaConsole-BoldItalic': 'Courier-BoldOblique',
'LucidaConsole-Italic': 'Courier-Oblique'
'LucidaConsole-Italic': 'Courier-Oblique',
'MS-Gothic': 'MS Gothic',
'MS-Gothic-Bold': 'MS Gothic-Bold',
'MS-Gothic-BoldItalic': 'MS Gothic-BoldItalic',
'MS-Gothic-Italic': 'MS Gothic-Italic',
'MS-Mincho': 'MS Mincho',
'MS-Mincho-Bold': 'MS Mincho-Bold',
'MS-Mincho-BoldItalic': 'MS Mincho-BoldItalic',
'MS-Mincho-Italic': 'MS Mincho-Italic',
'MS-PGothic': 'MS PGothic',
'MS-PGothic-Bold': 'MS PGothic-Bold',
'MS-PGothic-BoldItalic': 'MS PGothic-BoldItalic',
'MS-PGothic-Italic': 'MS PGothic-Italic',
'MS-PMincho': 'MS PMincho',
'MS-PMincho-Bold': 'MS PMincho-Bold',
'MS-PMincho-BoldItalic': 'MS PMincho-BoldItalic',
'MS-PMincho-Italic': 'MS PMincho-Italic',
};
var serifFonts = {
@ -16139,6 +16326,7 @@ var CMapConverterList = {
'90msp-RKSJ-H': sjisToUnicode,
'90msp-RKSJ-V': sjisToUnicode,
'GBK-EUC-H': gbkToUnicode,
'B5pc-H': big5ToUnicode,
'ETenms-B5-H': big5ToUnicode,
'ETenms-B5-V': big5ToUnicode,
};
@ -18164,8 +18352,8 @@ var Font = (function FontClosure() {
}
var bmpLength = i + 1;
var trailingRangesCount = ranges[bmpLength - 1][1] < 0xFFFF ? 1 : 0;
var segCount = bmpLength + trailingRangesCount;
if (ranges[i][1] === 0xFFFF) { ranges[i][1] = 0xFFFE; }
var segCount = bmpLength + 1;
var segCount2 = segCount * 2;
var searchRange = getMaxPower2(segCount) * 2;
var searchEntry = Math.log(segCount) / Math.log(2);
@ -18210,12 +18398,10 @@ var Font = (function FontClosure() {
}
}
if (trailingRangesCount > 0) {
endCount += '\xFF\xFF';
startCount += '\xFF\xFF';
idDeltas += '\x00\x01';
idRangeOffsets += '\x00\x00';
}
endCount += '\xFF\xFF';
startCount += '\xFF\xFF';
idDeltas += '\x00\x01';
idRangeOffsets += '\x00\x00';
var format314 = '\x00\x00' + // language
string16(segCount2) +
@ -18302,6 +18488,14 @@ var Font = (function FontClosure() {
if (firstChar > lastChar) {
return false;
}
stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap
var usWinAscent = int16(stream.getBytes(2));
if (usWinAscent === 0) { // makes font unreadable by windows
return false;
}
// OS/2 appears to be valid, resetting some fields
os2.data[8] = os2.data[9] = 0; // IE rejects fonts if fsType != 0
return true;
}
@ -19151,16 +19345,6 @@ var Font = (function FontClosure() {
return names;
}
function isOS2Valid(os2Table) {
var data = os2Table.data;
// usWinAscent == 0 makes font unreadable by windows
var usWinAscent = (data[74] << 8) | data[75];
if (usWinAscent === 0)
return false;
return true;
}
var TTOpsStackDeltas = [
0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5,
-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1,
@ -19355,12 +19539,6 @@ var Font = (function FontClosure() {
// of missing tables
createOpenTypeHeader(header.version, ttf, numTables);
// Invalid OS/2 can break the font for the Windows
if (os2 && !isOS2Valid(os2)) {
tables.splice(tables.indexOf(os2), 1);
os2 = null;
}
// Ensure the hmtx table contains the advance width and
// sidebearings information for numGlyphs in the maxp table
font.pos = (font.start || 0) + maxp.offset;
@ -21658,10 +21836,19 @@ var CFFParser = (function CFFParserClosure() {
}
return { charStrings: charStrings, seacs: seacs };
},
emptyPrivateDictionary:
function CFFParser_emptyPrivateDictionary(parentDict) {
var privateDict = this.createDict(CFFPrivateDict, [],
parentDict.strings);
parentDict.setByKey(18, [0, 0]);
parentDict.privateDict = privateDict;
},
parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
// no private dict, do nothing
if (!parentDict.hasName('Private'))
if (!parentDict.hasName('Private')) {
this.emptyPrivateDictionary(parentDict);
return;
}
var privateOffset = parentDict.getByName('Private');
// make sure the params are formatted correctly
if (!isArray(privateOffset) || privateOffset.length !== 2) {
@ -21672,7 +21859,7 @@ var CFFParser = (function CFFParserClosure() {
var offset = privateOffset[1];
// remove empty dicts or ones that refer to invalid location
if (size === 0 || offset >= this.bytes.length) {
parentDict.removeByName('Private');
this.emptyPrivateDictionary(parentDict);
return;
}
@ -21690,7 +21877,7 @@ var CFFParser = (function CFFParserClosure() {
var relativeOffset = offset + subrsOffset;
// Validate the offset.
if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
privateDict.removeByName('Subrs');
this.emptyPrivateDictionary(parentDict);
return;
}
var subrsIndex = this.parseIndex(relativeOffset);
@ -22371,15 +22558,23 @@ var CFFCompiler = (function CFFCompilerClosure() {
output) {
for (var i = 0, ii = dicts.length; i < ii; ++i) {
var fontDict = dicts[i];
if (!fontDict.privateDict || !fontDict.hasName('Private'))
continue;
assert(fontDict.privateDict && fontDict.hasName('Private'),
'There must be an private dictionary.');
var privateDict = fontDict.privateDict;
var privateDictTracker = new CFFOffsetTracker();
var privateDictData = this.compileDict(privateDict, privateDictTracker);
privateDictTracker.offset(output.length);
var outputLength = output.length;
privateDictTracker.offset(outputLength);
if (!privateDictData.length) {
// The private dictionary was empty, set the output length to zero to
// ensure the offset length isn't out of bounds in the eyes of the
// sanitizer.
outputLength = 0;
}
trackers[i].setEntryLocation('Private',
[privateDictData.length, output.length],
[privateDictData.length, outputLength],
output);
output.add(privateDictData);

View File

@ -826,6 +826,11 @@ html[dir='rtl'] .toolbarButton.pageDown::before {
padding-top: 4px;
}
#viewBookmark[href='#'] {
opacity: .5;
pointer-events: none;
}
.toolbarButton.bookmark::before {
content: url(images/toolbarButton-bookmark.png);
}

View File

@ -1290,6 +1290,7 @@ var PDFView = {
if (PDFView.supportsPrinting) {
pdfDocument.getJavaScript().then(function(javaScript) {
if (javaScript.length) {
console.warn('Warning: JavaScript is not supported');
PDFView.fallback();
}
// Hack to support auto printing.
@ -1363,7 +1364,7 @@ var PDFView = {
self.setTitle(pdfTitle + ' - ' + document.title);
if (info.IsAcroFormPresent) {
// AcroForm/XFA was found
console.warn('Warning: AcroForm/XFA is not supported');
PDFView.fallback();
}
});
@ -1565,55 +1566,52 @@ var PDFView = {
},
getVisiblePages: function pdfViewGetVisiblePages() {
return this.getVisibleElements(this.container,
this.pages, true);
if (!this.isFullscreen) {
return this.getVisibleElements(this.container, this.pages, true);
} else {
// The algorithm in getVisibleElements is broken in fullscreen mode.
var visible = [], page = this.page;
var currentPage = this.pages[page - 1];
visible.push({ id: currentPage.id, view: currentPage });
return { first: currentPage, last: currentPage, views: visible};
}
},
getVisibleThumbs: function pdfViewGetVisibleThumbs() {
return this.getVisibleElements(this.thumbnailContainer,
this.thumbnails);
return this.getVisibleElements(this.thumbnailContainer, this.thumbnails);
},
// Generic helper to find out what elements are visible within a scroll pane.
getVisibleElements: function pdfViewGetVisibleElements(
scrollEl, views, sortByVisibility) {
var currentHeight = 0, view;
var top = scrollEl.scrollTop;
var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
for (var i = 1, ii = views.length; i <= ii; ++i) {
view = views[i - 1];
var visible = [], view;
var currentHeight, viewHeight, hiddenHeight, percentHeight;
var currentWidth, viewWidth;
for (var i = 0, ii = views.length; i < ii; ++i) {
view = views[i];
currentHeight = view.el.offsetTop + view.el.clientTop;
if (currentHeight + view.el.clientHeight > top)
break;
currentHeight += view.el.clientHeight;
}
var visible = [];
// Algorithm broken in fullscreen mode
if (this.isFullscreen) {
var currentPage = this.pages[this.page - 1];
visible.push({
id: currentPage.id,
view: currentPage
});
return { first: currentPage, last: currentPage, views: visible};
}
var bottom = top + scrollEl.clientHeight;
var nextHeight, hidden, percent, viewHeight;
for (; i <= ii && currentHeight < bottom; ++i) {
view = views[i - 1];
viewHeight = view.el.clientHeight;
currentHeight = view.el.offsetTop + view.el.clientTop;
nextHeight = currentHeight + viewHeight;
hidden = Math.max(0, top - currentHeight) +
Math.max(0, nextHeight - bottom);
percent = Math.floor((viewHeight - hidden) * 100.0 / viewHeight);
if ((currentHeight + viewHeight) < top) {
continue;
}
if (currentHeight > bottom) {
break;
}
currentWidth = view.el.offsetLeft + view.el.clientLeft;
viewWidth = view.el.clientWidth;
if ((currentWidth + viewWidth) < left || currentWidth > right) {
continue;
}
hiddenHeight = Math.max(0, top - currentHeight) +
Math.max(0, currentHeight + viewHeight - bottom);
percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0;
visible.push({ id: view.id, y: currentHeight,
view: view, percent: percent });
currentHeight = nextHeight;
view: view, percent: percentHeight });
}
var first = visible[0];
@ -1622,13 +1620,12 @@ var PDFView = {
if (sortByVisibility) {
visible.sort(function(a, b) {
var pc = a.percent - b.percent;
if (Math.abs(pc) > 0.001)
if (Math.abs(pc) > 0.001) {
return -pc;
}
return a.id - b.id; // ensure stability
});
}
return {first: first, last: last, views: visible};
},
@ -1704,6 +1701,10 @@ var PDFView = {
this.page = this.page;
this.clearMouseScrollState();
this.hidePresentationControls();
// Ensure that the thumbnail of the current page is visible
// when exiting fullscreen mode.
scrollIntoView(document.getElementById('thumbnailContainer' + this.page));
},
showPresentationControls: function pdfViewShowPresentationControls() {
@ -2086,7 +2087,6 @@ var PageView = function pageView(container, pdfPage, id, scale,
var canvas = document.createElement('canvas');
canvas.id = 'page' + this.id;
canvas.mozOpaque = true;
div.appendChild(canvas);
this.canvas = canvas;
@ -2116,13 +2116,10 @@ var PageView = function pageView(container, pdfPage, id, scale,
}
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
// TODO(mack): use data attributes to store these
ctx._scaleX = outputScale.sx;
ctx._scaleY = outputScale.sy;
ctx.save();
ctx.fillStyle = 'rgb(255, 255, 255)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
if (outputScale.scaled) {
ctx.scale(outputScale.sx, outputScale.sy);
}
@ -2337,7 +2334,6 @@ var ThumbnailView = function thumbnailView(container, pdfPage, id) {
function getPageDrawContext() {
var canvas = document.createElement('canvas');
canvas.id = 'thumbnail' + id;
canvas.mozOpaque = true;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
@ -2599,7 +2595,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) {
var textDiv = document.createElement('div');
// vScale and hScale already contain the scaling to pixel units
var fontHeight = geom.fontSize * geom.vScale;
var fontHeight = geom.fontSize * Math.abs(geom.vScale);
textDiv.dataset.canvasWidth = geom.canvasWidth * geom.hScale;
textDiv.dataset.fontName = geom.fontName;
@ -3250,7 +3246,8 @@ window.addEventListener('keydown', function keydown(evt) {
// First, handle the key bindings that are independent whether an input
// control is selected or not.
if (cmd == 1 || cmd == 8) { // either CTRL or META key.
if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
// either CTRL or META key with optional SHIFT.
switch (evt.keyCode) {
case 70:
if (!PDFView.supportsIntegratedFind) {

View File

@ -1,4 +1,5 @@
chrome.manifest
components/PdfRedirector.js
components/PdfStreamConverter.js
content/build/pdf.js
content/PdfJs.jsm