From 11a1ebaada2de99c3cb9a4c17728c3f04bbb893e Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 21 Jun 2011 21:11:59 +0200 Subject: [PATCH 01/11] Start displaying TrueType fonts --- fonts.js | 10 +++++----- pdf.js | 9 +++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/fonts.js b/fonts.js index ad3d4fd35..80a9f4bc2 100644 --- a/fonts.js +++ b/fonts.js @@ -103,7 +103,7 @@ var Font = (function () { // If the font is to be ignored, register it like an already loaded font // to avoid the cost of waiting for it be be loaded by the platform. - if (properties.ignore || properties.type == "TrueType" || kDisableFonts) { + if (properties.ignore || kDisableFonts) { Fonts[name] = { data: file, loading: false, @@ -368,11 +368,11 @@ var Font = (function () { var length = FontsUtils.bytesToInteger(file.getBytes(4)); // Read the table associated data - var currentPosition = file.pos; - file.pos = file.start + offset; - + var previousPosition = file.pos; + file.pos = file.start ? file.start : 0; + file.skip(offset); var data = file.getBytes(length); - file.pos = currentPosition; + file.pos = previousPosition; return { tag: tag, diff --git a/pdf.js b/pdf.js index 4db4ef06f..8268f1673 100644 --- a/pdf.js +++ b/pdf.js @@ -2199,8 +2199,13 @@ var CanvasGraphics = (function() { var tokens = []; var token = ""; - var buffer = cmapObj.ensureBuffer ? cmapObj.ensureBuffer() : cmapObj; - var cmap = cmapObj.getBytes(buffer.byteLength); + var length = cmapObj.length; + if (cmapObj instanceof FlateStream) { + cmapObj.readBlock(); + length = cmapObj.bufferLength; + } + + var cmap = cmapObj.getBytes(length); for (var i =0; i < cmap.length; i++) { var byte = cmap[i]; if (byte == 0x20 || byte == 0x0A || byte == 0x3C || byte == 0x3E) { From fdfd03b671c479e10ab44461a5ba510b33d2128f Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Wed, 22 Jun 2011 04:41:31 +0200 Subject: [PATCH 02/11] Support Format 6 cmap table, but does not pass the sanitizer yet --- fonts.js | 59 ++++++++++++++++++++++++++++++++++++++++++-------------- pdf.js | 4 +--- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/fonts.js b/fonts.js index 80a9f4bc2..f5a531785 100644 --- a/fonts.js +++ b/fonts.js @@ -242,7 +242,7 @@ var Font = (function () { return ranges; }; - function createCMAPTable(glyphs) { + function createCMapTable(glyphs) { var ranges = getRanges(glyphs); var headerSize = (12 * 2 + (ranges.length * 4 * 2)); @@ -274,7 +274,7 @@ var Font = (function () { var bias = 0; for (var i = 0; i < segCount - 1; i++) { var range = ranges[i]; - var start = range[0]; + var start = range[0]; var end = range[1]; var delta = (((start - 1) - bias) ^ 0xffff) + 1; bias += (end - start + 1); @@ -393,6 +393,47 @@ var Font = (function () { } }; + function replaceCMapTable(font, properties) { + var version = FontsUtils.bytesToInteger(font.getBytes(2)); + var numTables = FontsUtils.bytesToInteger(font.getBytes(2)); + + var tables = []; + for (var i = 0; i < numTables; i++) { + var platformID = FontsUtils.bytesToInteger(font.getBytes(2)); + var encodingID = FontsUtils.bytesToInteger(font.getBytes(2)); + var offset = FontsUtils.bytesToInteger(font.getBytes(4)); + var format = FontsUtils.bytesToInteger(font.getBytes(2)); + var length = FontsUtils.bytesToInteger(font.getBytes(2)); + var language = FontsUtils.bytesToInteger(font.getBytes(2)); + + if (format == 0 && numTables == 1) { + // Format 0 alone is not allowed by the sanitizer so let's rewrite + // that to a 3-1-4 Unicode BMP table + var charset = properties.charset; + var glyphs = []; + for (var i = 0; i < charset.length; i++) { + glyphs.push({ + unicode: GlyphsUnicode[charset[i]] || 0 + }); + } + + cmap.data = createCMapTable(glyphs); + } else if (format == 6 && numTables == 1) { + // Format 6 is a 2-bytes dense mapping, which means the font data + // lives glue together even if they are pretty far in the unicode + // table. (This looks weird, so I can have missed something) + var firstCode = FontsUtils.bytesToInteger(font.getBytes(2)); + var entryCount = FontsUtils.bytesToInteger(font.getBytes(2)); + + var encoding = properties.encoding; + for (var j = 0; j < entryCount; j++) { + var charcode = FontsUtils.bytesToInteger(font.getBytes(2)); + encoding[charcode + firstCode] = charcode + firstCode; + } + } + } + }; + // Check that required tables are present var requiredTables = [ "OS/2", "cmap", "head", "hhea", "hmtx", "maxp", "name", "post" ]; @@ -448,18 +489,8 @@ var Font = (function () { data: OS2 }); - // If the font is missing a OS/2 table it's could be an old mac font - // without a 3-1-4 Unicode BMP table, so let's rewrite it. - var charset = properties.charset; - var glyphs = []; - for (var i = 0; i < charset.length; i++) { - glyphs.push({ - unicode: GlyphsUnicode[charset[i]] - }); - } - // Replace the old CMAP table with a shiny new one - cmap.data = createCMAPTable(glyphs); + replaceCMapTable(font, properties); // Rewrite the 'post' table if needed if (!post) { @@ -599,7 +630,7 @@ var Font = (function () { var charstrings = font.getOrderedCharStrings(properties.glyphs); /** CMAP */ - cmap = createCMAPTable(charstrings); + cmap = createCMapTable(charstrings); createTableEntry(otf, offsets, "cmap", cmap); /** HEAD */ diff --git a/pdf.js b/pdf.js index 8268f1673..72a7b7970 100644 --- a/pdf.js +++ b/pdf.js @@ -2193,8 +2193,6 @@ var CanvasGraphics = (function() { } else if (IsStream(cmapObj)) { var encoding = Encodings["WinAnsiEncoding"]; var firstChar = xref.fetchIfRef(fontDict.get("FirstChar")); - for (var i = firstChar; i < encoding.length; i++) - encodingMap[i] = new Name(encoding[i]); var tokens = []; var token = ""; @@ -2538,7 +2536,7 @@ var CanvasGraphics = (function() { } this.current.fontSize = size; - this.ctx.font = this.current.fontSize +'px "' + fontName + '"'; + this.ctx.font = this.current.fontSize +'px "' + fontName + '", Symbol'; }, setTextRenderingMode: function(mode) { TODO("text rendering mode"); From 00df9b82eed490d5807fbd57cf0f36004f5d6da1 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Wed, 22 Jun 2011 07:46:41 +0200 Subject: [PATCH 03/11] Start of a TTF Format6 to Format4 converter (sigh) --- fonts.js | 30 ++++++++++++++++++++---------- pdf.js | 7 +++++-- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/fonts.js b/fonts.js index f5a531785..c7230a55a 100644 --- a/fonts.js +++ b/fonts.js @@ -284,8 +284,8 @@ var Font = (function () { idDeltas += string16(delta); idRangeOffsets += string16(0); - for (var j = start; j <= end; j++) - glyphsIds += String.fromCharCode(j); + for (var j = 0; j < range.length; j++) + glyphsIds += String.fromCharCode(range[j]); } startCount += "\xFF\xFF"; @@ -393,11 +393,10 @@ var Font = (function () { } }; - function replaceCMapTable(font, properties) { + function replaceCMapTable(cmap, font, properties) { var version = FontsUtils.bytesToInteger(font.getBytes(2)); var numTables = FontsUtils.bytesToInteger(font.getBytes(2)); - var tables = []; for (var i = 0; i < numTables; i++) { var platformID = FontsUtils.bytesToInteger(font.getBytes(2)); var encodingID = FontsUtils.bytesToInteger(font.getBytes(2)); @@ -406,14 +405,15 @@ var Font = (function () { var length = FontsUtils.bytesToInteger(font.getBytes(2)); var language = FontsUtils.bytesToInteger(font.getBytes(2)); - if (format == 0 && numTables == 1) { + if ((format == 0 && numTables == 1) || + (format == 6 && numTables == 1 && !properties.encoding.empty)) { // Format 0 alone is not allowed by the sanitizer so let's rewrite // that to a 3-1-4 Unicode BMP table var charset = properties.charset; var glyphs = []; - for (var i = 0; i < charset.length; i++) { + for (var j = 0; j < charset.length; j++) { glyphs.push({ - unicode: GlyphsUnicode[charset[i]] || 0 + unicode: GlyphsUnicode[charset[j]] || 0 }); } @@ -421,15 +421,25 @@ var Font = (function () { } else if (format == 6 && numTables == 1) { // Format 6 is a 2-bytes dense mapping, which means the font data // lives glue together even if they are pretty far in the unicode - // table. (This looks weird, so I can have missed something) + // table. (This looks weird, so I can have missed something), this + // works on Linux but seems to fails on Mac so let's rewrite the + // cmap table to a 3-1-4 style var firstCode = FontsUtils.bytesToInteger(font.getBytes(2)); var entryCount = FontsUtils.bytesToInteger(font.getBytes(2)); var encoding = properties.encoding; + var glyphs = []; for (var j = 0; j < entryCount; j++) { var charcode = FontsUtils.bytesToInteger(font.getBytes(2)); - encoding[charcode + firstCode] = charcode + firstCode; + glyphs.push({unicode: charcode + firstCode }); } + + var ranges = getRanges(glyphs); + var denseRange = ranges[0]; + var pos = 0; + for (var j = denseRange[0]; j <= denseRange[1]; j++) + encoding[j - 1] = glyphs[pos++].unicode; + cmap.data = createCMapTable(glyphs); } } }; @@ -490,7 +500,7 @@ var Font = (function () { }); // Replace the old CMAP table with a shiny new one - replaceCMapTable(font, properties); + replaceCMapTable(cmap, font, properties); // Rewrite the 'post' table if needed if (!post) { diff --git a/pdf.js b/pdf.js index 72a7b7970..9d06241f7 100644 --- a/pdf.js +++ b/pdf.js @@ -2143,7 +2143,7 @@ var CanvasGraphics = (function() { // Fonts with an embedded cmap but without any assignment in // it are not yet supported, so ask the fonts loader to ignore // them to not pay a stupid one sec latence. - var ignoreFont = true; + var ignoreFont = false; var encodingMap = {}; var charset = []; @@ -2187,6 +2187,7 @@ var CanvasGraphics = (function() { } } } else if (fontDict.has("ToUnicode")) { + encodingMap = {empty: true}; var cmapObj = xref.fetchIfRef(fontDict.get("ToUnicode")); if (IsName(cmapObj)) { error("ToUnicode file cmap translation not implemented"); @@ -2230,7 +2231,9 @@ var CanvasGraphics = (function() { var code = parseInt("0x" + tokens[j+2]); for (var k = startRange; k <= endRange; k++) { - encodingMap[k] = GlyphsUnicode[encoding[code]]; + // The encoding mapping table will be filled + // later during the building phase + //encodingMap[k] = GlyphsUnicode[encoding[code]]; charset.push(encoding[code++]); } } From e0c98ba3c6e562c8da611aaa1a3c411b106d3475 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Wed, 22 Jun 2011 10:56:31 +0200 Subject: [PATCH 04/11] Enhance the converter code by filling Format 6 dense array gaps --- fonts.js | 31 ++++++++++++++++++++++++++----- pdf.js | 2 +- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/fonts.js b/fonts.js index c7230a55a..ded1b70c2 100644 --- a/fonts.js +++ b/fonts.js @@ -427,18 +427,39 @@ var Font = (function () { var firstCode = FontsUtils.bytesToInteger(font.getBytes(2)); var entryCount = FontsUtils.bytesToInteger(font.getBytes(2)); + // Since Format 6 is a dense array, check for gaps in the indexes + // to fill them later if needed + var gaps = []; + for (var j = 1; j <= entryCount; j++) + gaps.push(j); + var encoding = properties.encoding; var glyphs = []; for (var j = 0; j < entryCount; j++) { var charcode = FontsUtils.bytesToInteger(font.getBytes(2)); - glyphs.push({unicode: charcode + firstCode }); + var index = gaps.indexOf(charcode); + if (index != -1) + gaps.splice(index, 1); + + glyphs.push({unicode: charcode + firstCode}); } + while (gaps.length) + glyphs.push({unicode: gaps.pop() + firstCode }); + var ranges = getRanges(glyphs); - var denseRange = ranges[0]; - var pos = 0; - for (var j = denseRange[0]; j <= denseRange[1]; j++) - encoding[j - 1] = glyphs[pos++].unicode; + + var pos = firstCode; + var bias = 1; + for (var j = 0; j < ranges.length; j++) { + var range = ranges[j]; + var start = range[0]; + var end = range[1]; + for (var k = start; k < end; k++) { + encoding[pos] = glyphs[pos - firstCode].unicode; + pos++; + } + } cmap.data = createCMapTable(glyphs); } } diff --git a/pdf.js b/pdf.js index 9d06241f7..23dd5bee9 100644 --- a/pdf.js +++ b/pdf.js @@ -2234,7 +2234,7 @@ var CanvasGraphics = (function() { // The encoding mapping table will be filled // later during the building phase //encodingMap[k] = GlyphsUnicode[encoding[code]]; - charset.push(encoding[code++]); + charset.push(encoding[code++] || ".notdef"); } } break; From a772c9a2e2c40abdc52aa266fc67b4ecfaa3ea00 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Wed, 22 Jun 2011 11:25:00 +0200 Subject: [PATCH 05/11] Fill more gaps for Format 6 dense array --- fonts.js | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/fonts.js b/fonts.js index ded1b70c2..a008dfce0 100644 --- a/fonts.js +++ b/fonts.js @@ -427,39 +427,37 @@ var Font = (function () { var firstCode = FontsUtils.bytesToInteger(font.getBytes(2)); var entryCount = FontsUtils.bytesToInteger(font.getBytes(2)); - // Since Format 6 is a dense array, check for gaps in the indexes - // to fill them later if needed - var gaps = []; - for (var j = 1; j <= entryCount; j++) - gaps.push(j); - - var encoding = properties.encoding; var glyphs = []; + var min = 0xffff, max = 0; for (var j = 0; j < entryCount; j++) { var charcode = FontsUtils.bytesToInteger(font.getBytes(2)); - var index = gaps.indexOf(charcode); - if (index != -1) - gaps.splice(index, 1); + glyphs.push(charcode); - glyphs.push({unicode: charcode + firstCode}); + if (charcode < min) + min = charcode; + if (charcode > max) + max = charcode; } - while (gaps.length) - glyphs.push({unicode: gaps.pop() + firstCode }); - - var ranges = getRanges(glyphs); - - var pos = firstCode; - var bias = 1; - for (var j = 0; j < ranges.length; j++) { - var range = ranges[j]; - var start = range[0]; - var end = range[1]; - for (var k = start; k < end; k++) { - encoding[pos] = glyphs[pos - firstCode].unicode; - pos++; - } + // Since Format 6 is a dense array, check for gaps + for (var j = min; j < max; j++) { + if (glyphs.indexOf(j) == -1) + glyphs.push(j); } + + for (var j = 0; j < glyphs.length; j++) + glyphs[j] = { unicode: glyphs[j] + firstCode }; + + var ranges= getRanges(glyphs); + assert(ranges.length == 1, "Got " + ranges.length + " ranges in a dense array"); + + var encoding = properties.encoding; + var denseRange = ranges[0]; + var start = denseRange[0]; + var end = denseRange[1]; + var index = firstCode; + for (var j = start; j <= end; j++) + encoding[index++] = glyphs[j - firstCode - 1].unicode; cmap.data = createCMapTable(glyphs); } } From 4ae16721fad131dc08994e149c6640ae65117e9f Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 22 Jun 2011 18:37:58 -0700 Subject: [PATCH 06/11] actually wait for fonts to be loaded, and write out a log of failed eq comparisons --- test.py | 25 +++++++++++++++++- test_slave.html | 68 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/test.py b/test.py index 0c326ec09..26a86b6dd 100644 --- a/test.py +++ b/test.py @@ -9,6 +9,7 @@ def prompt(question): ANAL = True DEFAULT_MANIFEST_FILE = 'test_manifest.json' +EQLOG_FILE = 'eq.log' REFDIR = 'ref' TMPDIR = 'tmp' VERBOSE = False @@ -35,6 +36,7 @@ class State: numEqNoSnapshot = 0 numFBFFailures = 0 numLoadFailures = 0 + eqLog = None class Result: def __init__(self, snapshot, failure): @@ -190,6 +192,7 @@ def check(task, results, browser): def checkEq(task, results, browser): pfx = os.path.join(REFDIR, sys.platform, browser, task['id']) results = results[0] + taskId = task['id'] passed = True for page in xrange(len(results)): @@ -208,7 +211,21 @@ def checkEq(task, results, browser): eq = (ref == snapshot) if not eq: - print 'TEST-UNEXPECTED-FAIL | eq', task['id'], '| in', browser, '| rendering of page', page + 1, '!= reference rendering' + print 'TEST-UNEXPECTED-FAIL | eq', taskId, '| in', browser, '| rendering of page', page + 1, '!= reference rendering' + # XXX need to dump this always, somehow, when we have + # the reference repository + if State.masterMode: + if not State.eqLog: + State.eqLog = open(EQLOG_FILE, 'w') + eqLog = State.eqLog + + # NB: this follows the format of Mozilla reftest + # output so that we can reuse its reftest-analyzer + # script + print >>eqLog, 'REFTEST TEST-UNEXPECTED-FAIL |', browser +'-'+ taskId +'-page'+ str(page + 1), '| image comparison (==)' + print >>eqLog, 'REFTEST IMAGE 1 (TEST):', snapshot + print >>eqLog, 'REFTEST IMAGE 2 (REFERENCE):', ref + passed = False State.numEqFailures += 1 @@ -292,6 +309,12 @@ def main(args): masterMode = (args[0] == '-m') manifestFile = args[0] if not masterMode else manifestFile + + + masterMode = True + + + setUp(manifestFile, masterMode) server = HTTPServer(('127.0.0.1', 8080), PDFTestHandler) diff --git a/test_slave.html b/test_slave.html index 06b911810..718e887e0 100644 --- a/test_slave.html +++ b/test_slave.html @@ -1,6 +1,7 @@ pdf.js test slave + @@ -31,7 +32,7 @@ function load() { stdout = document.getElementById("stdout"); log("Harness thinks this browser is '"+ browser +"'\n"); - log("Fetching manifest ..."); + log("Fetching manifest "+ manifestFile +"..."); var r = new XMLHttpRequest(); r.open("GET", manifestFile, false); @@ -81,38 +82,69 @@ function nextPage() { } failure = ''; - log(" drawing page "+ currentTask.pageNum +"..."); + log(" loading page "+ currentTask.pageNum +"... "); var ctx = canvas.getContext("2d"); clear(ctx); var fonts = []; + var fontsReady = true; var gfx = new CanvasGraphics(ctx); try { currentPage = pdfDoc.getPage(currentTask.pageNum); currentPage.compile(gfx, fonts); + + // Inspect fonts and translate the missing ones + var count = fonts.length; + for (var i = 0; i < count; ++i) { + var font = fonts[i]; + if (Fonts[font.name]) { + fontsReady = fontsReady && !Fonts[font.name].loading; + continue; + } + new Font(font.name, font.file, font.properties); + fontsReady = false; + } } catch(e) { failure = 'compile: '+ e.toString(); } - // TODO load fonts - setTimeout(function() { - if (!failure) { - try { - currentPage.display(gfx); - } catch(e) { - failure = 'render: '+ e.toString(); - } + var checkFontsLoadedIntervalTimer = null; + function checkFontsLoaded() { + for (var i = 0; i < count; i++) { + if (Fonts[font.name].loading) { + return; } - currentTask.taskDone = (currentTask.pageNum == pdfDoc.numPages - && (1 + currentTask.round) == currentTask.rounds); - sendTaskResult(canvas.toDataURL("image/png")); - log("done"+ (failure ? " (failed!)" : "") +"\n"); + } + window.clearInterval(checkFontsLoadedIntervalTimer); - ++currentTask.pageNum, nextPage(); - }, - 0 - ); + snapshotCurrentPage(gfx); + } + + if (failure || fontsReady) { + snapshotCurrentPage(gfx); + } else { + checkFontsLoadedIntervalTimer = setInterval(checkFontsLoaded, 10); + } +} + +function snapshotCurrentPage(gfx) { + log("done, snapshotting... "); + + if (!failure) { + try { + currentPage.display(gfx); + } catch(e) { + failure = 'render: '+ e.toString(); + } + } + + currentTask.taskDone = (currentTask.pageNum == pdfDoc.numPages + && (1 + currentTask.round) == currentTask.rounds); + sendTaskResult(canvas.toDataURL("image/png")); + log("done"+ (failure ? " (failed!)" : "") +"\n"); + + ++currentTask.pageNum, nextPage(); } function done() { From 2ad48898682e6c8f043e5c2317ccd30a3094eeb4 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 22 Jun 2011 18:40:20 -0700 Subject: [PATCH 07/11] remove debugging code --- test.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test.py b/test.py index 26a86b6dd..2d4a3e0f2 100644 --- a/test.py +++ b/test.py @@ -309,12 +309,6 @@ def main(args): masterMode = (args[0] == '-m') manifestFile = args[0] if not masterMode else manifestFile - - - masterMode = True - - - setUp(manifestFile, masterMode) server = HTTPServer(('127.0.0.1', 8080), PDFTestHandler) From 57e7e798a63ff54b19fffd2b67c3d3b55f06fad5 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 22 Jun 2011 18:50:38 -0700 Subject: [PATCH 08/11] fix strict-mode violations in chrome --- fonts.js | 6 +++--- pdf.js | 50 +++++++++++++++++++++++++------------------------- test.py | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/fonts.js b/fonts.js index a008dfce0..d5943b7a3 100644 --- a/fonts.js +++ b/fonts.js @@ -495,7 +495,7 @@ var Font = (function () { if (requiredTables.length && requiredTables[0] == "OS/2") { // Create a new file to hold the new version of our truetype with a new // header and new offsets - var ttf = Uint8Array(kMaxFontFileSize); + var ttf = new Uint8Array(kMaxFontFileSize); // The offsets object holds at the same time a representation of where // to write the table entry information about a table and another offset @@ -581,7 +581,7 @@ var Font = (function () { }, convert: function font_convert(name, font, properties) { - var otf = Uint8Array(kMaxFontFileSize); + var otf = new Uint8Array(kMaxFontFileSize); function createNameTable(name) { var names = [ @@ -1148,7 +1148,7 @@ var Type1Parser = function() { * The CFF class takes a Type1 file and wrap it into a 'Compact Font Format', * which itself embed Type2 charstrings. */ -const CFFStrings = [ +var CFFStrings = [ ".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand", "quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period", "slash","zero","one","two","three","four","five","six","seven","eight","nine", diff --git a/pdf.js b/pdf.js index 39e9e26df..5d9caf490 100644 --- a/pdf.js +++ b/pdf.js @@ -58,7 +58,7 @@ function bytesToString(bytes) { var Stream = (function() { function constructor(arrayBuffer, start, length, dict) { - this.bytes = Uint8Array(arrayBuffer); + this.bytes = new Uint8Array(arrayBuffer); this.start = start || 0; this.pos = this.start; this.end = (start + length) || this.bytes.length; @@ -125,7 +125,7 @@ var Stream = (function() { var StringStream = (function() { function constructor(str) { var length = str.length; - var bytes = Uint8Array(length); + var bytes = new Uint8Array(length); for (var n = 0; n < length; ++n) bytes[n] = str.charCodeAt(n); Stream.call(this, bytes); @@ -154,7 +154,7 @@ var DecodeStream = (function() { var size = 512; while (size < requested) size <<= 1; - var buffer2 = Uint8Array(size); + var buffer2 = new Uint8Array(size); for (var i = 0; i < current; ++i) buffer2[i] = buffer[i]; return this.buffer = buffer2; @@ -222,11 +222,11 @@ var DecodeStream = (function() { var FlateStream = (function() { - const codeLenCodeMap = Uint32Array([ + var codeLenCodeMap = new Uint32Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]); - const lengthDecode = Uint32Array([ + var lengthDecode = new Uint32Array([ 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, @@ -234,7 +234,7 @@ var FlateStream = (function() { 0x00102, 0x00102, 0x00102 ]); - const distDecode = Uint32Array([ + var distDecode = new Uint32Array([ 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, @@ -242,7 +242,7 @@ var FlateStream = (function() { 0xd4001, 0xd6001 ]); - const fixedLitCodeTab = [Uint32Array([ + var fixedLitCodeTab = [new Uint32Array([ 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, @@ -319,7 +319,7 @@ var FlateStream = (function() { 0x900ff ]), 9]; - const fixedDistCodeTab = [Uint32Array([ + var fixedDistCodeTab = [new Uint32Array([ 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, @@ -410,7 +410,7 @@ var FlateStream = (function() { // build the table var size = 1 << maxLen; - var codes = Uint32Array(size); + var codes = new Uint32Array(size); for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) { @@ -782,8 +782,8 @@ var Ascii85Stream = (function() { constructor.prototype = Object.create(DecodeStream.prototype); constructor.prototype.readBlock = function() { - const tildaCode = "~".charCodeAt(0); - const zCode = "z".charCodeAt(0); + var tildaCode = "~".charCodeAt(0); + var zCode = "z".charCodeAt(0); var str = this.str; var c = str.getByte(); @@ -1001,10 +1001,10 @@ var Lexer = (function() { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx ]; - const MIN_INT = (1<<31) | 0; - const MAX_INT = (MIN_INT - 1) | 0; - const MIN_UINT = 0; - const MAX_UINT = ((1<<30) * 4) - 1; + var MIN_INT = (1<<31) | 0; + var MAX_INT = (MIN_INT - 1) | 0; + var MIN_UINT = 0; + var MAX_UINT = ((1<<30) * 4) - 1; function ToHexDigit(ch) { if (ch >= "0" && ch <= "9") @@ -2031,7 +2031,7 @@ var PDFDoc = (function() { return constructor; })(); -const IDENTITY_MATRIX = [ 1, 0, 0, 1, 0, 0 ]; +var IDENTITY_MATRIX = [ 1, 0, 0, 1, 0, 0 ]; // contexts store most of the state we need natively. // However, PDF needs a bit more state, which we store here. @@ -2055,7 +2055,7 @@ var CanvasExtraState = (function() { return constructor; })(); -const Encodings = { +var Encodings = { get ExpertEncoding() { return shadow(this, "ExpertEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, "space","exclamsmall","Hungarumlautsmall",,"dollaroldstyle","dollarsuperior", @@ -2333,13 +2333,13 @@ var CanvasGraphics = (function() { }; } - const LINE_CAP_STYLES = [ "butt", "round", "square" ]; - const LINE_JOIN_STYLES = [ "miter", "round", "bevel" ]; - const NORMAL_CLIP = {}; - const EO_CLIP = {}; + var LINE_CAP_STYLES = [ "butt", "round", "square" ]; + var LINE_JOIN_STYLES = [ "miter", "round", "bevel" ]; + var NORMAL_CLIP = {}; + var EO_CLIP = {}; // Used for tiling patterns - const PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; + var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; constructor.prototype = { translateFont: function(fontDict, xref, resources) { @@ -2874,7 +2874,7 @@ var CanvasGraphics = (function() { var pattern = xref.fetchIfRef(patternRes.get(patternName.name)); var patternDict = IsStream(pattern) ? pattern.dict : pattern; - const types = [null, this.tilingFill, + var types = [null, this.tilingFill, function() { TODO("Shading Patterns"); }]; var typeNum = patternDict.get("PatternType"); var patternFn = types[typeNum]; @@ -3023,7 +3023,7 @@ var CanvasGraphics = (function() { if (background) TODO("handle background colors"); - const types = [null, + var types = [null, this.fillFunctionShading, this.fillAxialShading, this.fillRadialShading]; @@ -3460,7 +3460,7 @@ var PDFFunction = (function() { if (!dict) dict = fn; - const types = [this.constructSampled, + var types = [this.constructSampled, null, this.constructInterpolated, this.constructStiched, diff --git a/test.py b/test.py index 2d4a3e0f2..1557714d6 100644 --- a/test.py +++ b/test.py @@ -17,7 +17,7 @@ VERBOSE = False MIMEs = { '.css': 'text/css', '.html': 'text/html', - '.js': 'application/json', + '.js': 'application/javascript', '.json': 'application/json', '.pdf': 'application/pdf', '.xhtml': 'application/xhtml+xml', From d610397d1e4ec6500da543e7a866a957ccc629f7 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 22 Jun 2011 19:20:03 -0700 Subject: [PATCH 09/11] fake stream for unimplemented filters --- pdf.js | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/pdf.js b/pdf.js index 39e9e26df..cd3cdfba5 100644 --- a/pdf.js +++ b/pdf.js @@ -220,6 +220,43 @@ var DecodeStream = (function() { })(); +var FakeStream = (function() { + function constructor(stream) { + this.dict = stream.dict; + DecodeStream.call(this); + }; + + constructor.prototype = Object.create(DecodeStream.prototype); + constructor.prototype.readBlock = function() { + var bufferLength = this.bufferLength; + bufferLength += 1024; + var buffer = this.ensureBuffer(bufferLength); + this.bufferLength = bufferLength; + }; + constructor.prototype.getBytes = function(length) { + var pos = this.pos; + + if (length) { + this.ensureBuffer(pos + length); + var end = pos + length; + + while (!this.eof && this.bufferLength < end) + this.readBlock(); + + var bufEnd = this.bufferLength; + if (end > bufEnd) + end = bufEnd; + } else { + this.eof = true; + var end = this.bufferLength; + } + + this.pos = end; + return this.buffer.subarray(pos, end) + }; + + return constructor; +})(); var FlateStream = (function() { const codeLenCodeMap = Uint32Array([ @@ -597,9 +634,6 @@ var PredictorStream = (function() { constructor.prototype = Object.create(DecodeStream.prototype); constructor.prototype.readBlockTiff = function() { - var buffer = this.buffer; - var pos = this.pos; - var rowBytes = this.rowBytes; var pixBytes = this.pixBytes; @@ -660,9 +694,6 @@ var PredictorStream = (function() { this.bufferLength += rowBytes; }; constructor.prototype.readBlockPng = function() { - var buffer = this.buffer; - var pos = this.pos; - var rowBytes = this.rowBytes; var pixBytes = this.pixBytes; @@ -1448,6 +1479,9 @@ var Parser = (function() { return new JpegStream(bytes, stream.dict); } else if (name == "ASCII85Decode") { return new Ascii85Stream(stream); + } else if (name == "CCITTFaxDecode") { + TODO("implement fax stream"); + return new FakeStream(stream); } else { error("filter '" + name + "' not supported yet"); } From b54164d2a95054727a3f01b0bb861516566b2ac8 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Thu, 23 Jun 2011 05:38:05 +0200 Subject: [PATCH 10/11] Use the real content of the string to measure it's size --- pdf.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index 5d9caf490..addcea6de 100644 --- a/pdf.js +++ b/pdf.js @@ -2787,7 +2787,9 @@ var CanvasGraphics = (function() { this.ctx.transform.apply(this.ctx, this.current.textMatrix); this.ctx.scale(1, -1); this.ctx.translate(0, -2 * this.current.y); - this.ctx.fillText(Fonts.charsToUnicode(text), this.current.x, this.current.y); + + text = Fonts.charsToUnicode(text); + this.ctx.fillText(text, this.current.x, this.current.y); this.current.x += this.ctx.measureText(text).width; this.ctx.restore(); From 1532e86dcb82ff78d2fe0b52c0b7f1bc45eca0ce Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Wed, 22 Jun 2011 20:47:37 -0700 Subject: [PATCH 11/11] fix bug in testing multiple browsers --- test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test.py b/test.py index 1557714d6..9eab0e80e 100644 --- a/test.py +++ b/test.py @@ -117,8 +117,8 @@ def setUp(manifestFile, masterMode): assert not os.path.isdir(TMPDIR) testBrowsers = [ b for b in - ( 'firefox5', ) -#'chrome12', 'chrome13', 'firefox4', 'firefox6','opera11' ): + ( 'firefox5', 'firefox6', ) +#'chrome12', 'chrome13', 'firefox4', 'opera11' ): if os.access(b, os.R_OK | os.X_OK) ] mf = open(manifestFile) @@ -152,7 +152,7 @@ def setUp(manifestFile, masterMode): taskResults.append([ ]) State.taskResults[b][id] = taskResults - State.remaining = len(manifestList) + State.remaining = len(testBrowsers) * len(manifestList) for b in testBrowsers: print 'Launching', b