Merge remote-tracking branch 'origin/decodemap' into smaskscale

This commit is contained in:
Brendan Dahl 2011-12-15 15:20:36 -08:00
commit 01e876f014
11 changed files with 97 additions and 94 deletions

View File

@ -1,6 +1,6 @@
# pdf.js # pdf.js
## Overview ## Overview
@ -205,3 +205,4 @@ a "PDF Reference" from Adobe:
Recommended chapters to read: "2. Overview", "3.4 File Structure", Recommended chapters to read: "2. Overview", "3.4 File Structure",
"4.1 Graphics Objects" that lists the PDF commands. "4.1 Graphics Objects" that lists the PDF commands.

View File

@ -638,17 +638,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
geometry.hScale = tr[0] - bl[0]; geometry.hScale = tr[0] - bl[0];
geometry.vScale = tr[1] - bl[1]; geometry.vScale = tr[1] - bl[1];
} }
var spaceGlyph = font.charsToGlyphs(' '); geometry.spaceWidth = font.spaceWidth;
// Hack (sometimes space is not encoded)
if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0)
spaceGlyph = font.charsToGlyphs('i');
// Fallback
if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0)
spaceGlyph = [{width: 0}];
geometry.spaceWidth = spaceGlyph[0].width;
return geometry; return geometry;
}, },
@ -687,13 +677,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var textSelection = textLayer && !skipTextSelection ? true : false; var textSelection = textLayer && !skipTextSelection ? true : false;
var textRenderingMode = current.textRenderingMode; var textRenderingMode = current.textRenderingMode;
if (textSelection) {
ctx.save();
this.applyTextTransforms();
text.geom = this.getTextGeometry();
ctx.restore();
}
// Type3 fonts - each glyph is a "mini-PDF" // Type3 fonts - each glyph is a "mini-PDF"
if (font.coded) { if (font.coded) {
ctx.save(); ctx.save();
@ -701,6 +684,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
ctx.translate(current.x, current.y); ctx.translate(current.x, current.y);
ctx.scale(textHScale, 1); ctx.scale(textHScale, 1);
if (textSelection) {
this.save();
ctx.scale(1, -1);
text.geom = this.getTextGeometry();
this.restore();
}
for (var i = 0; i < glyphsLength; ++i) { for (var i = 0; i < glyphsLength; ++i) {
var glyph = glyphs[i]; var glyph = glyphs[i];
@ -720,7 +710,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var width = transformed[0] * fontSize + charSpacing; var width = transformed[0] * fontSize + charSpacing;
ctx.translate(width, 0); ctx.translate(width, 0);
current.x += width * textHScale2; current.x += width * textHScale;
text.str += glyph.unicode; text.str += glyph.unicode;
text.length++; text.length++;
@ -730,6 +720,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
} else { } else {
ctx.save(); ctx.save();
this.applyTextTransforms(); this.applyTextTransforms();
if (textSelection)
text.geom = this.getTextGeometry();
var width = 0; var width = 0;
for (var i = 0; i < glyphsLength; ++i) { for (var i = 0; i < glyphsLength; ++i) {
@ -780,18 +772,26 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
showSpacedText: function canvasGraphicsShowSpacedText(arr) { showSpacedText: function canvasGraphicsShowSpacedText(arr) {
var ctx = this.ctx; var ctx = this.ctx;
var current = this.current; var current = this.current;
var font = current.font;
var fontSize = current.fontSize; var fontSize = current.fontSize;
var textHScale2 = current.textHScale * var textHScale = current.textHScale;
(current.font.fontMatrix || IDENTITY_MATRIX)[0]; if (!font.coded)
textHScale *= (font.fontMatrix || IDENTITY_MATRIX)[0];
var arrLength = arr.length; var arrLength = arr.length;
var textLayer = this.textLayer; var textLayer = this.textLayer;
var font = current.font;
var text = {str: '', length: 0, canvasWidth: 0, geom: {}}; var text = {str: '', length: 0, canvasWidth: 0, geom: {}};
var textSelection = textLayer ? true : false; var textSelection = textLayer ? true : false;
if (textSelection) { if (textSelection) {
ctx.save(); ctx.save();
this.applyTextTransforms(); // Type3 fonts - each glyph is a "mini-PDF" (see also showText)
if (font.coded) {
ctx.transform.apply(ctx, current.textMatrix);
ctx.scale(1, -1);
ctx.translate(current.x, -1 * current.y);
ctx.scale(textHScale, 1);
} else
this.applyTextTransforms();
text.geom = this.getTextGeometry(); text.geom = this.getTextGeometry();
ctx.restore(); ctx.restore();
} }
@ -799,7 +799,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
for (var i = 0; i < arrLength; ++i) { for (var i = 0; i < arrLength; ++i) {
var e = arr[i]; var e = arr[i];
if (isNum(e)) { if (isNum(e)) {
var spacingLength = -e * 0.001 * fontSize * textHScale2; var spacingLength = -e * 0.001 * fontSize * textHScale;
current.x += spacingLength; current.x += spacingLength;
if (textSelection) { if (textSelection) {
@ -807,9 +807,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
text.canvasWidth += spacingLength; text.canvasWidth += spacingLength;
if (e < 0 && text.geom.spaceWidth > 0) { // avoid div by zero if (e < 0 && text.geom.spaceWidth > 0) { // avoid div by zero
var numFakeSpaces = Math.round(-e / text.geom.spaceWidth); var numFakeSpaces = Math.round(-e / text.geom.spaceWidth);
for (var j = 0; j < numFakeSpaces; ++j) if (numFakeSpaces > 0) {
text.str += '&nbsp;'; text.str += '&nbsp;';
text.length += numFakeSpaces > 0 ? 1 : 0; text.length++;
}
} }
} }
} else if (isString(e)) { } else if (isString(e)) {
@ -1105,9 +1106,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
paintImageXObject: function canvasGraphicsPaintImageXObject(objId) { paintImageXObject: function canvasGraphicsPaintImageXObject(objId) {
var imgData = this.objs.get(objId); var imgData = this.objs.get(objId);
if (!imgData) { if (!imgData)
error('Dependent image isn\'t ready yet'); error('Dependent image isn\'t ready yet');
}
this.save(); this.save();
var ctx = this.ctx; var ctx = this.ctx;
var w = imgData.width; var w = imgData.width;

View File

@ -515,8 +515,7 @@ var PDFDoc = (function PDFDocClosure() {
// Tell the worker the file it was created from. // Tell the worker the file it was created from.
messageHandler.send('workerSrc', workerSrc); messageHandler.send('workerSrc', workerSrc);
messageHandler.on('test', function pdfDocTest(message) { messageHandler.on('test', function pdfDocTest(supportTypedArray) {
var supportTypedArray = message.data;
if (supportTypedArray) { if (supportTypedArray) {
this.worker = worker; this.worker = worker;
this.setupMessageHandler(messageHandler); this.setupMessageHandler(messageHandler);
@ -554,8 +553,7 @@ var PDFDoc = (function PDFDocClosure() {
setupMessageHandler: function(messageHandler) { setupMessageHandler: function(messageHandler) {
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
messageHandler.on('page', function pdfDocPage(message) { messageHandler.on('page', function pdfDocPage(data) {
var data = message.data;
var pageNum = data.pageNum; var pageNum = data.pageNum;
var page = this.pageCache[pageNum]; var page = this.pageCache[pageNum];
var depFonts = data.depFonts; var depFonts = data.depFonts;
@ -563,8 +561,7 @@ var PDFDoc = (function PDFDocClosure() {
page.startRenderingFromIRQueue(data.IRQueue, depFonts); page.startRenderingFromIRQueue(data.IRQueue, depFonts);
}, this); }, this);
messageHandler.on('obj', function pdfDocObj(message) { messageHandler.on('obj', function pdfDocObj(data) {
var data = message.data;
var id = data[0]; var id = data[0];
var type = data[1]; var type = data[1];
@ -601,8 +598,7 @@ var PDFDoc = (function PDFDocClosure() {
} }
}, this); }, this);
messageHandler.on('font_ready', function pdfDocFontReady(message) { messageHandler.on('font_ready', function pdfDocFontReady(data) {
var data = message.data;
var id = data[0]; var id = data[0];
var font = new FontShape(data[1]); var font = new FontShape(data[1]);
@ -614,8 +610,7 @@ var PDFDoc = (function PDFDocClosure() {
} }
}.bind(this)); }.bind(this));
messageHandler.on('page_error', function pdfDocError(message) { messageHandler.on('page_error', function pdfDocError(data) {
var data = message.data;
var page = this.pageCache[data.pageNum]; var page = this.pageCache[data.pageNum];
if (page.callback) if (page.callback)
page.callback(data.error); page.callback(data.error);
@ -623,9 +618,9 @@ var PDFDoc = (function PDFDocClosure() {
throw data.error; throw data.error;
}, this); }, this);
messageHandler.on('jpeg_decode', function(message) { messageHandler.on('jpeg_decode', function(data, promise) {
var imageData = message.data[0]; var imageData = data[0];
var components = message.data[1]; var components = data[1];
if (components != 3 && components != 1) if (components != 3 && components != 1)
error('Only 3 component or 1 component can be returned'); error('Only 3 component or 1 component can be returned');
@ -652,7 +647,7 @@ var PDFDoc = (function PDFDocClosure() {
buf[j] = data[i]; buf[j] = data[i];
} }
} }
message.reply({ data: buf, width: width, height: height}); promise.resolve({ data: buf, width: width, height: height});
}).bind(this); }).bind(this);
var src = 'data:image/jpeg;base64,' + window.btoa(imageData); var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
img.src = src; img.src = src;

View File

@ -2101,6 +2101,37 @@ var Font = (function FontClosure() {
return rule; return rule;
}, },
get spaceWidth() {
// trying to estimate space character width
var possibleSpaceReplacements = ['space', 'minus', 'one', 'i'];
var width;
for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
var glyphName = possibleSpaceReplacements[i];
// if possible, getting width by glyph name
if (glyphName in this.widths) {
width = this.widths[glyphName];
break;
}
var glyphUnicode = GlyphsUnicode[glyphName];
// finding the charcode via unicodeToCID map
var charcode = 0;
if (this.composite)
charcode = this.unicodeToCID[glyphUnicode];
// ... via toUnicode map
if (!charcode && 'toUnicode' in this)
charcode = this.toUnicode.indexOf(glyphUnicode);
// setting it to unicode if negative or undefined
if (!(charcode > 0))
charcode = glyphUnicode;
// trying to get width via charcode
width = this.widths[charcode];
if (width)
break; // the non-zero width found
}
width = (width || this.defaultWidth) * this.widthMultiplier;
return shadow(this, 'spaceWidth', width);
},
charToGlyph: function fonts_charToGlyph(charcode) { charToGlyph: function fonts_charToGlyph(charcode) {
var unicode, width, codeIRQueue; var unicode, width, codeIRQueue;

View File

@ -239,7 +239,6 @@ var PDFImage = (function PDFImageClosure() {
bits = remainingBits; bits = remainingBits;
} }
} }
if(decodeMap) console.timeEnd('getComps');
return output; return output;
}, },
getOpacity: function getOpacity() { getOpacity: function getOpacity() {

View File

@ -249,7 +249,7 @@ var Parser = (function ParserClosure() {
if (name == 'CCITTFaxDecode' || name == 'CCF') { if (name == 'CCITTFaxDecode' || name == 'CCF') {
return new CCITTFaxStream(stream, params); return new CCITTFaxStream(stream, params);
} }
TODO('filter "' + name + '" not supported yet'); warn('filter "' + name + '" not supported yet');
return stream; return stream;
} }
}; };

View File

@ -3,41 +3,6 @@
'use strict'; 'use strict';
/**
* A wrapper for data to facilitate adding functionality to messages.
*/
function Message(data) {
this.data = data;
this.allowsReply = false;
this.combObj;
this.id;
}
Message.prototype = {
/**
* Reply to the action handler that sent the message.
*/
reply: function messageReply(data) {
if (!this.allowsReply)
error('This message does not accept replies.');
this.combObj.postMessage({
isReply: true,
callbackId: this.id,
data: data
});
},
/**
* Setup the message to allow a reply.
* @param {Object} combObj The handler that has a postMessage function.
* @param {String} id The id to identify this message.
*/
setupReply: function setupReply(combObj, id) {
this.allowsReply = true;
this.combObj = combObj;
this.id = id;
}
};
function MessageHandler(name, comObj) { function MessageHandler(name, comObj) {
this.name = name; this.name = name;
this.comObj = comObj; this.comObj = comObj;
@ -65,11 +30,19 @@ function MessageHandler(name, comObj) {
} }
} else if (data.action in ah) { } else if (data.action in ah) {
var action = ah[data.action]; var action = ah[data.action];
var message = new Message(data.data); if (data.callbackId) {
if (data.callbackId) var promise = new Promise();
message.setupReply(comObj, data.callbackId); promise.then(function(resolvedData) {
comObj.postMessage({
action[0].call(action[1], message); isReply: true,
callbackId: data.callbackId,
data: resolvedData
});
});
action[0].call(action[1], data.data, promise);
} else {
action[0].call(action[1], data.data);
}
} else { } else {
throw 'Unkown action from worker: ' + data.action; throw 'Unkown action from worker: ' + data.action;
} }
@ -108,8 +81,7 @@ var WorkerMessageHandler = {
setup: function wphSetup(handler) { setup: function wphSetup(handler) {
var pdfDoc = null; var pdfDoc = null;
handler.on('test', function wphSetupTest(message) { handler.on('test', function wphSetupTest(data) {
var data = message.data;
handler.send('test', data instanceof Uint8Array); handler.send('test', data instanceof Uint8Array);
}); });
@ -120,15 +92,13 @@ var WorkerMessageHandler = {
// undefined action `workerSrc`. // undefined action `workerSrc`.
}); });
handler.on('doc', function wphSetupDoc(message) { handler.on('doc', function wphSetupDoc(data) {
var data = message.data;
// Create only the model of the PDFDoc, which is enough for // Create only the model of the PDFDoc, which is enough for
// processing the content of the pdf. // processing the content of the pdf.
pdfDoc = new PDFDocModel(new Stream(data)); pdfDoc = new PDFDocModel(new Stream(data));
}); });
handler.on('page_request', function wphSetupPageRequest(message) { handler.on('page_request', function wphSetupPageRequest(pageNum) {
var pageNum = message.data;
pageNum = parseInt(pageNum); pageNum = parseInt(pageNum);
@ -177,8 +147,7 @@ var WorkerMessageHandler = {
}); });
}, this); }, this);
handler.on('font', function wphSetupFont(message) { handler.on('font', function wphSetupFont(data) {
var data = message.data;
var objId = data[0]; var objId = data[0];
var name = data[1]; var name = data[1];
var file = data[2]; var file = data[2];

View File

@ -19,3 +19,4 @@
!issue840.pdf !issue840.pdf
!scan-bad.pdf !scan-bad.pdf
!freeculture.pdf !freeculture.pdf
!issue918.pdf

BIN
test/pdfs/issue918.pdf Normal file

Binary file not shown.

View File

@ -349,6 +349,12 @@
"pageLimit": 3, "pageLimit": 3,
"type": "eq" "type": "eq"
}, },
{ "id": "issue918",
"file": "pdfs/issue918.pdf",
"md5": "d582cc0f2592ae82936589ced2a47e55",
"rounds": 1,
"type": "eq"
},
{ "id": "aboutstacks", { "id": "aboutstacks",
"file": "pdfs/aboutstacks.pdf", "file": "pdfs/aboutstacks.pdf",
"md5": "6e7c8416a293ba2d83bc8dd20c6ccf51", "md5": "6e7c8416a293ba2d83bc8dd20c6ccf51",

View File

@ -537,7 +537,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
]; ];
if (scale && scale !== PDFView.currentScale) if (scale && scale !== PDFView.currentScale)
PDFView.setScale(scale, true); PDFView.parseScale(scale, true);
setTimeout(function pageViewScrollIntoViewRelayout() { setTimeout(function pageViewScrollIntoViewRelayout() {
// letting page to re-layout before scrolling // letting page to re-layout before scrolling