Merge branch 'master' into shading
Conflicts: pdf.js
This commit is contained in:
commit
4861a9175d
10
Makefile
10
Makefile
@ -1,7 +1,7 @@
|
||||
REPO = git@github.com:andreasgal/pdf.js.git
|
||||
BUILD_DIR := build
|
||||
DEFAULT_BROWSERS := test/resources/browser_manifests/browser_manifest.json
|
||||
DEFAULT_TESTS := test/test_manifest.json
|
||||
DEFAULT_BROWSERS := resources/browser_manifests/browser_manifest.json
|
||||
DEFAULT_TESTS := test_manifest.json
|
||||
|
||||
# Let folks define custom rules for their clones.
|
||||
-include local.mk
|
||||
@ -43,7 +43,7 @@ PDF_BROWSERS := $(DEFAULT_BROWSERS)
|
||||
endif
|
||||
|
||||
browser-test:
|
||||
@if [ ! -f "$(PDF_BROWSERS)" ]; then \
|
||||
@if [ ! -f "test/$(PDF_BROWSERS)" ]; then \
|
||||
echo "Browser manifest file $(PDF_BROWSERS) does not exist."; \
|
||||
echo "Try copying one of the examples" \
|
||||
"in test/resources/browser_manifests/"; \
|
||||
@ -52,8 +52,8 @@ browser-test:
|
||||
|
||||
cd test; \
|
||||
python test.py --reftest \
|
||||
--browserManifestFile=$(abspath $(PDF_BROWSERS)) \
|
||||
--manifestFile=$(abspath $(PDF_TESTS))
|
||||
--browserManifestFile=$(PDF_BROWSERS) \
|
||||
--manifestFile=$(PDF_TESTS)
|
||||
|
||||
# make shell-test
|
||||
#
|
||||
|
134
fonts.js
134
fonts.js
@ -542,21 +542,12 @@ var Font = (function() {
|
||||
'\x00\x01' + // encodingID
|
||||
string32(4 + numTables * 8); // start of the table record
|
||||
|
||||
var headerSize = (12 * 2 + (ranges.length * 5 * 2));
|
||||
var segCount = ranges.length + 1;
|
||||
var segCount2 = segCount * 2;
|
||||
var searchRange = getMaxPower2(segCount) * 2;
|
||||
var searchEntry = Math.log(segCount) / Math.log(2);
|
||||
var rangeShift = 2 * segCount - searchRange;
|
||||
|
||||
var format314 = '\x00\x04' + // format
|
||||
string16(headerSize) + // length
|
||||
'\x00\x00' + // language
|
||||
string16(segCount2) +
|
||||
string16(searchRange) +
|
||||
string16(searchEntry) +
|
||||
string16(rangeShift);
|
||||
|
||||
// Fill up the 4 parallel arrays describing the segments.
|
||||
var startCount = '';
|
||||
var endCount = '';
|
||||
@ -568,7 +559,7 @@ var Font = (function() {
|
||||
var range = ranges[i];
|
||||
var start = range[0];
|
||||
var end = range[1];
|
||||
var delta = (bias - start) % 0xffff;
|
||||
var delta = (bias - start) & 0xffff;
|
||||
bias += (end - start + 1);
|
||||
|
||||
startCount += string16(start);
|
||||
@ -585,10 +576,19 @@ var Font = (function() {
|
||||
startCount += '\xFF\xFF';
|
||||
idDeltas += '\x00\x01';
|
||||
idRangeOffsets += '\x00\x00';
|
||||
format314 += endCount + '\x00\x00' + startCount +
|
||||
idDeltas + idRangeOffsets + glyphsIds;
|
||||
|
||||
return stringToArray(cmap + format314);
|
||||
var format314 = '\x00\x00' + // language
|
||||
string16(segCount2) +
|
||||
string16(searchRange) +
|
||||
string16(searchEntry) +
|
||||
string16(rangeShift) +
|
||||
endCount + '\x00\x00' + startCount +
|
||||
idDeltas + idRangeOffsets + glyphsIds;
|
||||
|
||||
return stringToArray(cmap +
|
||||
'\x00\x04' + // format
|
||||
string16(format314.length + 4) + // length
|
||||
format314);
|
||||
};
|
||||
|
||||
function createOS2Table(properties) {
|
||||
@ -705,6 +705,9 @@ var Font = (function() {
|
||||
var data = file.getBytes(length);
|
||||
file.pos = previousPosition;
|
||||
|
||||
if (tag == 'head')
|
||||
data[8] = data[9] = data[10] = data[11] = 0; // clearing checksum adjustment
|
||||
|
||||
return {
|
||||
tag: tag,
|
||||
checksum: checksum,
|
||||
@ -907,11 +910,6 @@ var Font = (function() {
|
||||
|
||||
convert: function font_convert(fontName, font, properties) {
|
||||
function createNameTable(name) {
|
||||
// All the strings of the name table should be an odd number
|
||||
// of bytes
|
||||
if (name.length % 2)
|
||||
name = name.slice(0, name.length - 1);
|
||||
|
||||
var strings = [
|
||||
'Original licence', // 0.Copyright
|
||||
name, // 1.Font family
|
||||
@ -919,7 +917,7 @@ var Font = (function() {
|
||||
'uniqueID', // 3.Unique ID
|
||||
name, // 4.Full font name
|
||||
'Version 0.11', // 5.Version
|
||||
'Unknown', // 6.Postscript name
|
||||
'', // 6.Postscript name
|
||||
'Unknown', // 7.Trademark
|
||||
'Unknown', // 8.Manufacturer
|
||||
'Unknown' // 9.Designer
|
||||
@ -958,7 +956,7 @@ var Font = (function() {
|
||||
platforms[i] + // platform ID
|
||||
encodings[i] + // encoding ID
|
||||
languages[i] + // language ID
|
||||
string16(i) + // name ID
|
||||
string16(j) + // name ID
|
||||
string16(str.length) +
|
||||
string16(strOffset);
|
||||
nameTable += nameRecord;
|
||||
@ -1133,6 +1131,12 @@ var Font = (function() {
|
||||
for (var i = 0; i < chars.length; ++i) {
|
||||
var charcode = chars.charCodeAt(i);
|
||||
var unicode = encoding[charcode];
|
||||
if ('undefined' == typeof(unicode)) {
|
||||
// FIXME/issue 233: we're hitting this in test/pdf/sizes.pdf
|
||||
// at the moment, for unknown reasons.
|
||||
warn('Unencoded charcode '+ charcode);
|
||||
unicode = charcode;
|
||||
}
|
||||
|
||||
// Check if the glyph has already been converted
|
||||
if (!IsNum(unicode))
|
||||
@ -1388,6 +1392,18 @@ var Type1Parser = function() {
|
||||
return array;
|
||||
};
|
||||
|
||||
function readNumber(str, index) {
|
||||
while (str[index++] == ' ')
|
||||
;
|
||||
var start = index;
|
||||
|
||||
var count = 0;
|
||||
while (str[index++] != ' ')
|
||||
count++;
|
||||
|
||||
return parseFloat(str.substr(start, count) || 0);
|
||||
};
|
||||
|
||||
this.extractFontProgram = function t1_extractFontProgram(stream) {
|
||||
var eexec = decrypt(stream, kEexecEncryptionKey, 4);
|
||||
var eexecStr = '';
|
||||
@ -1399,8 +1415,7 @@ var Type1Parser = function() {
|
||||
subrs: [],
|
||||
charstrings: [],
|
||||
properties: {
|
||||
stemSnapH: [0, 0],
|
||||
stemSnapV: [0, 0]
|
||||
'private': {}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1442,17 +1457,24 @@ var Type1Parser = function() {
|
||||
case '/Subrs':
|
||||
subrsSection = true;
|
||||
break;
|
||||
case '/StdHW':
|
||||
program.properties.stdHW = readNumberArray(eexecStr, i + 2)[0];
|
||||
break;
|
||||
case '/StdVW':
|
||||
program.properties.stdVW = readNumberArray(eexecStr, i + 2)[0];
|
||||
break;
|
||||
case '/BlueValues':
|
||||
case '/OtherBlues':
|
||||
case '/FamilyBlues':
|
||||
case '/FamilyOtherBlues':
|
||||
case '/StemSnapH':
|
||||
program.properties.stemSnapH = readNumberArray(eexecStr, i + 2);
|
||||
break;
|
||||
case '/StemSnapV':
|
||||
program.properties.stemSnapV = readNumberArray(eexecStr, i + 2);
|
||||
program.properties.private[token.substring(1)] = readNumberArray(eexecStr, i + 2);
|
||||
break;
|
||||
case '/StdHW':
|
||||
case '/StdVW':
|
||||
program.properties.private[token.substring(1)] = readNumberArray(eexecStr, i + 2)[0];
|
||||
break;
|
||||
case '/BlueShift':
|
||||
case '/BlueFuzz':
|
||||
case '/BlueScale':
|
||||
case '/LanguageGroup':
|
||||
case '/ExpansionFactor':
|
||||
program.properties.private[token.substring(1)] = readNumber(eexecStr, i + 1);
|
||||
break;
|
||||
}
|
||||
} else if (c == '/') {
|
||||
@ -1642,7 +1664,7 @@ CFF.prototype = {
|
||||
return '\x1c' +
|
||||
String.fromCharCode((value >> 8) & 0xFF) +
|
||||
String.fromCharCode(value & 0xFF);
|
||||
} else if (value >= (-2147483647-1) && value <= 2147483647) {
|
||||
} else if (value >= (-2147483648) && value <= 2147483647) {
|
||||
return '\xff' +
|
||||
String.fromCharCode((value >>> 24) & 0xFF) +
|
||||
String.fromCharCode((value >> 16) & 0xFF) +
|
||||
@ -1769,10 +1791,10 @@ CFF.prototype = {
|
||||
var dict =
|
||||
'\x00\x01\x01\x01\x30' +
|
||||
'\xf8\x1b\x00' + // version
|
||||
'\xf8\x1b\x01' + // Notice
|
||||
'\xf8\x1b\x02' + // FullName
|
||||
'\xf8\x1b\x03' + // FamilyName
|
||||
'\xf8\x1b\x04' + // Weight
|
||||
'\xf8\x1c\x01' + // Notice
|
||||
'\xf8\x1d\x02' + // FullName
|
||||
'\xf8\x1e\x03' + // FamilyName
|
||||
'\xf8\x1f\x04' + // Weight
|
||||
'\x1c\x00\x00\x10'; // Encoding
|
||||
|
||||
var boundingBox = properties.bbox;
|
||||
@ -1791,7 +1813,7 @@ CFF.prototype = {
|
||||
dict += self.encodeNumber(offset) + '\x11'; // Charstrings
|
||||
|
||||
dict += self.encodeNumber(fields.private.length);
|
||||
var offset = offset + fields.charstrings.length;
|
||||
offset = offset + fields.charstrings.length;
|
||||
dict += self.encodeNumber(offset) + '\x12'; // Private
|
||||
|
||||
return dict;
|
||||
@ -1835,19 +1857,33 @@ CFF.prototype = {
|
||||
'private': (function(self) {
|
||||
var data =
|
||||
'\x8b\x14' + // defaultWidth
|
||||
'\x8b\x15' + // nominalWidth
|
||||
self.encodeNumber(properties.stdHW || 0) + '\x0a' + // StdHW
|
||||
self.encodeNumber(properties.stdVW || 0) + '\x0b'; // StdVW
|
||||
'\x8b\x15'; // nominalWidth
|
||||
var fieldMap = {
|
||||
BlueValues: '\x06',
|
||||
OtherBlues: '\x07',
|
||||
FamilyBlues: '\x08',
|
||||
FamilyOtherBlues: '\x09',
|
||||
StemSnapH: '\x0c\x0c',
|
||||
StemSnapV: '\x0c\x0d',
|
||||
BlueShift: '\x0c\x0a',
|
||||
BlueFuzz: '\x0c\x0b',
|
||||
BlueScale: '\x0c\x09',
|
||||
LanguageGroup: '\x0c\x11',
|
||||
ExpansionFactor: '\x0c\x18'
|
||||
};
|
||||
for (var field in fieldMap) {
|
||||
if (!properties.private.hasOwnProperty(field)) continue;
|
||||
var value = properties.private[field];
|
||||
|
||||
var stemH = properties.stemSnapH;
|
||||
for (var i = 0; i < stemH.length; i++)
|
||||
data += self.encodeNumber(stemH[i]);
|
||||
data += '\x0c\x0c'; // StemSnapH
|
||||
|
||||
var stemV = properties.stemSnapV;
|
||||
for (var i = 0; i < stemV.length; i++)
|
||||
data += self.encodeNumber(stemV[i]);
|
||||
data += '\x0c\x0d'; // StemSnapV
|
||||
if (IsArray(value)) {
|
||||
data += self.encodeNumber(value[0]);
|
||||
for (var i = 1; i < value.length; i++)
|
||||
data += self.encodeNumber(value[i] - value[i - 1]);
|
||||
} else {
|
||||
data += self.encodeNumber(value);
|
||||
}
|
||||
data += fieldMap[field];
|
||||
}
|
||||
|
||||
data += self.encodeNumber(data.length + 4) + '\x13'; // Subrs offset
|
||||
|
||||
|
473
pdf.js
473
pdf.js
@ -44,7 +44,7 @@ function assertWellFormed(cond, msg) {
|
||||
}
|
||||
|
||||
function shadow(obj, prop, value) {
|
||||
Object.defineProperty(obj, prop, { value: value, enumerable: true });
|
||||
Object.defineProperty(obj, prop, { value: value, enumerable: true, configurable: true, writable: false });
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -2923,9 +2923,15 @@ var XRef = (function() {
|
||||
|
||||
var Page = (function() {
|
||||
function constructor(xref, pageNumber, pageDict) {
|
||||
this.xref = xref;
|
||||
this.pageNumber = pageNumber;
|
||||
this.pageDict = pageDict;
|
||||
this.stats = {
|
||||
create: Date.now(),
|
||||
compile: 0.0,
|
||||
fonts: 0.0,
|
||||
render: 0.0,
|
||||
};
|
||||
this.xref = xref;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
@ -2954,6 +2960,32 @@ var Page = (function() {
|
||||
return shadow(this, 'mediaBox',
|
||||
((IsArray(obj) && obj.length == 4) ? obj : null));
|
||||
},
|
||||
startRendering: function(canvasCtx, continuation) {
|
||||
var self = this;
|
||||
var stats = self.stats;
|
||||
stats.compile = stats.fonts = stats.render = 0;
|
||||
|
||||
var gfx = new CanvasGraphics(canvasCtx);
|
||||
var fonts = [ ];
|
||||
|
||||
this.compile(gfx, fonts);
|
||||
stats.compile = Date.now();
|
||||
|
||||
FontLoader.bind(
|
||||
fonts,
|
||||
function() {
|
||||
stats.fonts = Date.now();
|
||||
// Always defer call to display() to work around bug in
|
||||
// Firefox error reporting from XHR callbacks.
|
||||
setTimeout(function () {
|
||||
self.display(gfx);
|
||||
stats.render = Date.now();
|
||||
continuation();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
compile: function(gfx, fonts) {
|
||||
if (this.code) {
|
||||
// content was compiled
|
||||
@ -3385,18 +3417,13 @@ var Encodings = {
|
||||
|
||||
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
|
||||
|
||||
// <canvas> contexts store most of the state we need natively.
|
||||
// However, PDF needs a bit more state, which we store here.
|
||||
var CanvasExtraState = (function() {
|
||||
var EvalState = (function() {
|
||||
function constructor() {
|
||||
// Are soft masks and alpha values shapes or opacities?
|
||||
this.alphaIsShape = false;
|
||||
this.fontSize = 0;
|
||||
this.textMatrix = IDENTITY_MATRIX;
|
||||
this.leading = 0;
|
||||
// Current point (in user coordinates)
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
// Start of text line (in text coordinates)
|
||||
this.lineX = 0;
|
||||
this.lineY = 0;
|
||||
@ -3413,126 +3440,187 @@ var CanvasExtraState = (function() {
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
function ScratchCanvas(width, height) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return canvas;
|
||||
}
|
||||
|
||||
var CanvasGraphics = (function() {
|
||||
function constructor(canvasCtx, imageCanvas) {
|
||||
this.ctx = canvasCtx;
|
||||
this.current = new CanvasExtraState();
|
||||
this.stateStack = [];
|
||||
this.pendingClip = null;
|
||||
this.res = null;
|
||||
this.xobjs = null;
|
||||
this.ScratchCanvas = imageCanvas || ScratchCanvas;
|
||||
var PartialEvaluator = (function() {
|
||||
function constructor() {
|
||||
this.state = new EvalState();
|
||||
this.stateStack = [ ];
|
||||
}
|
||||
|
||||
var LINE_CAP_STYLES = ['butt', 'round', 'square'];
|
||||
var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
|
||||
var NORMAL_CLIP = {};
|
||||
var EO_CLIP = {};
|
||||
var OP_MAP = {
|
||||
// Graphics state
|
||||
w: 'setLineWidth',
|
||||
J: 'setLineCap',
|
||||
j: 'setLineJoin',
|
||||
M: 'setMiterLimit',
|
||||
d: 'setDash',
|
||||
ri: 'setRenderingIntent',
|
||||
i: 'setFlatness',
|
||||
gs: 'setGState',
|
||||
q: 'save',
|
||||
Q: 'restore',
|
||||
cm: 'transform',
|
||||
|
||||
// Used for tiling patterns
|
||||
var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
|
||||
// Path
|
||||
m: 'moveTo',
|
||||
l: 'lineTo',
|
||||
c: 'curveTo',
|
||||
v: 'curveTo2',
|
||||
y: 'curveTo3',
|
||||
h: 'closePath',
|
||||
re: 'rectangle',
|
||||
S: 'stroke',
|
||||
s: 'closeStroke',
|
||||
f: 'fill',
|
||||
F: 'fill',
|
||||
'f*': 'eoFill',
|
||||
B: 'fillStroke',
|
||||
'B*': 'eoFillStroke',
|
||||
b: 'closeFillStroke',
|
||||
'b*': 'closeEOFillStroke',
|
||||
n: 'endPath',
|
||||
|
||||
// Clipping
|
||||
W: 'clip',
|
||||
'W*': 'eoClip',
|
||||
|
||||
// Text
|
||||
BT: 'beginText',
|
||||
ET: 'endText',
|
||||
Tc: 'setCharSpacing',
|
||||
Tw: 'setWordSpacing',
|
||||
Tz: 'setHScale',
|
||||
TL: 'setLeading',
|
||||
Tf: 'setFont',
|
||||
Tr: 'setTextRenderingMode',
|
||||
Ts: 'setTextRise',
|
||||
Td: 'moveText',
|
||||
TD: 'setLeadingMoveText',
|
||||
Tm: 'setTextMatrix',
|
||||
'T*': 'nextLine',
|
||||
Tj: 'showText',
|
||||
TJ: 'showSpacedText',
|
||||
"'": 'nextLineShowText',
|
||||
'"': 'nextLineSetSpacingShowText',
|
||||
|
||||
// Type3 fonts
|
||||
d0: 'setCharWidth',
|
||||
d1: 'setCharWidthAndBounds',
|
||||
|
||||
// Color
|
||||
CS: 'setStrokeColorSpace',
|
||||
cs: 'setFillColorSpace',
|
||||
SC: 'setStrokeColor',
|
||||
SCN: 'setStrokeColorN',
|
||||
sc: 'setFillColor',
|
||||
scn: 'setFillColorN',
|
||||
G: 'setStrokeGray',
|
||||
g: 'setFillGray',
|
||||
RG: 'setStrokeRGBColor',
|
||||
rg: 'setFillRGBColor',
|
||||
K: 'setStrokeCMYKColor',
|
||||
k: 'setFillCMYKColor',
|
||||
|
||||
// Shading
|
||||
sh: 'shadingFill',
|
||||
|
||||
// Images
|
||||
BI: 'beginInlineImage',
|
||||
|
||||
// XObjects
|
||||
Do: 'paintXObject',
|
||||
|
||||
// Marked content
|
||||
MP: 'markPoint',
|
||||
DP: 'markPointProps',
|
||||
BMC: 'beginMarkedContent',
|
||||
BDC: 'beginMarkedContentProps',
|
||||
EMC: 'endMarkedContent',
|
||||
|
||||
// Compatibility
|
||||
BX: 'beginCompat',
|
||||
EX: 'endCompat'
|
||||
};
|
||||
|
||||
constructor.prototype = {
|
||||
map: {
|
||||
// Graphics state
|
||||
w: 'setLineWidth',
|
||||
J: 'setLineCap',
|
||||
j: 'setLineJoin',
|
||||
M: 'setMiterLimit',
|
||||
d: 'setDash',
|
||||
ri: 'setRenderingIntent',
|
||||
i: 'setFlatness',
|
||||
gs: 'setGState',
|
||||
q: 'save',
|
||||
Q: 'restore',
|
||||
cm: 'transform',
|
||||
eval: function(stream, xref, resources, fonts) {
|
||||
resources = xref.fetchIfRef(resources) || new Dict();
|
||||
var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict();
|
||||
|
||||
// Path
|
||||
m: 'moveTo',
|
||||
l: 'lineTo',
|
||||
c: 'curveTo',
|
||||
v: 'curveTo2',
|
||||
y: 'curveTo3',
|
||||
h: 'closePath',
|
||||
re: 'rectangle',
|
||||
S: 'stroke',
|
||||
s: 'closeStroke',
|
||||
f: 'fill',
|
||||
F: 'fill',
|
||||
'f*': 'eoFill',
|
||||
B: 'fillStroke',
|
||||
'B*': 'eoFillStroke',
|
||||
b: 'closeFillStroke',
|
||||
'b*': 'closeEOFillStroke',
|
||||
n: 'endPath',
|
||||
var parser = new Parser(new Lexer(stream), false);
|
||||
var objpool = [];
|
||||
|
||||
// Clipping
|
||||
W: 'clip',
|
||||
'W*': 'eoClip',
|
||||
function emitArg(arg) {
|
||||
if (typeof arg == 'object' || typeof arg == 'string') {
|
||||
var index = objpool.length;
|
||||
objpool[index] = arg;
|
||||
return 'objpool[' + index + ']';
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
// Text
|
||||
BT: 'beginText',
|
||||
ET: 'endText',
|
||||
Tc: 'setCharSpacing',
|
||||
Tw: 'setWordSpacing',
|
||||
Tz: 'setHScale',
|
||||
TL: 'setLeading',
|
||||
Tf: 'setFont',
|
||||
Tr: 'setTextRenderingMode',
|
||||
Ts: 'setTextRise',
|
||||
Td: 'moveText',
|
||||
TD: 'setLeadingMoveText',
|
||||
Tm: 'setTextMatrix',
|
||||
'T*': 'nextLine',
|
||||
Tj: 'showText',
|
||||
TJ: 'showSpacedText',
|
||||
"'": 'nextLineShowText',
|
||||
'"': 'nextLineSetSpacingShowText',
|
||||
var src = '';
|
||||
|
||||
// Type3 fonts
|
||||
d0: 'setCharWidth',
|
||||
d1: 'setCharWidthAndBounds',
|
||||
var args = [];
|
||||
var obj;
|
||||
while (!IsEOF(obj = parser.getObj())) {
|
||||
if (IsCmd(obj)) {
|
||||
var cmd = obj.cmd;
|
||||
var fn = OP_MAP[cmd];
|
||||
assertWellFormed(fn, "Unknown command '" + cmd + "'");
|
||||
// TODO figure out how to type-check vararg functions
|
||||
|
||||
// Color
|
||||
CS: 'setStrokeColorSpace',
|
||||
cs: 'setFillColorSpace',
|
||||
SC: 'setStrokeColor',
|
||||
SCN: 'setStrokeColorN',
|
||||
sc: 'setFillColor',
|
||||
scn: 'setFillColorN',
|
||||
G: 'setStrokeGray',
|
||||
g: 'setFillGray',
|
||||
RG: 'setStrokeRGBColor',
|
||||
rg: 'setFillRGBColor',
|
||||
K: 'setStrokeCMYKColor',
|
||||
k: 'setFillCMYKColor',
|
||||
if (cmd == 'Do' && !args[0].code) { // eagerly compile XForm objects
|
||||
var name = args[0].name;
|
||||
var xobj = xobjs.get(name);
|
||||
if (xobj) {
|
||||
xobj = xref.fetchIfRef(xobj);
|
||||
assertWellFormed(IsStream(xobj), 'XObject should be a stream');
|
||||
|
||||
// Shading
|
||||
sh: 'shadingFill',
|
||||
var type = xobj.dict.get('Subtype');
|
||||
assertWellFormed(
|
||||
IsName(type),
|
||||
'XObject should have a Name subtype'
|
||||
);
|
||||
|
||||
// Images
|
||||
BI: 'beginInlineImage',
|
||||
if ('Form' == type.name) {
|
||||
args[0].code = this.eval(xobj,
|
||||
xref,
|
||||
xobj.dict.get('Resources'),
|
||||
fonts);
|
||||
}
|
||||
}
|
||||
} else if (cmd == 'Tf') { // eagerly collect all fonts
|
||||
var fontRes = resources.get('Font');
|
||||
if (fontRes) {
|
||||
fontRes = xref.fetchIfRef(fontRes);
|
||||
var font = xref.fetchIfRef(fontRes.get(args[0].name));
|
||||
assertWellFormed(IsDict(font));
|
||||
if (!font.translated) {
|
||||
font.translated = this.translateFont(font, xref, resources);
|
||||
if (fonts && font.translated) {
|
||||
// keep track of each font we translated so the caller can
|
||||
// load them asynchronously before calling display on a page
|
||||
fonts.push(font.translated);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XObjects
|
||||
Do: 'paintXObject',
|
||||
src += 'this.';
|
||||
src += fn;
|
||||
src += '(';
|
||||
src += args.map(emitArg).join(',');
|
||||
src += ');\n';
|
||||
|
||||
// Marked content
|
||||
MP: 'markPoint',
|
||||
DP: 'markPointProps',
|
||||
BMC: 'beginMarkedContent',
|
||||
BDC: 'beginMarkedContentProps',
|
||||
EMC: 'endMarkedContent',
|
||||
args.length = 0;
|
||||
} else {
|
||||
assertWellFormed(args.length <= 33, 'Too many arguments');
|
||||
args.push(obj);
|
||||
}
|
||||
}
|
||||
|
||||
// Compatibility
|
||||
BX: 'beginCompat',
|
||||
EX: 'endCompat'
|
||||
var fn = Function('objpool', src);
|
||||
return function(gfx) { fn.call(gfx, objpool); };
|
||||
},
|
||||
|
||||
translateFont: function(fontDict, xref, resources) {
|
||||
@ -3697,7 +3785,66 @@ var CanvasGraphics = (function() {
|
||||
properties: properties
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
// <canvas> contexts store most of the state we need natively.
|
||||
// However, PDF needs a bit more state, which we store here.
|
||||
var CanvasExtraState = (function() {
|
||||
function constructor() {
|
||||
// Are soft masks and alpha values shapes or opacities?
|
||||
this.alphaIsShape = false;
|
||||
this.fontSize = 0;
|
||||
this.textMatrix = IDENTITY_MATRIX;
|
||||
this.leading = 0;
|
||||
// Current point (in user coordinates)
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
// Start of text line (in text coordinates)
|
||||
this.lineX = 0;
|
||||
this.lineY = 0;
|
||||
// Character and word spacing
|
||||
this.charSpace = 0;
|
||||
this.wordSpace = 0;
|
||||
this.textHScale = 100;
|
||||
// Color spaces
|
||||
this.fillColorSpace = null;
|
||||
this.strokeColorSpace = null;
|
||||
}
|
||||
constructor.prototype = {
|
||||
};
|
||||
return constructor;
|
||||
})();
|
||||
|
||||
function ScratchCanvas(width, height) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return canvas;
|
||||
}
|
||||
|
||||
var CanvasGraphics = (function() {
|
||||
function constructor(canvasCtx, imageCanvas) {
|
||||
this.ctx = canvasCtx;
|
||||
this.current = new CanvasExtraState();
|
||||
this.stateStack = [];
|
||||
this.pendingClip = null;
|
||||
this.res = null;
|
||||
this.xobjs = null;
|
||||
this.ScratchCanvas = imageCanvas || ScratchCanvas;
|
||||
}
|
||||
|
||||
var LINE_CAP_STYLES = ['butt', 'round', 'square'];
|
||||
var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
|
||||
var NORMAL_CLIP = {};
|
||||
var EO_CLIP = {};
|
||||
|
||||
// Used for tiling patterns
|
||||
var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
|
||||
|
||||
constructor.prototype = {
|
||||
beginDrawing: function(mediaBox) {
|
||||
var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
|
||||
this.ctx.save();
|
||||
@ -3705,6 +3852,11 @@ var CanvasGraphics = (function() {
|
||||
this.ctx.translate(0, -mediaBox.height);
|
||||
},
|
||||
|
||||
compile: function(stream, xref, resources, fonts) {
|
||||
var pe = new PartialEvaluator();
|
||||
return pe.eval(stream, xref, resources, fonts);
|
||||
},
|
||||
|
||||
execute: function(code, xref, resources) {
|
||||
resources = xref.fetchIfRef(resources) || new Dict();
|
||||
var savedXref = this.xref, savedRes = this.res, savedXobjs = this.xobjs;
|
||||
@ -3719,88 +3871,6 @@ var CanvasGraphics = (function() {
|
||||
this.xref = savedXref;
|
||||
},
|
||||
|
||||
compile: function(stream, xref, resources, fonts) {
|
||||
resources = xref.fetchIfRef(resources) || new Dict();
|
||||
var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict();
|
||||
|
||||
var parser = new Parser(new Lexer(stream), false);
|
||||
var objpool = [];
|
||||
|
||||
function emitArg(arg) {
|
||||
if (typeof arg == 'object' || typeof arg == 'string') {
|
||||
var index = objpool.length;
|
||||
objpool[index] = arg;
|
||||
return 'objpool[' + index + ']';
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
var src = '';
|
||||
|
||||
var args = [];
|
||||
var map = this.map;
|
||||
var obj;
|
||||
while (!IsEOF(obj = parser.getObj())) {
|
||||
if (IsCmd(obj)) {
|
||||
var cmd = obj.cmd;
|
||||
var fn = map[cmd];
|
||||
assertWellFormed(fn, "Unknown command '" + cmd + "'");
|
||||
// TODO figure out how to type-check vararg functions
|
||||
|
||||
if (cmd == 'Do' && !args[0].code) { // eagerly compile XForm objects
|
||||
var name = args[0].name;
|
||||
var xobj = xobjs.get(name);
|
||||
if (xobj) {
|
||||
xobj = xref.fetchIfRef(xobj);
|
||||
assertWellFormed(IsStream(xobj), 'XObject should be a stream');
|
||||
|
||||
var type = xobj.dict.get('Subtype');
|
||||
assertWellFormed(
|
||||
IsName(type),
|
||||
'XObject should have a Name subtype'
|
||||
);
|
||||
|
||||
if ('Form' == type.name) {
|
||||
args[0].code = this.compile(xobj,
|
||||
xref,
|
||||
xobj.dict.get('Resources'),
|
||||
fonts);
|
||||
}
|
||||
}
|
||||
} else if (cmd == 'Tf') { // eagerly collect all fonts
|
||||
var fontRes = resources.get('Font');
|
||||
if (fontRes) {
|
||||
fontRes = xref.fetchIfRef(fontRes);
|
||||
var font = xref.fetchIfRef(fontRes.get(args[0].name));
|
||||
assertWellFormed(IsDict(font));
|
||||
if (!font.translated) {
|
||||
font.translated = this.translateFont(font, xref, resources);
|
||||
if (fonts && font.translated) {
|
||||
// keep track of each font we translated so the caller can
|
||||
// load them asynchronously before calling display on a page
|
||||
fonts.push(font.translated);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
src += 'this.';
|
||||
src += fn;
|
||||
src += '(';
|
||||
src += args.map(emitArg).join(',');
|
||||
src += ');\n';
|
||||
|
||||
args.length = 0;
|
||||
} else {
|
||||
assertWellFormed(args.length <= 33, 'Too many arguments');
|
||||
args.push(obj);
|
||||
}
|
||||
}
|
||||
|
||||
var fn = Function('objpool', src);
|
||||
return function(gfx) { fn.call(gfx, objpool); };
|
||||
},
|
||||
|
||||
endDrawing: function() {
|
||||
this.ctx.restore();
|
||||
},
|
||||
@ -4349,8 +4419,8 @@ var CanvasGraphics = (function() {
|
||||
// Most likely we will not implement other types of shading
|
||||
// unless the browser supports them
|
||||
if (!shadingFn) {
|
||||
TODO("Unknown or NYI type of shading '"+ typeNum +"'");
|
||||
return this.makeCssRgb(0, 0, 0);
|
||||
warn("Unknown or NYI type of shading '"+ typeNum +"'");
|
||||
return 'hotpink';
|
||||
}
|
||||
|
||||
return shadingFn.call(this, shading, cs);
|
||||
@ -5310,13 +5380,16 @@ var PDFFunction = (function() {
|
||||
return array;
|
||||
},
|
||||
constructInterpolated: function() {
|
||||
error('unhandled type of function');
|
||||
TODO('unhandled type of function');
|
||||
this.func = function () { return [ 255, 105, 180 ]; }
|
||||
},
|
||||
constructStiched: function() {
|
||||
error('unhandled type of function');
|
||||
TODO('unhandled type of function');
|
||||
this.func = function () { return [ 255, 105, 180 ]; }
|
||||
},
|
||||
constructPostScript: function() {
|
||||
error('unhandled type of function');
|
||||
TODO('unhandled type of function');
|
||||
this.func = function () { return [ 255, 105, 180 ]; }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
/*
|
||||
* A Test Driver for PDF.js
|
||||
*/
|
||||
|
||||
|
||||
var appPath, browser, canvas, currentTaskIdx, manifest, stdout;
|
||||
|
||||
function queryParams() {
|
||||
@ -21,16 +23,16 @@ function load() {
|
||||
browser = params.browser;
|
||||
manifestFile = params.manifestFile;
|
||||
appPath = params.path;
|
||||
|
||||
|
||||
canvas = document.createElement("canvas");
|
||||
canvas.mozOpaque = true;
|
||||
stdout = document.getElementById("stdout");
|
||||
|
||||
|
||||
log("load...\n");
|
||||
|
||||
log("Harness thinks this browser is '"+ browser + "' with path " + appPath + "\n");
|
||||
log("Fetching manifest "+ manifestFile +"...");
|
||||
|
||||
|
||||
var r = new XMLHttpRequest();
|
||||
r.open("GET", manifestFile, false);
|
||||
r.onreadystatechange = function(e) {
|
||||
@ -61,15 +63,15 @@ function nextTask() {
|
||||
if (r.readyState == 4) {
|
||||
var data = r.mozResponseArrayBuffer || r.mozResponse ||
|
||||
r.responseArrayBuffer || r.response;
|
||||
|
||||
|
||||
try {
|
||||
task.pdfDoc = new PDFDoc(new Stream(data));
|
||||
} catch(e) {
|
||||
failure = 'load PDF doc: '+ e.toString();
|
||||
}
|
||||
|
||||
|
||||
task.pageNum = 1, nextPage(task, failure);
|
||||
}
|
||||
}
|
||||
};
|
||||
r.send(null);
|
||||
}
|
||||
@ -92,25 +94,13 @@ function nextPage(task, loadError) {
|
||||
var failure = loadError || '';
|
||||
|
||||
var ctx = null;
|
||||
var fonts;
|
||||
var gfx = null;
|
||||
var page = null;
|
||||
|
||||
if (!failure) {
|
||||
log(" loading page "+ task.pageNum +"... ");
|
||||
ctx = canvas.getContext("2d");
|
||||
fonts = [];
|
||||
try {
|
||||
gfx = new CanvasGraphics(ctx);
|
||||
log(" loading page "+ task.pageNum +"... ");
|
||||
ctx = canvas.getContext("2d");
|
||||
page = task.pdfDoc.getPage(task.pageNum);
|
||||
page.compile(gfx, fonts);
|
||||
} catch(e) {
|
||||
failure = 'compile: '+ e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (!failure) {
|
||||
try {
|
||||
var pdfToCssUnitsCoef = 96.0 / 72.0;
|
||||
// using mediaBox for the canvas size
|
||||
var pageWidth = (page.mediaBox[2] - page.mediaBox[0]);
|
||||
@ -118,42 +108,28 @@ function nextPage(task, loadError) {
|
||||
canvas.width = pageWidth * pdfToCssUnitsCoef;
|
||||
canvas.height = pageHeight * pdfToCssUnitsCoef;
|
||||
clear(ctx);
|
||||
|
||||
page.startRendering(
|
||||
ctx,
|
||||
function() { snapshotCurrentPage(page, task, failure); });
|
||||
} catch(e) {
|
||||
failure = 'page setup: '+ e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (!failure) {
|
||||
try {
|
||||
FontLoader.bind(fonts, function() {
|
||||
snapshotCurrentPage(gfx, page, task, failure);
|
||||
});
|
||||
} catch(e) {
|
||||
failure = 'fonts: '+ e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
// Skip right to snapshotting if there was a failure, since the
|
||||
// fonts might be in an inconsistent state.
|
||||
snapshotCurrentPage(gfx, page, task, failure);
|
||||
snapshotCurrentPage(page, task, failure);
|
||||
}
|
||||
}
|
||||
|
||||
function snapshotCurrentPage(gfx, page, task, failure) {
|
||||
function snapshotCurrentPage(page, task, failure) {
|
||||
log("done, snapshotting... ");
|
||||
|
||||
if (!failure) {
|
||||
try {
|
||||
page.display(gfx);
|
||||
} catch(e) {
|
||||
failure = 'render: '+ e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
sendTaskResult(canvas.toDataURL("image/png"), task, failure);
|
||||
log("done"+ (failure ? " (failed!: "+ failure +")" : "") +"\n");
|
||||
|
||||
|
||||
// Set up the next request
|
||||
backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0;
|
||||
setTimeout(function() {
|
||||
|
@ -189,7 +189,7 @@ class BaseBrowserCommand(object):
|
||||
self._fixupMacPath()
|
||||
|
||||
if not os.path.exists(self.path):
|
||||
throw("Path to browser '%s' does not exist." % self.path)
|
||||
raise Exception("Path to browser '%s' does not exist." % self.path)
|
||||
|
||||
def setup(self):
|
||||
self.tempDir = tempfile.mkdtemp()
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Binary file not shown.
@ -16,6 +16,7 @@ canvas {
|
||||
|
||||
span {
|
||||
font-size: 0.8em;
|
||||
text-shadow: 0px 1px 0px #fff;
|
||||
}
|
||||
|
||||
.control {
|
||||
@ -31,12 +32,12 @@ span {
|
||||
height: 20px;
|
||||
padding: 0px;
|
||||
margin: 0px 2px 0px 0px;
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
|
||||
-moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
|
||||
-webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.3);
|
||||
-moz-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.3);
|
||||
-webkit-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.control > select {
|
||||
@ -45,12 +46,12 @@ span {
|
||||
height: 22px;
|
||||
padding: 2px 0px 0px;
|
||||
margin: 0px 0px 1px;
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
|
||||
-moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
|
||||
-webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.3);
|
||||
-moz-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.3);
|
||||
-webkit-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.control > span {
|
||||
@ -96,6 +97,8 @@ span {
|
||||
|
||||
#controls {
|
||||
background-color: #eee;
|
||||
background: -moz-linear-gradient(center bottom, #ddd 0%, #fff 100%);
|
||||
background: -webkit-gradient(linear, left bottom, left top, color-stop(0.0, #ddd), color-stop(1.0, #fff));
|
||||
border-bottom: 1px solid #666;
|
||||
padding: 4px 0px 0px 8px;
|
||||
position: fixed;
|
||||
@ -114,58 +117,121 @@ span {
|
||||
-webkit-user-select: text;
|
||||
}
|
||||
|
||||
#previousPageButton {
|
||||
background: url('images/buttons.png') no-repeat 0px -23px;
|
||||
button {
|
||||
background-color: #ddd;
|
||||
background: -moz-linear-gradient(center bottom, #c3c3c3 0%, #f3f3f3 100%);
|
||||
background: -webkit-gradient(linear, left bottom, left top, color-stop(0.0, #c3c3c3), color-stop(1.0, #f3f3f3));
|
||||
border: 1px solid #4d4d4d;
|
||||
cursor: default;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin: 0px;
|
||||
margin: 0px 0px 1px;
|
||||
width: 29px;
|
||||
height: 22px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
background-color: #eee;
|
||||
background: -moz-linear-gradient(center bottom, #ddd 0%, #fff 100%);
|
||||
background: -webkit-gradient(linear, left bottom, left top, color-stop(0.0, #ddd), color-stop(1.0, #fff));
|
||||
}
|
||||
|
||||
button:disabled > span {
|
||||
opacity: 0.3;
|
||||
-moz-opacity: 0.3;
|
||||
-webkit-opacity: 0.3;
|
||||
}
|
||||
|
||||
button.down {
|
||||
background-color: #777;
|
||||
background: -moz-linear-gradient(center bottom, #888 0%, #555 100%);
|
||||
background: -webkit-gradient(linear, left bottom, left top, color-stop(0.0, #888), color-stop(1.0, #555));
|
||||
box-shadow: inset 0px 0px 2px rgba(0, 0, 0, 0.8);
|
||||
-moz-box-shadow: inset 0px 0px 2px rgba(0, 0, 0, 0.8);
|
||||
-webkit-box-shadow: inset 0px 0px 2px rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
#previousPageButton {
|
||||
width: 28px;
|
||||
height: 23px;
|
||||
border-right: 0px;
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
-moz-border-radius-topright: 0px;
|
||||
-moz-border-radius-bottomright: 0px;
|
||||
-webkit-border-top-right-radius: 0px;
|
||||
-webkit-border-bottom-right-radius: 0px;
|
||||
}
|
||||
|
||||
#previousPageButton.down {
|
||||
background: url('images/buttons.png') no-repeat 0px -46px;
|
||||
}
|
||||
|
||||
#previousPageButton.disabled {
|
||||
#previousPageButton > span {
|
||||
background: url('images/buttons.png') no-repeat 0px 0px;
|
||||
display: inline-block;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
#nextPageButton {
|
||||
background: url('images/buttons.png') no-repeat -28px -23px;
|
||||
cursor: default;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin: 0px;
|
||||
width: 28px;
|
||||
height: 23px;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
-moz-border-radius-topleft: 0px;
|
||||
-moz-border-radius-bottomleft: 0px;
|
||||
-webkit-border-top-left-radius: 0px;
|
||||
-webkit-border-bottom-left-radius: 0px;
|
||||
}
|
||||
|
||||
#nextPageButton.down {
|
||||
background: url('images/buttons.png') no-repeat -28px -46px;
|
||||
#nextPageButton > span {
|
||||
background: url('images/buttons.png') no-repeat -19px 0px;
|
||||
display: inline-block;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
#nextPageButton.disabled {
|
||||
background: url('images/buttons.png') no-repeat -28px 0px;
|
||||
#singleLayoutButton {
|
||||
width: 28px;
|
||||
border-right: 0px;
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
-moz-border-radius-topright: 0px;
|
||||
-moz-border-radius-bottomright: 0px;
|
||||
-webkit-border-top-right-radius: 0px;
|
||||
-webkit-border-bottom-right-radius: 0px;
|
||||
}
|
||||
|
||||
#singleLayoutButton > span {
|
||||
background: url('images/buttons.png') no-repeat -57px 0px;
|
||||
display: inline-block;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
#splitLayoutButton {
|
||||
width: 28px;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
-moz-border-radius-topleft: 0px;
|
||||
-moz-border-radius-bottomleft: 0px;
|
||||
-webkit-border-top-left-radius: 0px;
|
||||
-webkit-border-bottom-left-radius: 0px;
|
||||
}
|
||||
|
||||
#splitLayoutButton > span {
|
||||
background: url('images/buttons.png') no-repeat -76px 0px;
|
||||
display: inline-block;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
#openFileButton {
|
||||
background: url('images/buttons.png') no-repeat -56px -23px;
|
||||
cursor: default;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
#openFileButton > span {
|
||||
background: url('images/buttons.png') no-repeat -38px 0px;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin: 0px 0px 0px 3px;
|
||||
width: 29px;
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
#openFileButton.down {
|
||||
background: url('images/buttons.png') no-repeat -56px -46px;
|
||||
}
|
||||
|
||||
#openFileButton.disabled {
|
||||
background: url('images/buttons.png') no-repeat -56px 0px;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
#fileInput {
|
||||
|
@ -14,8 +14,8 @@
|
||||
<body>
|
||||
<div id="controls">
|
||||
<span class="control">
|
||||
<span id="previousPageButton" class="disabled"></span>
|
||||
<span id="nextPageButton" class="disabled"></span>
|
||||
<button id="previousPageButton" disabled="disabled"><span></span></button>
|
||||
<button id="nextPageButton" disabled="disabled"><span></span></button>
|
||||
<span class="label">Previous/Next</span>
|
||||
</span>
|
||||
<span class="control">
|
||||
@ -35,8 +35,18 @@
|
||||
</select>
|
||||
<span class="label">Zoom</span>
|
||||
</span>
|
||||
|
||||
<!-- WIP: Leave commented out until implemented -->
|
||||
<!--
|
||||
<span class="control">
|
||||
<button id="singleLayoutButton" class="selected"><span></span></button>
|
||||
<button id="splitLayoutButton"><span></span></button>
|
||||
<span class="label">Page Layout</span>
|
||||
</span>
|
||||
-->
|
||||
|
||||
<span class="control" id="fileWrapper">
|
||||
<span id="openFileButton"></span>
|
||||
<button id="openFileButton"><span></span></button>
|
||||
<input type="file" id="fileInput"/>
|
||||
<span class="label">Open File</span>
|
||||
</span>
|
||||
|
@ -43,7 +43,7 @@ var PDFViewer = {
|
||||
lastPagesDrawn: [],
|
||||
|
||||
visiblePages: function() {
|
||||
const pageBottomMargin = 10;
|
||||
var pageBottomMargin = 10;
|
||||
var windowTop = window.pageYOffset;
|
||||
var windowBottom = window.pageYOffset + window.innerHeight;
|
||||
|
||||
@ -123,14 +123,7 @@ var PDFViewer = {
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
|
||||
var gfx = new CanvasGraphics(ctx);
|
||||
|
||||
// page.compile will collect all fonts for us, once we have loaded them
|
||||
// we can trigger the actual page rendering with page.display
|
||||
var fonts = [];
|
||||
page.compile(gfx, fonts);
|
||||
|
||||
FontLoader.bind(fonts, function() { page.display(gfx); });
|
||||
page.startRendering(ctx, function() { });
|
||||
}
|
||||
},
|
||||
|
||||
@ -183,14 +176,7 @@ var PDFViewer = {
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
|
||||
var gfx = new CanvasGraphics(ctx);
|
||||
|
||||
// page.compile will collect all fonts for us, once we have loaded them
|
||||
// we can trigger the actual page rendering with page.display
|
||||
var fonts = [];
|
||||
page.compile(gfx, fonts);
|
||||
|
||||
FontLoader.bind(fonts, function() { page.display(gfx); });
|
||||
page.startRendering(ctx, function() { });
|
||||
}
|
||||
},
|
||||
|
||||
@ -243,10 +229,8 @@ var PDFViewer = {
|
||||
setTimeout(window.onscroll, 0);
|
||||
document.location.hash = PDFViewer.pageNumber;
|
||||
|
||||
PDFViewer.previousPageButton.className =
|
||||
(PDFViewer.pageNumber === 1) ? 'disabled' : '';
|
||||
PDFViewer.nextPageButton.className =
|
||||
(PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
|
||||
PDFViewer.previousPageButton.disabled = (PDFViewer.pageNumber === 1);
|
||||
PDFViewer.nextPageButton.disabled = (PDFViewer.pageNumber === PDFViewer.numberOfPages);
|
||||
}
|
||||
},
|
||||
|
||||
@ -333,10 +317,8 @@ var PDFViewer = {
|
||||
}).bind(this), 500);
|
||||
}
|
||||
|
||||
PDFViewer.previousPageButton.className =
|
||||
(PDFViewer.pageNumber === 1) ? 'disabled' : '';
|
||||
PDFViewer.nextPageButton.className =
|
||||
(PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
|
||||
PDFViewer.previousPageButton.disabled = (PDFViewer.pageNumber === 1);
|
||||
PDFViewer.nextPageButton.disabled = (PDFViewer.pageNumber === PDFViewer.numberOfPages);
|
||||
}
|
||||
};
|
||||
|
||||
@ -404,42 +386,30 @@ window.onload = function() {
|
||||
|
||||
PDFViewer.previousPageButton = document.getElementById('previousPageButton');
|
||||
PDFViewer.previousPageButton.onclick = function(evt) {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
PDFViewer.goToPreviousPage();
|
||||
}
|
||||
PDFViewer.goToPreviousPage();
|
||||
};
|
||||
PDFViewer.previousPageButton.onmousedown = function(evt) {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
this.className = 'down';
|
||||
}
|
||||
this.className = 'down';
|
||||
};
|
||||
PDFViewer.previousPageButton.onmouseup = function(evt) {
|
||||
this.className =
|
||||
(this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
|
||||
this.className = '';
|
||||
};
|
||||
PDFViewer.previousPageButton.onmouseout = function(evt) {
|
||||
this.className =
|
||||
(this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
|
||||
this.className = '';
|
||||
};
|
||||
|
||||
PDFViewer.nextPageButton = document.getElementById('nextPageButton');
|
||||
PDFViewer.nextPageButton.onclick = function(evt) {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
PDFViewer.goToNextPage();
|
||||
}
|
||||
PDFViewer.goToNextPage();
|
||||
};
|
||||
PDFViewer.nextPageButton.onmousedown = function(evt) {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
this.className = 'down';
|
||||
}
|
||||
this.className = 'down';
|
||||
};
|
||||
PDFViewer.nextPageButton.onmouseup = function(evt) {
|
||||
this.className =
|
||||
(this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
|
||||
this.className = '';
|
||||
};
|
||||
PDFViewer.nextPageButton.onmouseout = function(evt) {
|
||||
this.className =
|
||||
(this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
|
||||
this.className = '';
|
||||
};
|
||||
|
||||
PDFViewer.scaleSelect = document.getElementById('scaleSelect');
|
||||
@ -450,22 +420,16 @@ window.onload = function() {
|
||||
if (window.File && window.FileReader && window.FileList && window.Blob) {
|
||||
var openFileButton = document.getElementById('openFileButton');
|
||||
openFileButton.onclick = function(evt) {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
PDFViewer.fileInput.click();
|
||||
}
|
||||
PDFViewer.fileInput.click();
|
||||
};
|
||||
openFileButton.onmousedown = function(evt) {
|
||||
if (this.className.indexOf('disabled') === -1) {
|
||||
this.className = 'down';
|
||||
}
|
||||
this.className = 'down';
|
||||
};
|
||||
openFileButton.onmouseup = function(evt) {
|
||||
this.className =
|
||||
(this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
|
||||
this.className = '';
|
||||
};
|
||||
openFileButton.onmouseout = function(evt) {
|
||||
this.className =
|
||||
(this.className.indexOf('disabled') !== -1) ? 'disabled' : '';
|
||||
this.className = '';
|
||||
};
|
||||
|
||||
PDFViewer.fileInput = document.getElementById('fileInput');
|
||||
@ -540,10 +504,8 @@ window.onload = function() {
|
||||
// Update the page number input with the current page number.
|
||||
if (!PDFViewer.willJumpToPage && visiblePages.length > 0) {
|
||||
PDFViewer.pageNumber = PDFViewer.pageNumberInput.value = visiblePages[0];
|
||||
PDFViewer.previousPageButton.className =
|
||||
(PDFViewer.pageNumber === 1) ? 'disabled' : '';
|
||||
PDFViewer.nextPageButton.className =
|
||||
(PDFViewer.pageNumber === PDFViewer.numberOfPages) ? 'disabled' : '';
|
||||
PDFViewer.previousPageButton.disabled = (PDFViewer.pageNumber === 1);
|
||||
PDFViewer.nextPageButton.disabled = (PDFViewer.pageNumber === PDFViewer.numberOfPages);
|
||||
} else {
|
||||
PDFViewer.willJumpToPage = false;
|
||||
}
|
||||
|
@ -72,29 +72,15 @@ function displayPage(num) {
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
|
||||
var gfx = new CanvasGraphics(ctx);
|
||||
|
||||
// page.compile will collect all fonts for us, once we have loaded them
|
||||
// we can trigger the actual page rendering with page.display
|
||||
var fonts = [];
|
||||
page.compile(gfx, fonts);
|
||||
var t2 = Date.now();
|
||||
|
||||
function displayPage() {
|
||||
var t3 = Date.now();
|
||||
|
||||
page.display(gfx);
|
||||
|
||||
var t4 = Date.now();
|
||||
|
||||
var infoDisplay = document.getElementById('info');
|
||||
infoDisplay.innerHTML = 'Time to load/compile/fonts/render: ' +
|
||||
(t1 - t0) + '/' + (t2 - t1) + '/' + (t3 - t2) + '/' + (t4 - t3) + ' ms';
|
||||
}
|
||||
|
||||
// Always defer call to displayPage() to work around bug in
|
||||
// Firefox error reporting from XHR callbacks.
|
||||
FontLoader.bind(fonts, function() { setTimeout(displayPage, 0); });
|
||||
page.startRendering(
|
||||
ctx,
|
||||
function() {
|
||||
var infoDisplay = document.getElementById('info');
|
||||
var stats = page.stats;
|
||||
var t2 = stats.compile, t3 = stats.fonts, t4 = stats.render;
|
||||
infoDisplay.innerHTML = 'Time to load/compile/fonts/render: ' +
|
||||
(t1 - t0) + '/' + (t2 - t1) + '/' + (t3 - t2) + '/' + (t4 - t3) + ' ms';
|
||||
});
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user