add assert helpers, small cleanup

This commit is contained in:
Chris Jones 2011-05-17 11:59:38 +12:00
parent 8f8b302b23
commit d7f3c31d9d

69
pdf.js
View File

@ -1,5 +1,6 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- / /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */ /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
function warn(msg) { function warn(msg) {
if (console && console.log) if (console && console.log)
console.log(msg); console.log(msg);
@ -11,6 +12,18 @@ function error(msg) {
throw new Error(msg); throw new Error(msg);
} }
function assert(cond, msg) {
if (!cond)
error(msg);
}
// In a well-formed PDF, |cond| holds. If it doesn't, subsequent
// behavior is undefined.
function assertWellFormed(cond, msg) {
if (!cond)
error("Malformed PDF: "+ msg);
}
function shadow(obj, prop, value) { function shadow(obj, prop, value) {
Object.defineProperty(obj, prop, { value: value, enumerable: true }); Object.defineProperty(obj, prop, { value: value, enumerable: true });
return value; return value;
@ -1811,8 +1824,8 @@ var Page = (function() {
var contents = xref.fetchIfRef(this.contents); var contents = xref.fetchIfRef(this.contents);
var resources = xref.fetchIfRef(this.resources); var resources = xref.fetchIfRef(this.resources);
var mediaBox = xref.fetchIfRef(this.mediaBox); var mediaBox = xref.fetchIfRef(this.mediaBox);
if (!IsStream(contents) || !IsDict(resources)) assertWellFormed(IsStream(contents) && IsDict(resources),
error("invalid page contents or resources"); "invalid page contents or resources");
gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1], gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
width: mediaBox[2] - mediaBox[0], width: mediaBox[2] - mediaBox[0],
height: mediaBox[3] - mediaBox[1] }); height: mediaBox[3] - mediaBox[1] });
@ -1829,45 +1842,42 @@ var Catalog = (function() {
function constructor(xref) { function constructor(xref) {
this.xref = xref; this.xref = xref;
var obj = xref.getCatalogObj(); var obj = xref.getCatalogObj();
if (!IsDict(obj)) assertWellFormed(IsDict(obj), "catalog object is not a dictionary");
error("catalog object is not a dictionary");
this.catDict = obj; this.catDict = obj;
} }
constructor.prototype = { constructor.prototype = {
get toplevelPagesDict() { get toplevelPagesDict() {
var obj = this.catDict.get("Pages"); var obj = this.catDict.get("Pages");
if (!IsRef(obj)) assertWellFormed(IsRef(obj), "invalid top-level pages reference");
error("invalid top-level pages reference");
var obj = this.xref.fetch(obj); var obj = this.xref.fetch(obj);
if (!IsDict(obj)) assertWellFormed(IsDict(obj), "invalid top-level pages dictionary");
error("invalid top-level pages dictionary");
// shadow the prototype getter // shadow the prototype getter
return shadow(this, "toplevelPagesDict", obj); return shadow(this, "toplevelPagesDict", obj);
}, },
get numPages() { get numPages() {
obj = this.toplevelPagesDict.get("Count"); obj = this.toplevelPagesDict.get("Count");
if (!IsInt(obj)) assertWellFormed(IsInt(obj),
error("page count in top level pages object is not an integer"); "page count in top level pages object is not an integer");
// shadow the prototype getter // shadow the prototype getter
return shadow(this, "num", obj); return shadow(this, "num", obj);
}, },
traverseKids: function(pagesDict) { traverseKids: function(pagesDict) {
var pageCache = this.pageCache; var pageCache = this.pageCache;
var kids = pagesDict.get("Kids"); var kids = pagesDict.get("Kids");
if (!IsArray(kids)) assertWellFormed(IsArray(kids),
error("page dictionary kids object is not an array"); "page dictionary kids object is not an array");
for (var i = 0; i < kids.length; ++i) { for (var i = 0; i < kids.length; ++i) {
var kid = kids[i]; var kid = kids[i];
if (!IsRef(kid)) assertWellFormed(IsRef(kid),
error("page dictionary kid is not a reference"); "page dictionary kid is not a reference");
var obj = this.xref.fetch(kid); var obj = this.xref.fetch(kid);
if (IsDict(obj, "Page") || (IsDict(obj) && !obj.has("Kids"))) { if (IsDict(obj, "Page") || (IsDict(obj) && !obj.has("Kids"))) {
pageCache.push(new Page(this.xref, pageCache.length, obj)); pageCache.push(new Page(this.xref, pageCache.length, obj));
} else if (IsDict(obj)) { // must be a child page dictionary } else { // must be a child page dictionary
assertWellFormed(IsDict(obj),
"page dictionary kid reference points to wrong type of object");
this.traverseKids(obj); this.traverseKids(obj);
} else {
error("page dictionary kid reference points to wrong type of object");
} }
} }
}, },
@ -1988,9 +1998,7 @@ var PDFDoc = (function() {
}, },
getPage: function(n) { getPage: function(n) {
var linearization = this.linearization; var linearization = this.linearization;
if (linearization) { assert(!linearization, "linearized page access not implemented");
error("linearized page access not implemented");
}
return this.catalog.getPage(n); return this.catalog.getPage(n);
} }
}; };
@ -2112,15 +2120,13 @@ var CanvasGraphics = (function() {
if (IsCmd(obj)) { if (IsCmd(obj)) {
var cmd = obj.cmd; var cmd = obj.cmd;
var fn = map[cmd]; var fn = map[cmd];
if (fn) assertWellFormed(fn, "Unknown command '" + cmd + "'");
// TODO figure out how to type-check vararg functions // TODO figure out how to type-check vararg functions
fn.apply(this, args); fn.apply(this, args);
else
error("Unknown command '" + cmd + "'");
args.length = 0; args.length = 0;
} else { } else {
if (args.length > 33) assertWellFormed(args.length <= 33, "Too many arguments");
error("Too many arguments '" + cmd + "'");
args.push(obj); args.push(obj);
} }
} }
@ -2256,10 +2262,10 @@ var CanvasGraphics = (function() {
var e = arr[i]; var e = arr[i];
if (IsNum(e)) { if (IsNum(e)) {
this.current.curX -= e * 0.001 * this.current.fontSize; this.current.curX -= e * 0.001 * this.current.fontSize;
} else if (IsString(e)) {
this.showText(e);
} else { } else {
error("Unexpected element in TJ array"); assertWellFormed(IsString(e),
"TJ array element isn't string or num");
this.showText(e);
} }
} }
}, },
@ -2306,8 +2312,7 @@ var CanvasGraphics = (function() {
if (!xobj) if (!xobj)
return; return;
xobj = this.xref.fetchIfRef(xobj); xobj = this.xref.fetchIfRef(xobj);
if (!IsStream(xobj)) assertWellFormed(IsStream(xobj), "XObject should be a stream");
error("XObject should be a stream");
this.interpret(new Parser(new Lexer(xobj), false), this.interpret(new Parser(new Lexer(xobj), false),
this.xref, xobj.dict.get("Resources")); this.xref, xobj.dict.get("Resources"));