diff --git a/README.md b/README.md index 97db68d36..f12fce934 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,6 @@ -# pdf.js +# PDF.JS - -## Overview - pdf.js is an HTML5 technology experiment that explores building a faithful and efficient Portable Document Format (PDF) renderer without native code assistance. @@ -16,7 +13,7 @@ successful. -## Getting started +# Getting started ### Online demo @@ -29,11 +26,12 @@ using the pdf.js API. ### Extension -An up-to-date Firefox extension is also available: +A Firefox extension is also available: + http://mozilla.github.com/pdf.js/extensions/firefox/pdf.js.xpi -(The above link is updated upon every merge to our master branch). +Note that this extension is self-updating, and by default Firefox will auto-update extensions on a +daily basis (you can change this through the `extensions.update.interval` option in `about:config`). For an experimental Chrome extension, get the code as explained below and issue `make extension`. Then open Chrome with the flag `--enable-experimental-extension-apis`, go to `Tools > Extension` @@ -68,12 +66,12 @@ In order to bundle all `src/` files into a final `pdf.js`, issue: This will generate the file `build/pdf.js` that can be included in your final project. (WARNING: That's a large file! Consider minifying it). -## Learning +# Learning Here are some initial pointers to help contributors get off the ground. Additional resources are available in a separate section below. -#### Hello world +### Hello world For a "hello world" example, take a look at: @@ -82,7 +80,7 @@ For a "hello world" example, take a look at: This example illustrates the bare minimum ingredients for integrating pdf.js in a custom project. -#### Introductory video +### Introductory video Check out the presentation by our contributor Julian Viereck on the inner workings of PDF and pdf.js: @@ -92,7 +90,7 @@ workings of PDF and pdf.js: -## Contributing +# Contributing pdf.js is a community-driven project, so contributors are always welcome. Simply fork our repo and contribute away. Good starting places for picking @@ -122,7 +120,7 @@ You can add your name to it! :) -## Running the tests +# Running the tests pdf.js comes with browser-level regression tests that allow one to probe whether it's able to successfully parse PDFs, as well as compare its output @@ -148,7 +146,7 @@ images. The test type `load` simply tests whether the file loads without raising any errors. -## Running tests through our bot +### Running tests through our bot If you are a reviewer, you can use our remote bot to issue comprehensive tests against reference images before merging pull requests. @@ -158,7 +156,7 @@ See the bot repo for details: + https://github.com/mozilla/pdf.js-bot -## Additional resources +# Additional resources Gallery of user projects and modifications: @@ -188,7 +186,7 @@ Follow us on twitter: @pdfjs -## PDF-related resources +### PDF-related resources A really basic overview of PDF is described here: diff --git a/src/canvas.js b/src/canvas.js index 4feac4efe..5ef900861 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -48,6 +48,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() { // Note: fill alpha applies to all non-stroking operations this.fillAlpha = 1; this.strokeAlpha = 1; + this.lineWidth = 1; this.old = old; } @@ -329,6 +330,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { // Graphics state setLineWidth: function canvasGraphicsSetLineWidth(width) { + this.current.lineWidth = width; this.ctx.lineWidth = width; }, setLineCap: function canvasGraphicsSetLineCap(style) { @@ -442,6 +444,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { consumePath = typeof consumePath !== 'undefined' ? consumePath : true; var ctx = this.ctx; var strokeColor = this.current.strokeColor; + if (this.current.lineWidth === 0) + ctx.lineWidth = this.getSinglePixelWidth(); // For stroke we want to temporarily change the global alpha to the // stroking alpha. ctx.globalAlpha = this.current.strokeAlpha; @@ -640,7 +644,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { ctx.translate(current.x, current.y); ctx.scale(textHScale, 1); - ctx.lineWidth /= current.textMatrix[0]; if (textSelection) { this.save(); @@ -677,7 +680,15 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { } else { ctx.save(); this.applyTextTransforms(); - ctx.lineWidth /= current.textMatrix[0] * fontMatrix[0]; + + var lineWidth = current.lineWidth; + var scale = Math.abs(current.textMatrix[0] * fontMatrix[0]); + if (scale == 0 || lineWidth == 0) + lineWidth = this.getSinglePixelWidth(); + else + lineWidth /= scale; + + ctx.lineWidth = lineWidth; if (textSelection) text.geom = this.getTextGeometry(); @@ -1142,6 +1153,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { }, restoreFillRule: function canvasGraphicsRestoreFillRule(rule) { this.ctx.mozFillRule = rule; + }, + getSinglePixelWidth: function getSinglePixelWidth(scale) { + var inverse = this.ctx.mozCurrentTransformInverse; + return Math.abs(inverse[0] + inverse[2]); } }; diff --git a/src/fonts.js b/src/fonts.js index 616521a16..f96c15458 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -3340,15 +3340,9 @@ var Type2CFF = (function Type2CFFClosure() { inverseEncoding[encoding[charcode]] = charcode | 0; for (var i = 0, ii = charsets.length; i < ii; i++) { var glyph = charsets[i]; - if (glyph == '.notdef') { - charstrings.push({ - unicode: 0, - code: 0, - gid: i, - glyph: glyph - }); + if (glyph == '.notdef') continue; - } + var code = inverseEncoding[i]; if (!code || isSpecialUnicode(code)) { unassignedUnicodeItems.push(i); diff --git a/src/parser.js b/src/parser.js index fec71f915..4a884e0d4 100644 --- a/src/parser.js +++ b/src/parser.js @@ -253,6 +253,9 @@ var Parser = (function ParserClosure() { if (name == 'CCITTFaxDecode' || name == 'CCF') { return new CCITTFaxStream(stream, params); } + if (name == 'RunLengthDecode') { + return new RunLengthStream(stream); + } warn('filter "' + name + '" not supported yet'); return stream; } diff --git a/src/stream.js b/src/stream.js index cff83357a..610a54d38 100644 --- a/src/stream.js +++ b/src/stream.js @@ -1142,6 +1142,51 @@ var AsciiHexStream = (function AsciiHexStreamClosure() { return AsciiHexStream; })(); +var RunLengthStream = (function RunLengthStreamClosure() { + function RunLengthStream(str) { + this.str = str; + this.dict = str.dict; + + DecodeStream.call(this); + } + + RunLengthStream.prototype = Object.create(DecodeStream.prototype); + + RunLengthStream.prototype.readBlock = function runLengthStreamReadBlock() { + // The repeatHeader has following format. The first byte defines type of run + // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes + // (in addition to the second byte from the header), n = 129 through 255 - + // duplicate the second byte from the header (257 - n) times, n = 128 - end. + var repeatHeader = this.str.getBytes(2); + if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] == 128) { + this.eof = true; + return; + } + + var bufferLength = this.bufferLength; + var n = repeatHeader[0]; + if (n < 128) { + // copy n bytes + var buffer = this.ensureBuffer(bufferLength + n + 1); + buffer[bufferLength++] = repeatHeader[1]; + if (n > 0) { + var source = this.str.getBytes(n); + buffer.set(source, bufferLength); + bufferLength += n; + } + } else { + n = 257 - n; + var b = repeatHeader[1]; + var buffer = this.ensureBuffer(bufferLength + n + 1); + for (var i = 0; i < n; i++) + buffer[bufferLength++] = b; + } + this.bufferLength = bufferLength; + }; + + return RunLengthStream; +})(); + var CCITTFaxStream = (function CCITTFaxStreamClosure() { var ccittEOL = -2; diff --git a/test/.gitignore b/test/.gitignore index e69de29bb..9fec7b584 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -0,0 +1,3 @@ +ref/ +tmp/ + diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 2817f17d3..e0926492b 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -23,3 +23,4 @@ !smaskdim.pdf !type4psfunc.pdf !S2.pdf +!zerowidthline.pdf diff --git a/test/pdfs/zerowidthline.pdf b/test/pdfs/zerowidthline.pdf new file mode 100644 index 000000000..379f18049 Binary files /dev/null and b/test/pdfs/zerowidthline.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index fce77e0b2..5bc344abf 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -176,7 +176,6 @@ "md5": "eb7b224107205db4fea9f7df0185f77d", "link": true, "rounds": 1, - "skipPages": [12,31], "type": "eq" }, { "id": "fips197", @@ -423,5 +422,12 @@ "rounds": 1, "link": true, "type": "eq" + }, + { "id": "zerowidthline", + "file": "pdfs/zerowidthline.pdf", + "md5": "295d26e61a85635433f8e4b768953f60", + "rounds": 1, + "link": false, + "type": "eq" } ]