Merge upstream.

This commit is contained in:
Rob Sayre 2011-06-23 09:57:36 -07:00
commit 9da2b9c0ea
4 changed files with 141 additions and 56 deletions

View File

@ -495,7 +495,7 @@ var Font = (function () {
if (requiredTables.length && requiredTables[0] == "OS/2") { if (requiredTables.length && requiredTables[0] == "OS/2") {
// Create a new file to hold the new version of our truetype with a new // Create a new file to hold the new version of our truetype with a new
// header and new offsets // 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 // The offsets object holds at the same time a representation of where
// to write the table entry information about a table and another offset // 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) { convert: function font_convert(name, font, properties) {
var otf = Uint8Array(kMaxFontFileSize); var otf = new Uint8Array(kMaxFontFileSize);
function createNameTable(name) { function createNameTable(name) {
var names = [ var names = [
@ -1148,7 +1148,7 @@ var Type1Parser = function() {
* The CFF class takes a Type1 file and wrap it into a 'Compact Font Format', * The CFF class takes a Type1 file and wrap it into a 'Compact Font Format',
* which itself embed Type2 charstrings. * which itself embed Type2 charstrings.
*/ */
const CFFStrings = [ var CFFStrings = [
".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand", ".notdef","space","exclam","quotedbl","numbersign","dollar","percent","ampersand",
"quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period", "quoteright","parenleft","parenright","asterisk","plus","comma","hyphen","period",
"slash","zero","one","two","three","four","five","six","seven","eight","nine", "slash","zero","one","two","three","four","five","six","seven","eight","nine",

100
pdf.js
View File

@ -58,7 +58,7 @@ function bytesToString(bytes) {
var Stream = (function() { var Stream = (function() {
function constructor(arrayBuffer, start, length, dict) { function constructor(arrayBuffer, start, length, dict) {
this.bytes = Uint8Array(arrayBuffer); this.bytes = new Uint8Array(arrayBuffer);
this.start = start || 0; this.start = start || 0;
this.pos = this.start; this.pos = this.start;
this.end = (start + length) || this.bytes.length; this.end = (start + length) || this.bytes.length;
@ -125,7 +125,7 @@ var Stream = (function() {
var StringStream = (function() { var StringStream = (function() {
function constructor(str) { function constructor(str) {
var length = str.length; var length = str.length;
var bytes = Uint8Array(length); var bytes = new Uint8Array(length);
for (var n = 0; n < length; ++n) for (var n = 0; n < length; ++n)
bytes[n] = str.charCodeAt(n); bytes[n] = str.charCodeAt(n);
Stream.call(this, bytes); Stream.call(this, bytes);
@ -154,7 +154,7 @@ var DecodeStream = (function() {
var size = 512; var size = 512;
while (size < requested) while (size < requested)
size <<= 1; size <<= 1;
var buffer2 = Uint8Array(size); var buffer2 = new Uint8Array(size);
for (var i = 0; i < current; ++i) for (var i = 0; i < current; ++i)
buffer2[i] = buffer[i]; buffer2[i] = buffer[i];
return this.buffer = buffer2; return this.buffer = buffer2;
@ -220,13 +220,50 @@ 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() { 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 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, 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009,
0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017,
0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043,
@ -234,7 +271,7 @@ var FlateStream = (function() {
0x00102, 0x00102, 0x00102 0x00102, 0x00102, 0x00102
]); ]);
const distDecode = Uint32Array([ var distDecode = new Uint32Array([
0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009,
0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061,
0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401,
@ -242,7 +279,7 @@ var FlateStream = (function() {
0xd4001, 0xd6001 0xd4001, 0xd6001
]); ]);
const fixedLitCodeTab = [Uint32Array([ var fixedLitCodeTab = [new Uint32Array([
0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030,
0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080,
0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114,
@ -319,7 +356,7 @@ var FlateStream = (function() {
0x900ff 0x900ff
]), 9]; ]), 9];
const fixedDistCodeTab = [Uint32Array([ var fixedDistCodeTab = [new Uint32Array([
0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c,
0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016,
0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005,
@ -410,7 +447,7 @@ var FlateStream = (function() {
// build the table // build the table
var size = 1 << maxLen; var size = 1 << maxLen;
var codes = Uint32Array(size); var codes = new Uint32Array(size);
for (var len = 1, code = 0, skip = 2; for (var len = 1, code = 0, skip = 2;
len <= maxLen; len <= maxLen;
++len, code <<= 1, skip <<= 1) { ++len, code <<= 1, skip <<= 1) {
@ -597,9 +634,6 @@ var PredictorStream = (function() {
constructor.prototype = Object.create(DecodeStream.prototype); constructor.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlockTiff = function() { constructor.prototype.readBlockTiff = function() {
var buffer = this.buffer;
var pos = this.pos;
var rowBytes = this.rowBytes; var rowBytes = this.rowBytes;
var pixBytes = this.pixBytes; var pixBytes = this.pixBytes;
@ -660,9 +694,6 @@ var PredictorStream = (function() {
this.bufferLength += rowBytes; this.bufferLength += rowBytes;
}; };
constructor.prototype.readBlockPng = function() { constructor.prototype.readBlockPng = function() {
var buffer = this.buffer;
var pos = this.pos;
var rowBytes = this.rowBytes; var rowBytes = this.rowBytes;
var pixBytes = this.pixBytes; var pixBytes = this.pixBytes;
@ -782,8 +813,8 @@ var Ascii85Stream = (function() {
constructor.prototype = Object.create(DecodeStream.prototype); constructor.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlock = function() { constructor.prototype.readBlock = function() {
const tildaCode = "~".charCodeAt(0); var tildaCode = "~".charCodeAt(0);
const zCode = "z".charCodeAt(0); var zCode = "z".charCodeAt(0);
var str = this.str; var str = this.str;
var c = str.getByte(); var c = str.getByte();
@ -1001,10 +1032,10 @@ var Lexer = (function() {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
]; ];
const MIN_INT = (1<<31) | 0; var MIN_INT = (1<<31) | 0;
const MAX_INT = (MIN_INT - 1) | 0; var MAX_INT = (MIN_INT - 1) | 0;
const MIN_UINT = 0; var MIN_UINT = 0;
const MAX_UINT = ((1<<30) * 4) - 1; var MAX_UINT = ((1<<30) * 4) - 1;
function ToHexDigit(ch) { function ToHexDigit(ch) {
if (ch >= "0" && ch <= "9") if (ch >= "0" && ch <= "9")
@ -1448,6 +1479,9 @@ var Parser = (function() {
return new JpegStream(bytes, stream.dict); return new JpegStream(bytes, stream.dict);
} else if (name == "ASCII85Decode") { } else if (name == "ASCII85Decode") {
return new Ascii85Stream(stream); return new Ascii85Stream(stream);
} else if (name == "CCITTFaxDecode") {
TODO("implement fax stream");
return new FakeStream(stream);
} else { } else {
error("filter '" + name + "' not supported yet"); error("filter '" + name + "' not supported yet");
} }
@ -2031,7 +2065,7 @@ var PDFDoc = (function() {
return constructor; return constructor;
})(); })();
const IDENTITY_MATRIX = [ 1, 0, 0, 1, 0, 0 ]; var IDENTITY_MATRIX = [ 1, 0, 0, 1, 0, 0 ];
// <canvas> contexts store most of the state we need natively. // <canvas> contexts store most of the state we need natively.
// However, PDF needs a bit more state, which we store here. // However, PDF needs a bit more state, which we store here.
@ -2055,7 +2089,7 @@ var CanvasExtraState = (function() {
return constructor; return constructor;
})(); })();
const Encodings = { var Encodings = {
get ExpertEncoding() { get ExpertEncoding() {
return shadow(this, "ExpertEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, return shadow(this, "ExpertEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
"space","exclamsmall","Hungarumlautsmall",,"dollaroldstyle","dollarsuperior", "space","exclamsmall","Hungarumlautsmall",,"dollaroldstyle","dollarsuperior",
@ -2333,13 +2367,13 @@ var CanvasGraphics = (function() {
}; };
} }
const LINE_CAP_STYLES = [ "butt", "round", "square" ]; var LINE_CAP_STYLES = [ "butt", "round", "square" ];
const LINE_JOIN_STYLES = [ "miter", "round", "bevel" ]; var LINE_JOIN_STYLES = [ "miter", "round", "bevel" ];
const NORMAL_CLIP = {}; var NORMAL_CLIP = {};
const EO_CLIP = {}; var EO_CLIP = {};
// Used for tiling patterns // Used for tiling patterns
const PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
constructor.prototype = { constructor.prototype = {
translateFont: function(fontDict, xref, resources) { translateFont: function(fontDict, xref, resources) {
@ -2787,7 +2821,9 @@ var CanvasGraphics = (function() {
this.ctx.transform.apply(this.ctx, this.current.textMatrix); this.ctx.transform.apply(this.ctx, this.current.textMatrix);
this.ctx.scale(1, -1); this.ctx.scale(1, -1);
this.ctx.translate(0, -2 * this.current.y); 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.current.x += this.ctx.measureText(text).width;
this.ctx.restore(); this.ctx.restore();
@ -2874,7 +2910,7 @@ var CanvasGraphics = (function() {
var pattern = xref.fetchIfRef(patternRes.get(patternName.name)); var pattern = xref.fetchIfRef(patternRes.get(patternName.name));
var patternDict = IsStream(pattern) ? pattern.dict : pattern; var patternDict = IsStream(pattern) ? pattern.dict : pattern;
const types = [null, this.tilingFill, var types = [null, this.tilingFill,
function() { TODO("Shading Patterns"); }]; function() { TODO("Shading Patterns"); }];
var typeNum = patternDict.get("PatternType"); var typeNum = patternDict.get("PatternType");
var patternFn = types[typeNum]; var patternFn = types[typeNum];
@ -3023,7 +3059,7 @@ var CanvasGraphics = (function() {
if (background) if (background)
TODO("handle background colors"); TODO("handle background colors");
const types = [null, var types = [null,
this.fillFunctionShading, this.fillFunctionShading,
this.fillAxialShading, this.fillAxialShading,
this.fillRadialShading]; this.fillRadialShading];
@ -3460,7 +3496,7 @@ var PDFFunction = (function() {
if (!dict) if (!dict)
dict = fn; dict = fn;
const types = [this.constructSampled, var types = [this.constructSampled,
null, null,
this.constructInterpolated, this.constructInterpolated,
this.constructStiched, this.constructStiched,

View File

@ -11,6 +11,7 @@ DOC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
ANAL = True ANAL = True
DEFAULT_MANIFEST_FILE = 'test_manifest.json' DEFAULT_MANIFEST_FILE = 'test_manifest.json'
DEFAULT_BROWSER_MANIFEST_FILE = 'browser_manifest.json' DEFAULT_BROWSER_MANIFEST_FILE = 'browser_manifest.json'
EQLOG_FILE = 'eq.log'
REFDIR = 'ref' REFDIR = 'ref'
TMPDIR = 'tmp' TMPDIR = 'tmp'
VERBOSE = False VERBOSE = False
@ -42,7 +43,7 @@ def prompt(question):
MIMEs = { MIMEs = {
'.css': 'text/css', '.css': 'text/css',
'.html': 'text/html', '.html': 'text/html',
'.js': 'application/json', '.js': 'application/javascript',
'.json': 'application/json', '.json': 'application/json',
'.pdf': 'application/pdf', '.pdf': 'application/pdf',
'.xhtml': 'application/xhtml+xml', '.xhtml': 'application/xhtml+xml',
@ -61,6 +62,7 @@ class State:
numEqNoSnapshot = 0 numEqNoSnapshot = 0
numFBFFailures = 0 numFBFFailures = 0
numLoadFailures = 0 numLoadFailures = 0
eqLog = None
class Result: class Result:
def __init__(self, snapshot, failure): def __init__(self, snapshot, failure):
@ -191,7 +193,7 @@ def setUp(options):
taskResults.append([ ]) taskResults.append([ ])
State.taskResults[b.name][id] = taskResults State.taskResults[b.name][id] = taskResults
State.remaining = len(manifestList) State.remaining = len(testBrowsers) * len(manifestList)
for b in testBrowsers: for b in testBrowsers:
print 'Launching', b.name print 'Launching', b.name
@ -231,6 +233,7 @@ def check(task, results, browser):
def checkEq(task, results, browser): def checkEq(task, results, browser):
pfx = os.path.join(REFDIR, sys.platform, browser, task['id']) pfx = os.path.join(REFDIR, sys.platform, browser, task['id'])
results = results[0] results = results[0]
taskId = task['id']
passed = True passed = True
for page in xrange(len(results)): for page in xrange(len(results)):
@ -249,7 +252,21 @@ def checkEq(task, results, browser):
eq = (ref == snapshot) eq = (ref == snapshot)
if not eq: 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 passed = False
State.numEqFailures += 1 State.numEqFailures += 1

View File

@ -1,6 +1,7 @@
<html> <html>
<head> <head>
<title>pdf.js test slave</title> <title>pdf.js test slave</title>
<style type="text/css"></style>
<script type="text/javascript" src="/pdf.js"></script> <script type="text/javascript" src="/pdf.js"></script>
<script type="text/javascript" src="/fonts.js"></script> <script type="text/javascript" src="/fonts.js"></script>
<script type="text/javascript" src="/glyphlist.js"></script> <script type="text/javascript" src="/glyphlist.js"></script>
@ -31,7 +32,7 @@ function load() {
stdout = document.getElementById("stdout"); stdout = document.getElementById("stdout");
log("Harness thinks this browser is '"+ browser +"'\n"); log("Harness thinks this browser is '"+ browser +"'\n");
log("Fetching manifest ..."); log("Fetching manifest "+ manifestFile +"...");
var r = new XMLHttpRequest(); var r = new XMLHttpRequest();
r.open("GET", manifestFile, false); r.open("GET", manifestFile, false);
@ -81,38 +82,69 @@ function nextPage() {
} }
failure = ''; failure = '';
log(" drawing page "+ currentTask.pageNum +"..."); log(" loading page "+ currentTask.pageNum +"... ");
var ctx = canvas.getContext("2d"); var ctx = canvas.getContext("2d");
clear(ctx); clear(ctx);
var fonts = []; var fonts = [];
var fontsReady = true;
var gfx = new CanvasGraphics(ctx); var gfx = new CanvasGraphics(ctx);
try { try {
currentPage = pdfDoc.getPage(currentTask.pageNum); currentPage = pdfDoc.getPage(currentTask.pageNum);
currentPage.compile(gfx, fonts); 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) { } catch(e) {
failure = 'compile: '+ e.toString(); failure = 'compile: '+ e.toString();
} }
// TODO load fonts var checkFontsLoadedIntervalTimer = null;
setTimeout(function() { function checkFontsLoaded() {
if (!failure) { for (var i = 0; i < count; i++) {
try { if (Fonts[font.name].loading) {
currentPage.display(gfx); return;
} catch(e) {
failure = 'render: '+ e.toString();
}
} }
currentTask.taskDone = (currentTask.pageNum == pdfDoc.numPages }
&& (1 + currentTask.round) == currentTask.rounds); window.clearInterval(checkFontsLoadedIntervalTimer);
sendTaskResult(canvas.toDataURL("image/png"));
log("done"+ (failure ? " (failed!)" : "") +"\n");
++currentTask.pageNum, nextPage(); snapshotCurrentPage(gfx);
}, }
0
); 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() { function done() {