Merge remote-tracking branch 'mozilla/master' into issue1133
Conflicts: src/util.js test/test_manifest.json
@ -127,14 +127,14 @@ PdfStreamConverter.prototype = {
|
||||
'resource://pdf.js/web/viewer.html', null, null);
|
||||
|
||||
// Keep the URL the same so the browser sees it as the same.
|
||||
channel.originalURI = aRequest.originalURI;
|
||||
channel.originalURI = aRequest.URI;
|
||||
channel.asyncOpen(this.listener, aContext);
|
||||
|
||||
// Setup a global listener waiting for the next DOM to be created and verfiy
|
||||
// that its the one we want by its URL. When the correct DOM is found create
|
||||
// an event listener on that window for the pdf.js events that require
|
||||
// chrome priviledges.
|
||||
var url = aRequest.originalURI.spec;
|
||||
var url = aRequest.URI.spec;
|
||||
var gb = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
var domListener = function domListener(event) {
|
||||
var doc = event.originalTarget;
|
||||
|
@ -23,6 +23,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
||||
this.alphaIsShape = false;
|
||||
this.fontSize = 0;
|
||||
this.textMatrix = IDENTITY_MATRIX;
|
||||
this.fontMatrix = IDENTITY_MATRIX;
|
||||
this.leading = 0;
|
||||
// Current point (in user coordinates)
|
||||
this.x = 0;
|
||||
@ -546,12 +547,32 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
},
|
||||
setFont: function canvasGraphicsSetFont(fontRefName, size) {
|
||||
var fontObj = this.objs.get(fontRefName).fontObj;
|
||||
var current = this.current;
|
||||
|
||||
if (!fontObj) {
|
||||
if (!fontObj)
|
||||
error('Can\'t find font for ' + fontRefName);
|
||||
|
||||
// Slice-clone matrix so we can manipulate it without affecting original
|
||||
if (fontObj.fontMatrix)
|
||||
current.fontMatrix = fontObj.fontMatrix.slice(0);
|
||||
else
|
||||
current.fontMatrix = IDENTITY_MATRIX.slice(0);
|
||||
|
||||
// A valid matrix needs all main diagonal elements to be non-zero
|
||||
// This also ensures we bypass FF bugzilla bug #719844.
|
||||
if (current.fontMatrix[0] === 0 ||
|
||||
current.fontMatrix[3] === 0) {
|
||||
warn('Invalid font matrix for font ' + fontRefName);
|
||||
}
|
||||
|
||||
var name = fontObj.loadedName || 'sans-serif';
|
||||
// The spec for Tf (setFont) says that 'size' specifies the font 'scale',
|
||||
// and in some docs this can be negative (inverted x-y axes).
|
||||
// We implement this condition with fontMatrix.
|
||||
if (size < 0) {
|
||||
size = -size;
|
||||
current.fontMatrix[0] *= -1;
|
||||
current.fontMatrix[3] *= -1;
|
||||
}
|
||||
|
||||
this.current.font = fontObj;
|
||||
this.current.fontSize = size;
|
||||
@ -595,7 +616,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var textHScale = current.textHScale;
|
||||
var fontMatrix = current.font.fontMatrix || IDENTITY_MATRIX;
|
||||
var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
|
||||
|
||||
ctx.transform.apply(ctx, current.textMatrix);
|
||||
ctx.scale(1, -1);
|
||||
@ -629,7 +650,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var charSpacing = current.charSpacing;
|
||||
var wordSpacing = current.wordSpacing;
|
||||
var textHScale = current.textHScale;
|
||||
var fontMatrix = font.fontMatrix || IDENTITY_MATRIX;
|
||||
var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
|
||||
var textHScale2 = textHScale * fontMatrix[0];
|
||||
var glyphsLength = glyphs.length;
|
||||
var textLayer = this.textLayer;
|
||||
@ -667,7 +688,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
var width = transformed[0] * fontSize + charSpacing;
|
||||
var width = transformed[0] * fontSize +
|
||||
Util.sign(current.fontMatrix[0]) * charSpacing;
|
||||
|
||||
ctx.translate(width, 0);
|
||||
current.x += width * textHScale;
|
||||
@ -693,44 +715,45 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
if (textSelection)
|
||||
text.geom = this.getTextGeometry();
|
||||
|
||||
var width = 0;
|
||||
var x = 0;
|
||||
for (var i = 0; i < glyphsLength; ++i) {
|
||||
var glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
width += wordSpacing;
|
||||
x += Util.sign(current.fontMatrix[0]) * wordSpacing;
|
||||
continue;
|
||||
}
|
||||
|
||||
var char = glyph.fontChar;
|
||||
var charWidth = glyph.width * fontSize * 0.001 + charSpacing;
|
||||
var charWidth = glyph.width * fontSize * 0.001 +
|
||||
Util.sign(current.fontMatrix[0]) * charSpacing;
|
||||
|
||||
switch (textRenderingMode) {
|
||||
default: // other unsupported rendering modes
|
||||
case TextRenderingMode.FILL:
|
||||
case TextRenderingMode.FILL_ADD_TO_PATH:
|
||||
ctx.fillText(char, width, 0);
|
||||
ctx.fillText(char, x, 0);
|
||||
break;
|
||||
case TextRenderingMode.STROKE:
|
||||
case TextRenderingMode.STROKE_ADD_TO_PATH:
|
||||
ctx.strokeText(char, width, 0);
|
||||
ctx.strokeText(char, x, 0);
|
||||
break;
|
||||
case TextRenderingMode.FILL_STROKE:
|
||||
case TextRenderingMode.FILL_STROKE_ADD_TO_PATH:
|
||||
ctx.fillText(char, width, 0);
|
||||
ctx.strokeText(char, width, 0);
|
||||
ctx.fillText(char, x, 0);
|
||||
ctx.strokeText(char, x, 0);
|
||||
break;
|
||||
case TextRenderingMode.INVISIBLE:
|
||||
break;
|
||||
}
|
||||
|
||||
width += charWidth;
|
||||
x += charWidth;
|
||||
|
||||
text.str += glyph.unicode === ' ' ? '\u00A0' : glyph.unicode;
|
||||
text.length++;
|
||||
text.canvasWidth += charWidth;
|
||||
}
|
||||
current.x += width * textHScale2;
|
||||
current.x += x * textHScale2;
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
@ -746,7 +769,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var fontSize = current.fontSize;
|
||||
var textHScale = current.textHScale;
|
||||
if (!font.coded)
|
||||
textHScale *= (font.fontMatrix || IDENTITY_MATRIX)[0];
|
||||
textHScale *= (current.fontMatrix || IDENTITY_MATRIX)[0];
|
||||
var arrLength = arr.length;
|
||||
var textLayer = this.textLayer;
|
||||
var text = {str: '', length: 0, canvasWidth: 0, geom: {}};
|
||||
|
@ -33,7 +33,9 @@ function getPdf(arg, callback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', params.url);
|
||||
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
|
||||
xhr.expected = (params.url.indexOf('file:') === 0) ? 0 : 200;
|
||||
var protocol = params.url.indexOf(':') < 0 ? window.location.protocol :
|
||||
params.url.substring(0, params.url.indexOf(':') + 1);
|
||||
xhr.expected = (protocol === 'http:' || protocol === 'https:') ? 200 : 0;
|
||||
|
||||
if ('progress' in params)
|
||||
xhr.onprogress = params.progress || undefined;
|
||||
|
@ -159,6 +159,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
// a Stream in the main thread.
|
||||
if (translated.file)
|
||||
translated.file = translated.file.getBytes();
|
||||
if (translated.properties.file) {
|
||||
translated.properties.file =
|
||||
translated.properties.file.getBytes();
|
||||
}
|
||||
|
||||
handler.send('obj', [
|
||||
loadedName,
|
||||
@ -783,11 +787,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
properties: properties
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// According to the spec if 'FontDescriptor' is declared, 'FirstChar',
|
||||
// 'LastChar' and 'Widths' should exists too, but some PDF encoders seems
|
||||
// 'LastChar' and 'Widths' should exist too, but some PDF encoders seem
|
||||
// to ignore this rule when a variant of a standart font is used.
|
||||
// TODO Fill the width array depending on which of the base font this is
|
||||
// a variant.
|
||||
|
10
src/fonts.js
@ -2619,7 +2619,13 @@ var Type1Parser = function type1Parser() {
|
||||
while (str[index++] != ']')
|
||||
count++;
|
||||
|
||||
var array = str.substr(start, count).split(' ');
|
||||
str = str.substr(start, count);
|
||||
|
||||
str = str.trim();
|
||||
// Remove adjacent spaces
|
||||
str = str.replace(/\s+/g, ' ');
|
||||
|
||||
var array = str.split(' ');
|
||||
for (var i = 0, ii = array.length; i < ii; i++)
|
||||
array[i] = parseFloat(array[i] || 0);
|
||||
return array;
|
||||
@ -3620,7 +3626,7 @@ var Type2CFF = (function Type2CFFClosure() {
|
||||
dict['cidOperatorPresent'] = true;
|
||||
break;
|
||||
default:
|
||||
TODO('interpret top dict key');
|
||||
TODO('interpret top dict key: ' + key);
|
||||
}
|
||||
}
|
||||
return dict;
|
||||
|
@ -111,6 +111,10 @@ var Util = (function UtilClosure() {
|
||||
];
|
||||
}
|
||||
|
||||
Util.sign = function sign(num) {
|
||||
return num < 0 ? -1 : 1;
|
||||
};
|
||||
|
||||
return Util;
|
||||
})();
|
||||
|
||||
|
@ -109,11 +109,27 @@ var WorkerMessageHandler = {
|
||||
// Pre compile the pdf page and fetch the fonts/images.
|
||||
IRQueue = page.getIRQueue(handler, dependency);
|
||||
} catch (e) {
|
||||
var minimumStackMessage =
|
||||
'worker.js: while trying to getPage() and getIRQueue()';
|
||||
|
||||
// Turn the error into an obj that can be serialized
|
||||
e = {
|
||||
message: typeof e === 'object' ? e.message : e,
|
||||
stack: typeof e === 'object' ? e.stack : null
|
||||
};
|
||||
if (typeof e === 'string') {
|
||||
e = {
|
||||
message: e,
|
||||
stack: minimumStackMessage
|
||||
};
|
||||
} else if (typeof e === 'object') {
|
||||
e = {
|
||||
message: e.message || e.toString(),
|
||||
stack: e.stack || minimumStackMessage
|
||||
};
|
||||
} else {
|
||||
e = {
|
||||
message: 'Unknown exception type: ' + (typeof e),
|
||||
stack: minimumStackMessage
|
||||
};
|
||||
}
|
||||
|
||||
handler.send('page_error', {
|
||||
pageNum: pageNum,
|
||||
error: e
|
||||
|
1
test/pdfs/issue1049.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://ernestinefont.com/wp-content/themes/iA3%201.2.1/assets/pdf/ErnestinePro-InfoGuide.pdf
|
@ -451,5 +451,12 @@
|
||||
"rounds": 1,
|
||||
"link": true,
|
||||
"type": "eq"
|
||||
},
|
||||
{ "id": "issue1049",
|
||||
"file": "pdfs/issue1049.pdf",
|
||||
"md5": "15473fffcdde9fb8f3756a4cf1aab347",
|
||||
"rounds": 1,
|
||||
"link": true,
|
||||
"type": "eq"
|
||||
}
|
||||
]
|
||||
|
@ -20,7 +20,8 @@
|
||||
height="48.000000px"
|
||||
width="48.000000px"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
version="1.1"
|
||||
viewbox="0 0 48 48">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
@ -16,7 +16,8 @@
|
||||
id="svg2994"
|
||||
height="48px"
|
||||
width="48px"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
viewbox="0 0 48 48">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
@ -16,7 +16,8 @@
|
||||
id="svg2913"
|
||||
height="48px"
|
||||
width="48px"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
viewbox="0 0 48 48">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@ -19,7 +19,8 @@
|
||||
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
|
||||
inkscape:export-xdpi="90.000000"
|
||||
inkscape:export-ydpi="90.000000"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
viewbox="0 0 48 48">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.2 KiB |
@ -19,7 +19,8 @@
|
||||
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
|
||||
inkscape:export-xdpi="90.000000"
|
||||
inkscape:export-ydpi="90.000000"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
viewbox="0 0 48 48">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
BIN
web/images/loading-icon.gif
Normal file
After Width: | Height: | Size: 2.5 KiB |
@ -16,7 +16,8 @@
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
|
||||
sodipodi:docname="list-add.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
viewbox="0 0 48 48">
|
||||
<defs
|
||||
id="defs6433">
|
||||
<inkscape:perspective
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@ -16,7 +16,8 @@
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
|
||||
sodipodi:docname="list-remove.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
viewbox="0 0 48 48">
|
||||
<defs
|
||||
id="defs6433">
|
||||
<inkscape:perspective
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@ -235,6 +235,16 @@ canvas {
|
||||
-webkit-box-shadow: 0px 2px 10px #ff0;
|
||||
}
|
||||
|
||||
.loadingIcon {
|
||||
position: absolute;
|
||||
display: block;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('images/loading-icon.gif') center no-repeat;
|
||||
}
|
||||
|
||||
.textLayer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
@ -88,16 +88,19 @@ var FirefoxCom = (function FirefoxComClosure() {
|
||||
})();
|
||||
|
||||
// Settings Manager - This is a utility for saving settings
|
||||
// First we see if localStorage is available, FF bug #495747
|
||||
// First we see if localStorage is available
|
||||
// If not, we use FUEL in FF
|
||||
var Settings = (function SettingsClosure() {
|
||||
var isLocalStorageEnabled = (function localStorageEnabledTest() {
|
||||
// Feature test as per http://diveintohtml5.info/storage.html
|
||||
// The additional localStorage call is to get around a FF quirk, see
|
||||
// bug #495747 in bugzilla
|
||||
try {
|
||||
localStorage;
|
||||
return 'localStorage' in window && window['localStorage'] !== null &&
|
||||
localStorage;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})();
|
||||
|
||||
var isFirefoxExtension = PDFJS.isFirefoxExtension;
|
||||
@ -134,6 +137,9 @@ var Settings = (function SettingsClosure() {
|
||||
|
||||
Settings.prototype = {
|
||||
set: function settingsSet(name, val) {
|
||||
if (!('file' in this))
|
||||
return false;
|
||||
|
||||
var file = this.file;
|
||||
file[name] = val;
|
||||
var database = JSON.stringify(this.database);
|
||||
@ -144,6 +150,9 @@ var Settings = (function SettingsClosure() {
|
||||
},
|
||||
|
||||
get: function settingsGet(name, defaultValue) {
|
||||
if (!('file' in this))
|
||||
return defaultValue;
|
||||
|
||||
return this.file[name] || defaultValue;
|
||||
}
|
||||
};
|
||||
@ -380,8 +389,14 @@ var PDFView = {
|
||||
|
||||
if (moreInfo) {
|
||||
errorMoreInfo.value += 'Message: ' + moreInfo.message;
|
||||
if (moreInfo.stack)
|
||||
if (moreInfo.stack) {
|
||||
errorMoreInfo.value += '\n' + 'Stack: ' + moreInfo.stack;
|
||||
} else {
|
||||
if (moreInfo.filename)
|
||||
errorMoreInfo.value += '\n' + 'File: ' + moreInfo.filename;
|
||||
if (moreInfo.lineNumber)
|
||||
errorMoreInfo.value += '\n' + 'Line: ' + moreInfo.lineNumber;
|
||||
}
|
||||
}
|
||||
errorMoreInfo.rows = errorMoreInfo.value.split('\n').length - 1;
|
||||
},
|
||||
@ -644,6 +659,10 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
div.removeAttribute('data-loaded');
|
||||
|
||||
delete this.canvas;
|
||||
|
||||
this.loadingIconDiv = document.createElement('div');
|
||||
this.loadingIconDiv.className = 'loadingIcon';
|
||||
div.appendChild(this.loadingIconDiv);
|
||||
};
|
||||
|
||||
function setupAnnotations(content, scale) {
|
||||
@ -808,7 +827,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
};
|
||||
|
||||
this.drawingRequired = function() {
|
||||
return !div.hasChildNodes();
|
||||
return !div.querySelector('canvas');
|
||||
};
|
||||
|
||||
this.draw = function pageviewDraw(callback) {
|
||||
@ -843,19 +862,23 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
||||
ctx.restore();
|
||||
ctx.translate(-this.x * scale, -this.y * scale);
|
||||
|
||||
stats.begin = Date.now();
|
||||
this.content.startRendering(ctx,
|
||||
(function pageViewDrawCallback(error) {
|
||||
if (error)
|
||||
PDFView.error('An error occurred while rendering the page.', error);
|
||||
this.updateStats();
|
||||
if (this.onAfterDraw)
|
||||
this.onAfterDraw();
|
||||
// Rendering area
|
||||
|
||||
cache.push(this);
|
||||
callback();
|
||||
}).bind(this), textLayer
|
||||
);
|
||||
var self = this;
|
||||
stats.begin = Date.now();
|
||||
this.content.startRendering(ctx, function pageViewDrawCallback(error) {
|
||||
div.removeChild(self.loadingIconDiv);
|
||||
|
||||
if (error)
|
||||
PDFView.error('An error occurred while rendering the page.', error);
|
||||
|
||||
self.updateStats();
|
||||
if (self.onAfterDraw)
|
||||
self.onAfterDraw();
|
||||
|
||||
cache.push(self);
|
||||
callback();
|
||||
}, textLayer);
|
||||
|
||||
setupAnnotations(this.content, this.scale);
|
||||
div.setAttribute('data-loaded', true);
|
||||
|