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 cd3cdfba5..d940c4f8b 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; @@ -259,11 +259,11 @@ var FakeStream = (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, @@ -271,7 +271,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, @@ -279,7 +279,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, @@ -356,7 +356,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, @@ -447,7 +447,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) { @@ -813,8 +813,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(); @@ -1032,10 +1032,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") @@ -2065,7 +2065,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. @@ -2089,7 +2089,7 @@ var CanvasExtraState = (function() { return constructor; })(); -const Encodings = { +var Encodings = { get ExpertEncoding() { return shadow(this, "ExpertEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, "space","exclamsmall","Hungarumlautsmall",,"dollaroldstyle","dollarsuperior", @@ -2367,13 +2367,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) { @@ -2821,7 +2821,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(); @@ -2908,7 +2910,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]; @@ -3057,7 +3059,7 @@ var CanvasGraphics = (function() { if (background) TODO("handle background colors"); - const types = [null, + var types = [null, this.fillFunctionShading, this.fillAxialShading, this.fillRadialShading]; @@ -3494,7 +3496,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 0c326ec09..9eab0e80e 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 @@ -16,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', @@ -35,6 +36,7 @@ class State: numEqNoSnapshot = 0 numFBFFailures = 0 numLoadFailures = 0 + eqLog = None class Result: def __init__(self, snapshot, failure): @@ -115,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) @@ -150,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 @@ -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 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() {