diff --git a/extensions/firefox/components/PdfStreamConverter.js b/extensions/firefox/components/PdfStreamConverter.js index 984915d23..bd3bfffcf 100644 --- a/extensions/firefox/components/PdfStreamConverter.js +++ b/extensions/firefox/components/PdfStreamConverter.js @@ -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; diff --git a/src/canvas.js b/src/canvas.js index d0b0064f6..f4815a655 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -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: {}}; diff --git a/src/core.js b/src/core.js index cb601398e..ae0f97231 100644 --- a/src/core.js +++ b/src/core.js @@ -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; diff --git a/src/evaluator.js b/src/evaluator.js index c70013d25..1597bed11 100644 --- a/src/evaluator.js +++ b/src/evaluator.js @@ -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. diff --git a/src/fonts.js b/src/fonts.js index 3f618b82a..b12707eb5 100644 --- a/src/fonts.js +++ b/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; diff --git a/src/util.js b/src/util.js index caa523ec7..f00fcd1ce 100644 --- a/src/util.js +++ b/src/util.js @@ -111,6 +111,10 @@ var Util = (function UtilClosure() { ]; } + Util.sign = function sign(num) { + return num < 0 ? -1 : 1; + }; + return Util; })(); diff --git a/src/worker.js b/src/worker.js index b81ff0540..3122d741e 100644 --- a/src/worker.js +++ b/src/worker.js @@ -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 diff --git a/test/pdfs/issue1049.pdf.link b/test/pdfs/issue1049.pdf.link new file mode 100644 index 000000000..c486dda43 --- /dev/null +++ b/test/pdfs/issue1049.pdf.link @@ -0,0 +1 @@ +http://ernestinefont.com/wp-content/themes/iA3%201.2.1/assets/pdf/ErnestinePro-InfoGuide.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index dd5c54147..3a1b5bd70 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -451,5 +451,12 @@ "rounds": 1, "link": true, "type": "eq" + }, + { "id": "issue1049", + "file": "pdfs/issue1049.pdf", + "md5": "15473fffcdde9fb8f3756a4cf1aab347", + "rounds": 1, + "link": true, + "type": "eq" } ] diff --git a/web/images/bookmark.svg b/web/images/bookmark.svg index 2c1fa130d..bee6efefd 100644 --- a/web/images/bookmark.svg +++ b/web/images/bookmark.svg @@ -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"> + inkscape:output_extension="org.inkscape.output.svg.inkscape" + viewbox="0 0 48 48"> + inkscape:output_extension="org.inkscape.output.svg.inkscape" + viewbox="0 0 48 48"> + inkscape:output_extension="org.inkscape.output.svg.inkscape" + viewbox="0 0 48 48"> + inkscape:output_extension="org.inkscape.output.svg.inkscape" + viewbox="0 0 48 48"> + inkscape:output_extension="org.inkscape.output.svg.inkscape" + viewbox="0 0 48 48"> + inkscape:output_extension="org.inkscape.output.svg.inkscape" + viewbox="0 0 48 48">