Merge branch 'master' of https://github.com/mozilla/pdf.js into amowarnings
This commit is contained in:
commit
b381c960d9
6
Makefile
6
Makefile
@ -3,6 +3,7 @@ BUILD_DIR := build
|
|||||||
BUILD_TARGET := $(BUILD_DIR)/pdf.js
|
BUILD_TARGET := $(BUILD_DIR)/pdf.js
|
||||||
DEFAULT_BROWSERS := resources/browser_manifests/browser_manifest.json
|
DEFAULT_BROWSERS := resources/browser_manifests/browser_manifest.json
|
||||||
DEFAULT_TESTS := test_manifest.json
|
DEFAULT_TESTS := test_manifest.json
|
||||||
|
DEFAULT_PYTHON := python2.7
|
||||||
|
|
||||||
EXTENSION_SRC := ./extensions/
|
EXTENSION_SRC := ./extensions/
|
||||||
EXTENSION_BASE_VERSION := 4bb289ec499013de66eb421737a4dbb4a9273eda
|
EXTENSION_BASE_VERSION := 4bb289ec499013de66eb421737a4dbb4a9273eda
|
||||||
@ -36,6 +37,7 @@ PDF_JS_FILES = \
|
|||||||
stream.js \
|
stream.js \
|
||||||
worker.js \
|
worker.js \
|
||||||
../external/jpgjs/jpg.js \
|
../external/jpgjs/jpg.js \
|
||||||
|
jpx.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# make server
|
# make server
|
||||||
@ -43,7 +45,7 @@ PDF_JS_FILES = \
|
|||||||
# This target starts a local web server at localhost:8888. This can be
|
# This target starts a local web server at localhost:8888. This can be
|
||||||
# used for testing all browsers.
|
# used for testing all browsers.
|
||||||
server:
|
server:
|
||||||
@cd test; python test.py --port=8888;
|
@cd test; $(DEFAULT_PYTHON) test.py --port=8888;
|
||||||
|
|
||||||
# make test
|
# make test
|
||||||
#
|
#
|
||||||
@ -106,7 +108,7 @@ browser-test:
|
|||||||
fi;
|
fi;
|
||||||
|
|
||||||
cd test; \
|
cd test; \
|
||||||
python test.py --reftest \
|
$(DEFAULT_PYTHON) test.py --reftest \
|
||||||
--browserManifestFile=$(PDF_BROWSERS) \
|
--browserManifestFile=$(PDF_BROWSERS) \
|
||||||
--manifestFile=$(PDF_TESTS)
|
--manifestFile=$(PDF_TESTS)
|
||||||
|
|
||||||
|
30
README.md
30
README.md
@ -1,9 +1,6 @@
|
|||||||
# pdf.js
|
# PDF.JS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
pdf.js is an HTML5 technology experiment that explores building a faithful
|
pdf.js is an HTML5 technology experiment that explores building a faithful
|
||||||
and efficient Portable Document Format (PDF) renderer without native code
|
and efficient Portable Document Format (PDF) renderer without native code
|
||||||
assistance.
|
assistance.
|
||||||
@ -14,9 +11,9 @@ rendering PDFs, and eventually release a PDF reader extension powered by
|
|||||||
pdf.js. Integration with Firefox is a possibility if the experiment proves
|
pdf.js. Integration with Firefox is a possibility if the experiment proves
|
||||||
successful.
|
successful.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Getting started
|
||||||
## Getting started
|
|
||||||
|
|
||||||
### Online demo
|
### Online demo
|
||||||
|
|
||||||
@ -29,11 +26,12 @@ using the pdf.js API.
|
|||||||
|
|
||||||
### Extension
|
### Extension
|
||||||
|
|
||||||
An up-to-date Firefox extension is also available:
|
A Firefox extension is also available:
|
||||||
|
|
||||||
+ http://mozilla.github.com/pdf.js/extensions/firefox/pdf.js.xpi
|
+ http://mozilla.github.com/pdf.js/extensions/firefox/pdf.js.xpi
|
||||||
|
|
||||||
(The above link is updated upon every merge to our master branch).
|
Note that this extension is self-updating, and by default Firefox will auto-update extensions on a
|
||||||
|
daily basis (you can change this through the `extensions.update.interval` option in `about:config`).
|
||||||
|
|
||||||
For an experimental Chrome extension, get the code as explained below and issue `make extension`.
|
For an experimental Chrome extension, get the code as explained below and issue `make extension`.
|
||||||
Then open Chrome with the flag `--enable-experimental-extension-apis`, go to `Tools > Extension`
|
Then open Chrome with the flag `--enable-experimental-extension-apis`, go to `Tools > Extension`
|
||||||
@ -68,12 +66,12 @@ In order to bundle all `src/` files into a final `pdf.js`, issue:
|
|||||||
This will generate the file `build/pdf.js` that can be included in your final project. (WARNING: That's a large file! Consider minifying it).
|
This will generate the file `build/pdf.js` that can be included in your final project. (WARNING: That's a large file! Consider minifying it).
|
||||||
|
|
||||||
|
|
||||||
## Learning
|
# Learning
|
||||||
|
|
||||||
Here are some initial pointers to help contributors get off the ground.
|
Here are some initial pointers to help contributors get off the ground.
|
||||||
Additional resources are available in a separate section below.
|
Additional resources are available in a separate section below.
|
||||||
|
|
||||||
#### Hello world
|
### Hello world
|
||||||
|
|
||||||
For a "hello world" example, take a look at:
|
For a "hello world" example, take a look at:
|
||||||
|
|
||||||
@ -82,7 +80,7 @@ For a "hello world" example, take a look at:
|
|||||||
This example illustrates the bare minimum ingredients for integrating pdf.js
|
This example illustrates the bare minimum ingredients for integrating pdf.js
|
||||||
in a custom project.
|
in a custom project.
|
||||||
|
|
||||||
#### Introductory video
|
### Introductory video
|
||||||
|
|
||||||
Check out the presentation by our contributor Julian Viereck on the inner
|
Check out the presentation by our contributor Julian Viereck on the inner
|
||||||
workings of PDF and pdf.js:
|
workings of PDF and pdf.js:
|
||||||
@ -92,7 +90,7 @@ workings of PDF and pdf.js:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
# Contributing
|
||||||
|
|
||||||
pdf.js is a community-driven project, so contributors are always welcome.
|
pdf.js is a community-driven project, so contributors are always welcome.
|
||||||
Simply fork our repo and contribute away. Good starting places for picking
|
Simply fork our repo and contribute away. Good starting places for picking
|
||||||
@ -122,7 +120,7 @@ You can add your name to it! :)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Running the tests
|
# Running the tests
|
||||||
|
|
||||||
pdf.js comes with browser-level regression tests that allow one to probe
|
pdf.js comes with browser-level regression tests that allow one to probe
|
||||||
whether it's able to successfully parse PDFs, as well as compare its output
|
whether it's able to successfully parse PDFs, as well as compare its output
|
||||||
@ -148,7 +146,7 @@ images. The test type `load` simply tests whether the file loads without
|
|||||||
raising any errors.
|
raising any errors.
|
||||||
|
|
||||||
|
|
||||||
## Running tests through our bot
|
### Running tests through our bot
|
||||||
|
|
||||||
If you are a reviewer, you can use our remote bot to issue comprehensive tests
|
If you are a reviewer, you can use our remote bot to issue comprehensive tests
|
||||||
against reference images before merging pull requests.
|
against reference images before merging pull requests.
|
||||||
@ -158,7 +156,7 @@ See the bot repo for details:
|
|||||||
+ https://github.com/mozilla/pdf.js-bot
|
+ https://github.com/mozilla/pdf.js-bot
|
||||||
|
|
||||||
|
|
||||||
## Additional resources
|
# Additional resources
|
||||||
|
|
||||||
Gallery of user projects and modifications:
|
Gallery of user projects and modifications:
|
||||||
|
|
||||||
@ -188,7 +186,7 @@ Follow us on twitter: @pdfjs
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## PDF-related resources
|
### PDF-related resources
|
||||||
|
|
||||||
A really basic overview of PDF is described here:
|
A really basic overview of PDF is described here:
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<script type="text/javascript" src="../../src/stream.js"></script>
|
<script type="text/javascript" src="../../src/stream.js"></script>
|
||||||
<script type="text/javascript" src="../../src/worker.js"></script>
|
<script type="text/javascript" src="../../src/worker.js"></script>
|
||||||
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
|
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
|
||||||
|
<script type="text/javascript" src="../../src/jpx.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Specify the main script used to create a new PDF.JS web worker.
|
// Specify the main script used to create a new PDF.JS web worker.
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<script type="text/javascript" src="../../src/stream.js"></script>
|
<script type="text/javascript" src="../../src/stream.js"></script>
|
||||||
<script type="text/javascript" src="../../src/worker.js"></script>
|
<script type="text/javascript" src="../../src/worker.js"></script>
|
||||||
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
|
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
|
||||||
|
<script type="text/javascript" src="../../src/jpx.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// Specify the main script used to create a new PDF.JS web worker.
|
// Specify the main script used to create a new PDF.JS web worker.
|
||||||
|
@ -48,6 +48,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
|
|||||||
// Note: fill alpha applies to all non-stroking operations
|
// Note: fill alpha applies to all non-stroking operations
|
||||||
this.fillAlpha = 1;
|
this.fillAlpha = 1;
|
||||||
this.strokeAlpha = 1;
|
this.strokeAlpha = 1;
|
||||||
|
this.lineWidth = 1;
|
||||||
|
|
||||||
this.old = old;
|
this.old = old;
|
||||||
}
|
}
|
||||||
@ -329,6 +330,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
|
|
||||||
// Graphics state
|
// Graphics state
|
||||||
setLineWidth: function canvasGraphicsSetLineWidth(width) {
|
setLineWidth: function canvasGraphicsSetLineWidth(width) {
|
||||||
|
this.current.lineWidth = width;
|
||||||
this.ctx.lineWidth = width;
|
this.ctx.lineWidth = width;
|
||||||
},
|
},
|
||||||
setLineCap: function canvasGraphicsSetLineCap(style) {
|
setLineCap: function canvasGraphicsSetLineCap(style) {
|
||||||
@ -442,6 +444,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
|
consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
|
||||||
var ctx = this.ctx;
|
var ctx = this.ctx;
|
||||||
var strokeColor = this.current.strokeColor;
|
var strokeColor = this.current.strokeColor;
|
||||||
|
if (this.current.lineWidth === 0)
|
||||||
|
ctx.lineWidth = this.getSinglePixelWidth();
|
||||||
// For stroke we want to temporarily change the global alpha to the
|
// For stroke we want to temporarily change the global alpha to the
|
||||||
// stroking alpha.
|
// stroking alpha.
|
||||||
ctx.globalAlpha = this.current.strokeAlpha;
|
ctx.globalAlpha = this.current.strokeAlpha;
|
||||||
@ -544,7 +548,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
var fontObj = this.objs.get(fontRefName).fontObj;
|
var fontObj = this.objs.get(fontRefName).fontObj;
|
||||||
|
|
||||||
if (!fontObj) {
|
if (!fontObj) {
|
||||||
throw 'Can\'t find font for ' + fontRefName;
|
error('Can\'t find font for ' + fontRefName);
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = fontObj.loadedName || 'sans-serif';
|
var name = fontObj.loadedName || 'sans-serif';
|
||||||
@ -640,7 +644,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
ctx.translate(current.x, current.y);
|
ctx.translate(current.x, current.y);
|
||||||
|
|
||||||
ctx.scale(textHScale, 1);
|
ctx.scale(textHScale, 1);
|
||||||
ctx.lineWidth /= current.textMatrix[0];
|
|
||||||
|
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
this.save();
|
this.save();
|
||||||
@ -677,7 +680,15 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
} else {
|
} else {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
this.applyTextTransforms();
|
this.applyTextTransforms();
|
||||||
ctx.lineWidth /= current.textMatrix[0] * fontMatrix[0];
|
|
||||||
|
var lineWidth = current.lineWidth;
|
||||||
|
var scale = Math.abs(current.textMatrix[0] * fontMatrix[0]);
|
||||||
|
if (scale == 0 || lineWidth == 0)
|
||||||
|
lineWidth = this.getSinglePixelWidth();
|
||||||
|
else
|
||||||
|
lineWidth /= scale;
|
||||||
|
|
||||||
|
ctx.lineWidth = lineWidth;
|
||||||
|
|
||||||
if (textSelection)
|
if (textSelection)
|
||||||
text.geom = this.getTextGeometry();
|
text.geom = this.getTextGeometry();
|
||||||
@ -855,7 +866,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
} else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
|
} else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
|
||||||
var pattern = Pattern.shadingFromIR(this.ctx, IR);
|
var pattern = Pattern.shadingFromIR(this.ctx, IR);
|
||||||
} else {
|
} else {
|
||||||
throw 'Unkown IR type';
|
error('Unkown IR type ' + IR[0]);
|
||||||
}
|
}
|
||||||
return pattern;
|
return pattern;
|
||||||
},
|
},
|
||||||
@ -1142,6 +1153,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
},
|
},
|
||||||
restoreFillRule: function canvasGraphicsRestoreFillRule(rule) {
|
restoreFillRule: function canvasGraphicsRestoreFillRule(rule) {
|
||||||
this.ctx.mozFillRule = rule;
|
this.ctx.mozFillRule = rule;
|
||||||
|
},
|
||||||
|
getSinglePixelWidth: function getSinglePixelWidth(scale) {
|
||||||
|
var inverse = this.ctx.mozCurrentTransformInverse;
|
||||||
|
return Math.abs(inverse[0] + inverse[2]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -369,55 +369,16 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() {
|
|||||||
DeviceCmykCS.prototype = {
|
DeviceCmykCS.prototype = {
|
||||||
getRgb: function cmykcs_getRgb(color) {
|
getRgb: function cmykcs_getRgb(color) {
|
||||||
var c = color[0], m = color[1], y = color[2], k = color[3];
|
var c = color[0], m = color[1], y = color[2], k = color[3];
|
||||||
var c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k;
|
|
||||||
|
|
||||||
var x, r, g, b;
|
// CMYK -> CMY: http://www.easyrgb.com/index.php?X=MATH&H=14#text14
|
||||||
// this is a matrix multiplication, unrolled for performance
|
c = (c * (1 - k) + k);
|
||||||
// code is taken from the poppler implementation
|
m = (m * (1 - k) + k);
|
||||||
x = c1 * m1 * y1 * k1; // 0 0 0 0
|
y = (y * (1 - k) + k);
|
||||||
r = g = b = x;
|
|
||||||
x = c1 * m1 * y1 * k; // 0 0 0 1
|
// CMY -> RGB: http://www.easyrgb.com/index.php?X=MATH&H=12#text12
|
||||||
r += 0.1373 * x;
|
var r = (1 - c);
|
||||||
g += 0.1216 * x;
|
var g = (1 - m);
|
||||||
b += 0.1255 * x;
|
var b = (1 - y);
|
||||||
x = c1 * m1 * y * k1; // 0 0 1 0
|
|
||||||
r += x;
|
|
||||||
g += 0.9490 * x;
|
|
||||||
x = c1 * m1 * y * k; // 0 0 1 1
|
|
||||||
r += 0.1098 * x;
|
|
||||||
g += 0.1020 * x;
|
|
||||||
x = c1 * m * y1 * k1; // 0 1 0 0
|
|
||||||
r += 0.9255 * x;
|
|
||||||
b += 0.5490 * x;
|
|
||||||
x = c1 * m * y1 * k; // 0 1 0 1
|
|
||||||
r += 0.1412 * x;
|
|
||||||
x = c1 * m * y * k1; // 0 1 1 0
|
|
||||||
r += 0.9294 * x;
|
|
||||||
g += 0.1098 * x;
|
|
||||||
b += 0.1412 * x;
|
|
||||||
x = c1 * m * y * k; // 0 1 1 1
|
|
||||||
r += 0.1333 * x;
|
|
||||||
x = c * m1 * y1 * k1; // 1 0 0 0
|
|
||||||
g += 0.6784 * x;
|
|
||||||
b += 0.9373 * x;
|
|
||||||
x = c * m1 * y1 * k; // 1 0 0 1
|
|
||||||
g += 0.0588 * x;
|
|
||||||
b += 0.1412 * x;
|
|
||||||
x = c * m1 * y * k1; // 1 0 1 0
|
|
||||||
g += 0.6510 * x;
|
|
||||||
b += 0.3137 * x;
|
|
||||||
x = c * m1 * y * k; // 1 0 1 1
|
|
||||||
g += 0.0745 * x;
|
|
||||||
x = c * m * y1 * k1; // 1 1 0 0
|
|
||||||
r += 0.1804 * x;
|
|
||||||
g += 0.1922 * x;
|
|
||||||
b += 0.5725 * x;
|
|
||||||
x = c * m * y1 * k; // 1 1 0 1
|
|
||||||
b += 0.0078 * x;
|
|
||||||
x = c * m * y * k1; // 1 1 1 0
|
|
||||||
r += 0.2118 * x;
|
|
||||||
g += 0.2119 * x;
|
|
||||||
b += 0.2235 * x;
|
|
||||||
|
|
||||||
return [r, g, b];
|
return [r, g, b];
|
||||||
},
|
},
|
||||||
|
10
src/core.js
10
src/core.js
@ -410,14 +410,14 @@ var Page = (function PageClosure() {
|
|||||||
if (callback)
|
if (callback)
|
||||||
callback(e);
|
callback(e);
|
||||||
else
|
else
|
||||||
throw e;
|
error(e);
|
||||||
}
|
}
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
function pageDisplayReadPromiseError(reason) {
|
function pageDisplayReadPromiseError(reason) {
|
||||||
if (callback)
|
if (callback)
|
||||||
callback(reason);
|
callback(reason);
|
||||||
else
|
else
|
||||||
throw reason;
|
error(reason);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -620,7 +620,7 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
|
if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
|
||||||
var workerSrc = PDFJS.workerSrc;
|
var workerSrc = PDFJS.workerSrc;
|
||||||
if (typeof workerSrc === 'undefined') {
|
if (typeof workerSrc === 'undefined') {
|
||||||
throw 'No PDFJS.workerSrc specified';
|
error('No PDFJS.workerSrc specified');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -728,7 +728,7 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw 'Got unkown object type ' + type;
|
error('Got unkown object type ' + type);
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
@ -749,7 +749,7 @@ var PDFDoc = (function PDFDocClosure() {
|
|||||||
if (page.displayReadyPromise)
|
if (page.displayReadyPromise)
|
||||||
page.displayReadyPromise.reject(data.error);
|
page.displayReadyPromise.reject(data.error);
|
||||||
else
|
else
|
||||||
throw data.error;
|
error(data.error);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
messageHandler.on('jpeg_decode', function(data, promise) {
|
messageHandler.on('jpeg_decode', function(data, promise) {
|
||||||
|
@ -481,8 +481,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
|
properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var flags = properties.flags;
|
||||||
var differences = [];
|
var differences = [];
|
||||||
var baseEncoding = Encodings.StandardEncoding;
|
var baseEncoding = !!(flags & FontFlags.Symbolic) ?
|
||||||
|
Encodings.symbolsEncoding : Encodings.StandardEncoding;
|
||||||
var hasEncoding = dict.has('Encoding');
|
var hasEncoding = dict.has('Encoding');
|
||||||
if (hasEncoding) {
|
if (hasEncoding) {
|
||||||
var encoding = xref.fetchIfRef(dict.get('Encoding'));
|
var encoding = xref.fetchIfRef(dict.get('Encoding'));
|
||||||
@ -761,8 +763,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
// Simulating descriptor flags attribute
|
// Simulating descriptor flags attribute
|
||||||
var fontNameWoStyle = baseFontName.split('-')[0];
|
var fontNameWoStyle = baseFontName.split('-')[0];
|
||||||
var flags = (serifFonts[fontNameWoStyle] ||
|
var flags = (serifFonts[fontNameWoStyle] ||
|
||||||
(fontNameWoStyle.search(/serif/gi) != -1) ? 2 : 0) |
|
(fontNameWoStyle.search(/serif/gi) != -1) ? FontFlags.Serif : 0) |
|
||||||
(symbolsFonts[fontNameWoStyle] ? 4 : 32);
|
(symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
|
||||||
|
FontFlags.Nonsymbolic);
|
||||||
|
|
||||||
var properties = {
|
var properties = {
|
||||||
type: type.name,
|
type: type.name,
|
||||||
|
82
src/fonts.js
82
src/fonts.js
@ -19,6 +19,18 @@ var kPDFGlyphSpaceUnits = 1000;
|
|||||||
// Until hinting is fully supported this constant can be used
|
// Until hinting is fully supported this constant can be used
|
||||||
var kHintingEnabled = false;
|
var kHintingEnabled = false;
|
||||||
|
|
||||||
|
var FontFlags = {
|
||||||
|
FixedPitch: 1,
|
||||||
|
Serif: 2,
|
||||||
|
Symbolic: 4,
|
||||||
|
Script: 8,
|
||||||
|
Nonsymbolic: 32,
|
||||||
|
Italic: 64,
|
||||||
|
AllCap: 65536,
|
||||||
|
SmallCap: 131072,
|
||||||
|
ForceBold: 262144
|
||||||
|
};
|
||||||
|
|
||||||
var Encodings = {
|
var Encodings = {
|
||||||
get ExpertEncoding() {
|
get ExpertEncoding() {
|
||||||
return shadow(this, 'ExpertEncoding', ['', '', '', '', '', '', '', '', '',
|
return shadow(this, 'ExpertEncoding', ['', '', '', '', '', '', '', '', '',
|
||||||
@ -160,19 +172,20 @@ var Encodings = {
|
|||||||
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
|
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
|
||||||
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||||
'braceleft', 'bar', 'braceright', 'asciitilde', '', '', 'exclamdown',
|
'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '',
|
||||||
'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
|
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||||
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
|
'', '', '', '', '', '', '', '', '', '', 'exclamdown', 'cent', 'sterling',
|
||||||
'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
|
'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',
|
||||||
'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
|
'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi',
|
||||||
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
|
'fl', '', 'endash', 'dagger', 'daggerdbl', 'periodcentered', '',
|
||||||
'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
|
'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright',
|
||||||
'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring',
|
'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '',
|
||||||
'cedilla', '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '',
|
'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent',
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '',
|
'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron',
|
||||||
'ordfeminine', '', '', '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine',
|
'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||||
'', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '', 'lslash',
|
'AE', '', 'ordfeminine', '', '', '', '', 'Lslash', 'Oslash', 'OE',
|
||||||
'oslash', 'oe', 'germandbls'
|
'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '',
|
||||||
|
'lslash', 'oslash', 'oe', 'germandbls'
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
get WinAnsiEncoding() {
|
get WinAnsiEncoding() {
|
||||||
@ -405,6 +418,19 @@ var symbolsFonts = {
|
|||||||
'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true
|
'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Some characters, e.g. copyrightserif, mapped to the private use area and
|
||||||
|
// might not be displayed using standard fonts. Mapping/hacking well-known chars
|
||||||
|
// to the similar equivalents in the normal characters range.
|
||||||
|
function mapPrivateUseChars(code) {
|
||||||
|
switch (code) {
|
||||||
|
case 0xF8E9: // copyrightsans
|
||||||
|
case 0xF6D9: // copyrightserif
|
||||||
|
return 0x00A9; // copyright
|
||||||
|
default:
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var FontLoader = {
|
var FontLoader = {
|
||||||
listeningForFontLoad: false,
|
listeningForFontLoad: false,
|
||||||
|
|
||||||
@ -761,8 +787,8 @@ var Font = (function FontClosure() {
|
|||||||
var names = name.split('+');
|
var names = name.split('+');
|
||||||
names = names.length > 1 ? names[1] : names[0];
|
names = names.length > 1 ? names[1] : names[0];
|
||||||
names = names.split(/[-,_]/g)[0];
|
names = names.split(/[-,_]/g)[0];
|
||||||
this.isSerifFont = !!(properties.flags & 2);
|
this.isSerifFont = !!(properties.flags & FontFlags.Serif);
|
||||||
this.isSymbolicFont = !!(properties.flags & 4);
|
this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
|
||||||
|
|
||||||
var type = properties.type;
|
var type = properties.type;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -2136,10 +2162,11 @@ var Font = (function FontClosure() {
|
|||||||
window.btoa(data) + ');');
|
window.btoa(data) + ');');
|
||||||
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}';
|
var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}';
|
||||||
|
|
||||||
|
var styleElement = document.createElement('style');
|
||||||
document.documentElement.getElementsByTagName('head')[0].appendChild(
|
document.documentElement.getElementsByTagName('head')[0].appendChild(
|
||||||
document.createElement('style'));
|
styleElement);
|
||||||
|
|
||||||
var styleSheet = document.styleSheets[document.styleSheets.length - 1];
|
var styleSheet = styleElement.sheet;
|
||||||
styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
styleSheet.insertRule(rule, styleSheet.cssRules.length);
|
||||||
|
|
||||||
return rule;
|
return rule;
|
||||||
@ -2185,7 +2212,7 @@ var Font = (function FontClosure() {
|
|||||||
case 'CIDFontType0':
|
case 'CIDFontType0':
|
||||||
if (this.noUnicodeAdaptation) {
|
if (this.noUnicodeAdaptation) {
|
||||||
width = this.widths[this.unicodeToCID[charcode] || charcode];
|
width = this.widths[this.unicodeToCID[charcode] || charcode];
|
||||||
unicode = charcode;
|
unicode = mapPrivateUseChars(charcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
unicode = this.toUnicode[charcode] || charcode;
|
unicode = this.toUnicode[charcode] || charcode;
|
||||||
@ -2193,7 +2220,7 @@ var Font = (function FontClosure() {
|
|||||||
case 'CIDFontType2':
|
case 'CIDFontType2':
|
||||||
if (this.noUnicodeAdaptation) {
|
if (this.noUnicodeAdaptation) {
|
||||||
width = this.widths[this.unicodeToCID[charcode] || charcode];
|
width = this.widths[this.unicodeToCID[charcode] || charcode];
|
||||||
unicode = charcode;
|
unicode = mapPrivateUseChars(charcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
unicode = this.toUnicode[charcode] || charcode;
|
unicode = this.toUnicode[charcode] || charcode;
|
||||||
@ -2203,7 +2230,7 @@ var Font = (function FontClosure() {
|
|||||||
if (!isNum(width))
|
if (!isNum(width))
|
||||||
width = this.widths[glyphName];
|
width = this.widths[glyphName];
|
||||||
if (this.noUnicodeAdaptation) {
|
if (this.noUnicodeAdaptation) {
|
||||||
unicode = GlyphsUnicode[glyphName] || charcode;
|
unicode = mapPrivateUseChars(GlyphsUnicode[glyphName] || charcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
unicode = this.glyphNameMap[glyphName] ||
|
unicode = this.glyphNameMap[glyphName] ||
|
||||||
@ -2234,9 +2261,8 @@ var Font = (function FontClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MacRoman encoding address by re-encoding the cmap table
|
// MacRoman encoding address by re-encoding the cmap table
|
||||||
unicode = glyphName in GlyphsUnicode ?
|
unicode = glyphName in this.glyphNameMap ?
|
||||||
GlyphsUnicode[glyphName] :
|
this.glyphNameMap[glyphName] : GlyphsUnicode[glyphName];
|
||||||
this.glyphNameMap[glyphName];
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warn('Unsupported font type: ' + this.type);
|
warn('Unsupported font type: ' + this.type);
|
||||||
@ -3339,15 +3365,9 @@ var Type2CFF = (function Type2CFFClosure() {
|
|||||||
inverseEncoding[encoding[charcode]] = charcode | 0;
|
inverseEncoding[encoding[charcode]] = charcode | 0;
|
||||||
for (var i = 0, ii = charsets.length; i < ii; i++) {
|
for (var i = 0, ii = charsets.length; i < ii; i++) {
|
||||||
var glyph = charsets[i];
|
var glyph = charsets[i];
|
||||||
if (glyph == '.notdef') {
|
if (glyph == '.notdef')
|
||||||
charstrings.push({
|
|
||||||
unicode: 0,
|
|
||||||
code: 0,
|
|
||||||
gid: i,
|
|
||||||
glyph: glyph
|
|
||||||
});
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
var code = inverseEncoding[i];
|
var code = inverseEncoding[i];
|
||||||
if (!code || isSpecialUnicode(code)) {
|
if (!code || isSpecialUnicode(code)) {
|
||||||
unassignedUnicodeItems.push(i);
|
unassignedUnicodeItems.push(i);
|
||||||
|
1854
src/jpx.js
Normal file
1854
src/jpx.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -574,7 +574,7 @@ var XRef = (function XRefClosure() {
|
|||||||
var stream, parser;
|
var stream, parser;
|
||||||
if (e.uncompressed) {
|
if (e.uncompressed) {
|
||||||
if (e.gen != gen)
|
if (e.gen != gen)
|
||||||
throw ('inconsistent generation in XRef');
|
error('inconsistent generation in XRef');
|
||||||
stream = this.stream.makeSubStream(e.offset);
|
stream = this.stream.makeSubStream(e.offset);
|
||||||
parser = new Parser(new Lexer(stream), true, this);
|
parser = new Parser(new Lexer(stream), true, this);
|
||||||
var obj1 = parser.getObj();
|
var obj1 = parser.getObj();
|
||||||
@ -703,7 +703,7 @@ var PDFObjects = (function PDFObjectsClosure() {
|
|||||||
// If there isn't an object yet or the object isn't resolved, then the
|
// If there isn't an object yet or the object isn't resolved, then the
|
||||||
// data isn't ready yet!
|
// data isn't ready yet!
|
||||||
if (!obj || !obj.isResolved) {
|
if (!obj || !obj.isResolved) {
|
||||||
throw 'Requesting object that isn\'t resolved yet ' + objId;
|
error('Requesting object that isn\'t resolved yet ' + objId);
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return obj.data;
|
return obj.data;
|
||||||
|
@ -240,6 +240,10 @@ var Parser = (function ParserClosure() {
|
|||||||
var bytes = stream.getBytes(length);
|
var bytes = stream.getBytes(length);
|
||||||
return new JpegStream(bytes, stream.dict, this.xref);
|
return new JpegStream(bytes, stream.dict, this.xref);
|
||||||
}
|
}
|
||||||
|
if (name == 'JPXDecode' || name == 'JPX') {
|
||||||
|
var bytes = stream.getBytes(length);
|
||||||
|
return new JpxStream(bytes, stream.dict);
|
||||||
|
}
|
||||||
if (name == 'ASCII85Decode' || name == 'A85') {
|
if (name == 'ASCII85Decode' || name == 'A85') {
|
||||||
return new Ascii85Stream(stream);
|
return new Ascii85Stream(stream);
|
||||||
}
|
}
|
||||||
@ -249,6 +253,9 @@ var Parser = (function ParserClosure() {
|
|||||||
if (name == 'CCITTFaxDecode' || name == 'CCF') {
|
if (name == 'CCITTFaxDecode' || name == 'CCF') {
|
||||||
return new CCITTFaxStream(stream, params);
|
return new CCITTFaxStream(stream, params);
|
||||||
}
|
}
|
||||||
|
if (name == 'RunLengthDecode') {
|
||||||
|
return new RunLengthStream(stream);
|
||||||
|
}
|
||||||
warn('filter "' + name + '" not supported yet');
|
warn('filter "' + name + '" not supported yet');
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
170
src/stream.js
170
src/stream.js
@ -821,21 +821,25 @@ var JpegStream = (function JpegStreamClosure() {
|
|||||||
JpegStream.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) {
|
JpegStream.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) {
|
||||||
if (this.bufferLength)
|
if (this.bufferLength)
|
||||||
return;
|
return;
|
||||||
var jpegImage = new JpegImage();
|
try {
|
||||||
if (this.colorTransform != -1)
|
var jpegImage = new JpegImage();
|
||||||
jpegImage.colorTransform = this.colorTransform;
|
if (this.colorTransform != -1)
|
||||||
jpegImage.parse(this.bytes);
|
jpegImage.colorTransform = this.colorTransform;
|
||||||
var width = jpegImage.width;
|
jpegImage.parse(this.bytes);
|
||||||
var height = jpegImage.height;
|
var width = jpegImage.width;
|
||||||
var data = jpegImage.getData(width, height);
|
var height = jpegImage.height;
|
||||||
this.buffer = data;
|
var data = jpegImage.getData(width, height);
|
||||||
this.bufferLength = data.length;
|
this.buffer = data;
|
||||||
|
this.bufferLength = data.length;
|
||||||
|
} catch (e) {
|
||||||
|
error('JPEG error: ' + e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
JpegStream.prototype.getIR = function jpegStreamGetIR() {
|
JpegStream.prototype.getIR = function jpegStreamGetIR() {
|
||||||
return bytesToString(this.bytes);
|
return bytesToString(this.bytes);
|
||||||
};
|
};
|
||||||
JpegStream.prototype.getChar = function jpegStreamGetChar() {
|
JpegStream.prototype.getChar = function jpegStreamGetChar() {
|
||||||
error('internal error: getChar is not valid on JpegStream');
|
error('internal error: getChar is not valid on JpegStream');
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Checks if the image can be decoded and displayed by the browser without any
|
* Checks if the image can be decoded and displayed by the browser without any
|
||||||
@ -869,6 +873,107 @@ var JpegStream = (function JpegStreamClosure() {
|
|||||||
return JpegStream;
|
return JpegStream;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For JPEG 2000's we use a library to decode these images and
|
||||||
|
* the stream behaves like all the other DecodeStreams.
|
||||||
|
*/
|
||||||
|
var JpxStream = (function JpxStreamClosure() {
|
||||||
|
function JpxStream(bytes, dict) {
|
||||||
|
this.dict = dict;
|
||||||
|
this.bytes = bytes;
|
||||||
|
|
||||||
|
DecodeStream.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
JpxStream.prototype = Object.create(DecodeStream.prototype);
|
||||||
|
|
||||||
|
JpxStream.prototype.ensureBuffer = function jpxStreamEnsureBuffer(req) {
|
||||||
|
if (this.bufferLength)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var jpxImage = new JpxImage();
|
||||||
|
jpxImage.parse(this.bytes);
|
||||||
|
|
||||||
|
var width = jpxImage.width;
|
||||||
|
var height = jpxImage.height;
|
||||||
|
var componentsCount = jpxImage.componentsCount;
|
||||||
|
if (componentsCount != 1 && componentsCount != 3 && componentsCount != 4)
|
||||||
|
error('JPX with ' + componentsCount + ' components is not supported');
|
||||||
|
|
||||||
|
var data = new Uint8Array(width * height * componentsCount);
|
||||||
|
|
||||||
|
for (var k = 0, kk = jpxImage.tiles.length; k < kk; k++) {
|
||||||
|
var tileCompoments = jpxImage.tiles[k];
|
||||||
|
var tileWidth = tileCompoments[0].width;
|
||||||
|
var tileHeight = tileCompoments[0].height;
|
||||||
|
var tileLeft = tileCompoments[0].left;
|
||||||
|
var tileTop = tileCompoments[0].top;
|
||||||
|
|
||||||
|
var dataPosition, sourcePosition, data0, data1, data2, data3, rowFeed;
|
||||||
|
switch (componentsCount) {
|
||||||
|
case 1:
|
||||||
|
data0 = tileCompoments[0].items;
|
||||||
|
|
||||||
|
dataPosition = width * tileTop + tileLeft;
|
||||||
|
rowFeed = width - tileWidth;
|
||||||
|
sourcePosition = 0;
|
||||||
|
for (var j = 0; j < tileHeight; j++) {
|
||||||
|
for (var i = 0; i < tileWidth; i++)
|
||||||
|
data[dataPosition++] = data0[sourcePosition++];
|
||||||
|
dataPosition += rowFeed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
data0 = tileCompoments[0].items;
|
||||||
|
data1 = tileCompoments[1].items;
|
||||||
|
data2 = tileCompoments[2].items;
|
||||||
|
|
||||||
|
dataPosition = (width * tileTop + tileLeft) * 3;
|
||||||
|
rowFeed = (width - tileWidth) * 3;
|
||||||
|
sourcePosition = 0;
|
||||||
|
for (var j = 0; j < tileHeight; j++) {
|
||||||
|
for (var i = 0; i < tileWidth; i++) {
|
||||||
|
data[dataPosition++] = data0[sourcePosition];
|
||||||
|
data[dataPosition++] = data1[sourcePosition];
|
||||||
|
data[dataPosition++] = data2[sourcePosition];
|
||||||
|
sourcePosition++;
|
||||||
|
}
|
||||||
|
dataPosition += rowFeed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
data0 = tileCompoments[0].items;
|
||||||
|
data1 = tileCompoments[1].items;
|
||||||
|
data2 = tileCompoments[2].items;
|
||||||
|
data3 = tileCompoments[3].items;
|
||||||
|
|
||||||
|
dataPosition = (width * tileTop + tileLeft) * 4;
|
||||||
|
rowFeed = (width - tileWidth) * 4;
|
||||||
|
sourcePosition = 0;
|
||||||
|
for (var j = 0; j < tileHeight; j++) {
|
||||||
|
for (var i = 0; i < tileWidth; i++) {
|
||||||
|
data[dataPosition++] = data0[sourcePosition];
|
||||||
|
data[dataPosition++] = data1[sourcePosition];
|
||||||
|
data[dataPosition++] = data2[sourcePosition];
|
||||||
|
data[dataPosition++] = data3[sourcePosition];
|
||||||
|
sourcePosition++;
|
||||||
|
}
|
||||||
|
dataPosition += rowFeed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.buffer = data;
|
||||||
|
this.bufferLength = data.length;
|
||||||
|
};
|
||||||
|
JpxStream.prototype.getChar = function jpxStreamGetChar() {
|
||||||
|
error('internal error: getChar is not valid on JpxStream');
|
||||||
|
};
|
||||||
|
|
||||||
|
return JpxStream;
|
||||||
|
})();
|
||||||
|
|
||||||
var DecryptStream = (function DecryptStreamClosure() {
|
var DecryptStream = (function DecryptStreamClosure() {
|
||||||
function DecryptStream(str, decrypt) {
|
function DecryptStream(str, decrypt) {
|
||||||
this.str = str;
|
this.str = str;
|
||||||
@ -1041,6 +1146,51 @@ var AsciiHexStream = (function AsciiHexStreamClosure() {
|
|||||||
return AsciiHexStream;
|
return AsciiHexStream;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
var RunLengthStream = (function RunLengthStreamClosure() {
|
||||||
|
function RunLengthStream(str) {
|
||||||
|
this.str = str;
|
||||||
|
this.dict = str.dict;
|
||||||
|
|
||||||
|
DecodeStream.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunLengthStream.prototype = Object.create(DecodeStream.prototype);
|
||||||
|
|
||||||
|
RunLengthStream.prototype.readBlock = function runLengthStreamReadBlock() {
|
||||||
|
// The repeatHeader has following format. The first byte defines type of run
|
||||||
|
// and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes
|
||||||
|
// (in addition to the second byte from the header), n = 129 through 255 -
|
||||||
|
// duplicate the second byte from the header (257 - n) times, n = 128 - end.
|
||||||
|
var repeatHeader = this.str.getBytes(2);
|
||||||
|
if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] == 128) {
|
||||||
|
this.eof = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bufferLength = this.bufferLength;
|
||||||
|
var n = repeatHeader[0];
|
||||||
|
if (n < 128) {
|
||||||
|
// copy n bytes
|
||||||
|
var buffer = this.ensureBuffer(bufferLength + n + 1);
|
||||||
|
buffer[bufferLength++] = repeatHeader[1];
|
||||||
|
if (n > 0) {
|
||||||
|
var source = this.str.getBytes(n);
|
||||||
|
buffer.set(source, bufferLength);
|
||||||
|
bufferLength += n;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
n = 257 - n;
|
||||||
|
var b = repeatHeader[1];
|
||||||
|
var buffer = this.ensureBuffer(bufferLength + n + 1);
|
||||||
|
for (var i = 0; i < n; i++)
|
||||||
|
buffer[bufferLength++] = b;
|
||||||
|
}
|
||||||
|
this.bufferLength = bufferLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
return RunLengthStream;
|
||||||
|
})();
|
||||||
|
|
||||||
var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
||||||
|
|
||||||
var ccittEOL = -2;
|
var ccittEOL = -2;
|
||||||
|
16
src/util.js
16
src/util.js
@ -255,8 +255,8 @@ var Promise = (function PromiseClosure() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this._data !== EMPTY_PROMISE) {
|
if (this._data !== EMPTY_PROMISE) {
|
||||||
throw 'Promise ' + this.name +
|
error('Promise ' + this.name +
|
||||||
': Cannot set the data of a promise twice';
|
': Cannot set the data of a promise twice');
|
||||||
}
|
}
|
||||||
this._data = value;
|
this._data = value;
|
||||||
this.hasData = true;
|
this.hasData = true;
|
||||||
@ -268,7 +268,7 @@ var Promise = (function PromiseClosure() {
|
|||||||
|
|
||||||
get data() {
|
get data() {
|
||||||
if (this._data === EMPTY_PROMISE) {
|
if (this._data === EMPTY_PROMISE) {
|
||||||
throw 'Promise ' + this.name + ': Cannot get data that isn\'t set';
|
error('Promise ' + this.name + ': Cannot get data that isn\'t set');
|
||||||
}
|
}
|
||||||
return this._data;
|
return this._data;
|
||||||
},
|
},
|
||||||
@ -283,10 +283,10 @@ var Promise = (function PromiseClosure() {
|
|||||||
|
|
||||||
resolve: function promiseResolve(data) {
|
resolve: function promiseResolve(data) {
|
||||||
if (this.isResolved) {
|
if (this.isResolved) {
|
||||||
throw 'A Promise can be resolved only once ' + this.name;
|
error('A Promise can be resolved only once ' + this.name);
|
||||||
}
|
}
|
||||||
if (this.isRejected) {
|
if (this.isRejected) {
|
||||||
throw 'The Promise was already rejected ' + this.name;
|
error('The Promise was already rejected ' + this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isResolved = true;
|
this.isResolved = true;
|
||||||
@ -300,10 +300,10 @@ var Promise = (function PromiseClosure() {
|
|||||||
|
|
||||||
reject: function proimseReject(reason) {
|
reject: function proimseReject(reason) {
|
||||||
if (this.isRejected) {
|
if (this.isRejected) {
|
||||||
throw 'A Promise can be rejected only once ' + this.name;
|
error('A Promise can be rejected only once ' + this.name);
|
||||||
}
|
}
|
||||||
if (this.isResolved) {
|
if (this.isResolved) {
|
||||||
throw 'The Promise was already resolved ' + this.name;
|
error('The Promise was already resolved ' + this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isRejected = true;
|
this.isRejected = true;
|
||||||
@ -317,7 +317,7 @@ var Promise = (function PromiseClosure() {
|
|||||||
|
|
||||||
then: function promiseThen(callback, errback) {
|
then: function promiseThen(callback, errback) {
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
throw 'Requiring callback' + this.name;
|
error('Requiring callback' + this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the promise is already resolved, call the callback directly.
|
// If the promise is already resolved, call the callback directly.
|
||||||
|
@ -26,7 +26,7 @@ function MessageHandler(name, comObj) {
|
|||||||
delete callbacks[callbackId];
|
delete callbacks[callbackId];
|
||||||
callback(data.data);
|
callback(data.data);
|
||||||
} else {
|
} else {
|
||||||
throw 'Cannot resolve callback ' + callbackId;
|
error('Cannot resolve callback ' + callbackId);
|
||||||
}
|
}
|
||||||
} else if (data.action in ah) {
|
} else if (data.action in ah) {
|
||||||
var action = ah[data.action];
|
var action = ah[data.action];
|
||||||
@ -44,7 +44,7 @@ function MessageHandler(name, comObj) {
|
|||||||
action[0].call(action[1], data.data);
|
action[0].call(action[1], data.data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw 'Unkown action from worker: ' + data.action;
|
error('Unkown action from worker: ' + data.action);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ MessageHandler.prototype = {
|
|||||||
on: function messageHandlerOn(actionName, handler, scope) {
|
on: function messageHandlerOn(actionName, handler, scope) {
|
||||||
var ah = this.actionHandler;
|
var ah = this.actionHandler;
|
||||||
if (ah[actionName]) {
|
if (ah[actionName]) {
|
||||||
throw 'There is already an actionName called "' + actionName + '"';
|
error('There is already an actionName called "' + actionName + '"');
|
||||||
}
|
}
|
||||||
ah[actionName] = [handler, scope];
|
ah[actionName] = [handler, scope];
|
||||||
},
|
},
|
||||||
@ -208,6 +208,7 @@ var workerConsole = {
|
|||||||
action: 'console_error',
|
action: 'console_error',
|
||||||
data: args
|
data: args
|
||||||
});
|
});
|
||||||
|
throw 'pdf.js execution error';
|
||||||
},
|
},
|
||||||
|
|
||||||
time: function time(name) {
|
time: function time(name) {
|
||||||
@ -217,7 +218,7 @@ var workerConsole = {
|
|||||||
timeEnd: function timeEnd(name) {
|
timeEnd: function timeEnd(name) {
|
||||||
var time = consoleTimer[name];
|
var time = consoleTimer[name];
|
||||||
if (time == null) {
|
if (time == null) {
|
||||||
throw 'Unkown timer name ' + name;
|
error('Unkown timer name ' + name);
|
||||||
}
|
}
|
||||||
this.log('Timer:', name, Date.now() - time);
|
this.log('Timer:', name, Date.now() - time);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ var files = [
|
|||||||
'pattern.js',
|
'pattern.js',
|
||||||
'stream.js',
|
'stream.js',
|
||||||
'worker.js',
|
'worker.js',
|
||||||
'../external/jpgjs/jpg.js'
|
'../external/jpgjs/jpg.js',
|
||||||
|
'jpx.js'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Load all the files.
|
// Load all the files.
|
||||||
|
3
test/.gitignore
vendored
3
test/.gitignore
vendored
@ -0,0 +1,3 @@
|
|||||||
|
ref/
|
||||||
|
tmp/
|
||||||
|
|
2
test/pdfs/.gitignore
vendored
2
test/pdfs/.gitignore
vendored
@ -22,3 +22,5 @@
|
|||||||
!issue918.pdf
|
!issue918.pdf
|
||||||
!smaskdim.pdf
|
!smaskdim.pdf
|
||||||
!type4psfunc.pdf
|
!type4psfunc.pdf
|
||||||
|
!S2.pdf
|
||||||
|
!zerowidthline.pdf
|
||||||
|
2549
test/pdfs/S2.pdf
Normal file
2549
test/pdfs/S2.pdf
Normal file
File diff suppressed because one or more lines are too long
1
test/pdfs/issue1096.pdf.link
Normal file
1
test/pdfs/issue1096.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://www.faithaliveresources.org/Content/Site135/FilesSamples/105315400440pdf_00000009843.pdf
|
1
test/pdfs/issue1127.pdf.link
Normal file
1
test/pdfs/issue1127.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://vmp.ethz.ch/pdfs/diplome/vordiplome/Block%201/Algorithmen_%26_Komplexitaet/AlgoKo_f08_Aufg.pdf
|
BIN
test/pdfs/zerowidthline.pdf
Normal file
BIN
test/pdfs/zerowidthline.pdf
Normal file
Binary file not shown.
@ -9,7 +9,7 @@ USAGE_EXAMPLE = "%prog"
|
|||||||
# The local web server uses the git repo as the document root.
|
# The local web server uses the git repo as the document root.
|
||||||
DOC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
|
DOC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
|
||||||
|
|
||||||
ANAL = True
|
GIT_CLONE_CHECK = True
|
||||||
DEFAULT_MANIFEST_FILE = 'test_manifest.json'
|
DEFAULT_MANIFEST_FILE = 'test_manifest.json'
|
||||||
EQLOG_FILE = 'eq.log'
|
EQLOG_FILE = 'eq.log'
|
||||||
BROWSERLOG_FILE = 'browser.log'
|
BROWSERLOG_FILE = 'browser.log'
|
||||||
@ -344,7 +344,7 @@ def verifyPDFs(manifestList):
|
|||||||
|
|
||||||
def setUp(options):
|
def setUp(options):
|
||||||
# Only serve files from a pdf.js clone
|
# Only serve files from a pdf.js clone
|
||||||
assert not ANAL or os.path.isfile('../src/pdf.js') and os.path.isdir('../.git')
|
assert not GIT_CLONE_CHECK or os.path.isfile('../src/pdf.js') and os.path.isdir('../.git')
|
||||||
|
|
||||||
if options.masterMode and os.path.isdir(TMPDIR):
|
if options.masterMode and os.path.isdir(TMPDIR):
|
||||||
print 'Temporary snapshot dir tmp/ is still around.'
|
print 'Temporary snapshot dir tmp/ is still around.'
|
||||||
|
@ -176,7 +176,6 @@
|
|||||||
"md5": "eb7b224107205db4fea9f7df0185f77d",
|
"md5": "eb7b224107205db4fea9f7df0185f77d",
|
||||||
"link": true,
|
"link": true,
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"skipPages": [12,31],
|
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
{ "id": "fips197",
|
{ "id": "fips197",
|
||||||
@ -403,6 +402,21 @@
|
|||||||
"link": true,
|
"link": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "issue1096",
|
||||||
|
"file": "pdfs/issue1096.pdf",
|
||||||
|
"md5": "7f75d2b4b93c78d401ff39e8c1b00612",
|
||||||
|
"rounds": 1,
|
||||||
|
"pageLimit": 10,
|
||||||
|
"link": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "issue1127",
|
||||||
|
"file": "pdfs/issue1127.pdf",
|
||||||
|
"md5": "4fb2be5ffefeafda4ba977de2a1bb4d8",
|
||||||
|
"rounds": 1,
|
||||||
|
"link": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "liveprogramming",
|
{ "id": "liveprogramming",
|
||||||
"file": "pdfs/liveprogramming.pdf",
|
"file": "pdfs/liveprogramming.pdf",
|
||||||
"md5": "7bd4dad1188232ef597d36fd72c33e52",
|
"md5": "7bd4dad1188232ef597d36fd72c33e52",
|
||||||
@ -411,11 +425,24 @@
|
|||||||
"link": true,
|
"link": true,
|
||||||
"type": "load"
|
"type": "load"
|
||||||
},
|
},
|
||||||
|
{ "id": "S2-eq",
|
||||||
|
"file": "pdfs/S2.pdf",
|
||||||
|
"md5": "d0b6137846df6e0fe058f234a87fb588",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue1055",
|
{ "id": "issue1055",
|
||||||
"file": "pdfs/issue1055.pdf",
|
"file": "pdfs/issue1055.pdf",
|
||||||
"md5": "3ba56c2e48dce81da8669b1b9cf98ff0",
|
"md5": "3ba56c2e48dce81da8669b1b9cf98ff0",
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"link": true,
|
"link": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "zerowidthline",
|
||||||
|
"file": "pdfs/zerowidthline.pdf",
|
||||||
|
"md5": "295d26e61a85635433f8e4b768953f60",
|
||||||
|
"rounds": 1,
|
||||||
|
"link": false,
|
||||||
|
"type": "eq"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
<script type="text/javascript" src="/src/stream.js"></script>
|
<script type="text/javascript" src="/src/stream.js"></script>
|
||||||
<script type="text/javascript" src="/src/worker.js"></script>
|
<script type="text/javascript" src="/src/worker.js"></script>
|
||||||
<script type="text/javascript" src="/external/jpgjs/jpg.js"></script>
|
<script type="text/javascript" src="/external/jpgjs/jpg.js"></script>
|
||||||
|
<script type="text/javascript" src="/src/jpx.js"></script>
|
||||||
<script type="text/javascript" src="driver.js"></script>
|
<script type="text/javascript" src="driver.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -224,3 +224,10 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// Check console compatability
|
||||||
|
(function checkConsoleCompatibility() {
|
||||||
|
if (typeof console == 'undefined') {
|
||||||
|
console = {log: function() {}};
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
<script type="text/javascript" src="../src/stream.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
<script type="text/javascript" src="../src/stream.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
||||||
<script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
<script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
||||||
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
||||||
|
<script type="text/javascript" src="../src/jpx.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
|
||||||
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE -->
|
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE -->
|
||||||
<script type="text/javascript" src="viewer.js"></script>
|
<script type="text/javascript" src="viewer.js"></script>
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
var kDefaultURL = 'compressed.tracemonkey-pldi-09.pdf';
|
var kDefaultURL = 'compressed.tracemonkey-pldi-09.pdf';
|
||||||
var kDefaultScale = 'auto';
|
var kDefaultScale = 'auto';
|
||||||
var kDefaultScaleDelta = 1.1;
|
var kDefaultScaleDelta = 1.1;
|
||||||
|
var kUnknownScale = 0;
|
||||||
var kCacheSize = 20;
|
var kCacheSize = 20;
|
||||||
var kCssUnits = 96.0 / 72.0;
|
var kCssUnits = 96.0 / 72.0;
|
||||||
var kScrollbarPadding = 40;
|
var kScrollbarPadding = 40;
|
||||||
@ -157,7 +158,7 @@ var currentPageNumber = 1;
|
|||||||
var PDFView = {
|
var PDFView = {
|
||||||
pages: [],
|
pages: [],
|
||||||
thumbnails: [],
|
thumbnails: [],
|
||||||
currentScale: 0,
|
currentScale: kUnknownScale,
|
||||||
currentScaleValue: null,
|
currentScaleValue: null,
|
||||||
initialBookmark: document.location.hash.substring(1),
|
initialBookmark: document.location.hash.substring(1),
|
||||||
|
|
||||||
@ -212,12 +213,12 @@ var PDFView = {
|
|||||||
|
|
||||||
zoomIn: function pdfViewZoomIn() {
|
zoomIn: function pdfViewZoomIn() {
|
||||||
var newScale = Math.min(kMaxScale, this.currentScale * kDefaultScaleDelta);
|
var newScale = Math.min(kMaxScale, this.currentScale * kDefaultScaleDelta);
|
||||||
this.setScale(newScale, true);
|
this.parseScale(newScale, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomOut: function pdfViewZoomOut() {
|
zoomOut: function pdfViewZoomOut() {
|
||||||
var newScale = Math.max(kMinScale, this.currentScale / kDefaultScaleDelta);
|
var newScale = Math.max(kMinScale, this.currentScale / kDefaultScaleDelta);
|
||||||
this.setScale(newScale, true);
|
this.parseScale(newScale, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
set page(val) {
|
set page(val) {
|
||||||
@ -478,10 +479,16 @@ var PDFView = {
|
|||||||
}
|
}
|
||||||
else if (storedHash)
|
else if (storedHash)
|
||||||
this.setHash(storedHash);
|
this.setHash(storedHash);
|
||||||
else {
|
else if (scale) {
|
||||||
this.parseScale(scale || kDefaultScale, true);
|
this.parseScale(scale, true);
|
||||||
this.page = 1;
|
this.page = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PDFView.currentScale === kUnknownScale) {
|
||||||
|
// Scale was not initialized: invalid bookmark or scale was not specified.
|
||||||
|
// Setting the default one.
|
||||||
|
this.parseScale(kDefaultScale, true);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setHash: function pdfViewSetHash(hash) {
|
setHash: function pdfViewSetHash(hash) {
|
||||||
@ -776,6 +783,8 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
|
|||||||
|
|
||||||
if (scale && scale !== PDFView.currentScale)
|
if (scale && scale !== PDFView.currentScale)
|
||||||
PDFView.parseScale(scale, true);
|
PDFView.parseScale(scale, true);
|
||||||
|
else if (PDFView.currentScale === kUnknownScale)
|
||||||
|
PDFView.parseScale(kDefaultScale, true);
|
||||||
|
|
||||||
setTimeout(function pageViewScrollIntoViewRelayout() {
|
setTimeout(function pageViewScrollIntoViewRelayout() {
|
||||||
// letting page to re-layout before scrolling
|
// letting page to re-layout before scrolling
|
||||||
@ -994,22 +1003,55 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var textDivs = this.textDivs;
|
var textDivs = this.textDivs;
|
||||||
var textLayerDiv = this.textLayerDiv;
|
var textLayerDiv = this.textLayerDiv;
|
||||||
this.textLayerTimer = setInterval(function renderTextLayer() {
|
var renderTimer = null;
|
||||||
|
var renderingDone = false;
|
||||||
|
var renderInterval = 0;
|
||||||
|
var resumeInterval = 500; // in ms
|
||||||
|
|
||||||
|
// Render the text layer, one div at a time
|
||||||
|
function renderTextLayer() {
|
||||||
if (textDivs.length === 0) {
|
if (textDivs.length === 0) {
|
||||||
clearInterval(self.textLayerTimer);
|
clearInterval(renderTimer);
|
||||||
|
renderingDone = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var textDiv = textDivs.shift();
|
var textDiv = textDivs.shift();
|
||||||
if (textDiv.dataset.textLength >= 1) { // avoid div by zero
|
if (textDiv.dataset.textLength > 0) {
|
||||||
textLayerDiv.appendChild(textDiv);
|
textLayerDiv.appendChild(textDiv);
|
||||||
// Adjust div width (via letterSpacing) to match canvas text
|
|
||||||
// Due to the .offsetWidth calls, this is slow
|
if (textDiv.dataset.textLength > 1) { // avoid div by zero
|
||||||
textDiv.style.letterSpacing =
|
// Adjust div width (via letterSpacing) to match canvas text
|
||||||
((textDiv.dataset.canvasWidth - textDiv.offsetWidth) /
|
// Due to the .offsetWidth calls, this is slow
|
||||||
(textDiv.dataset.textLength - 1)) + 'px';
|
// This needs to come after appending to the DOM
|
||||||
|
textDiv.style.letterSpacing =
|
||||||
|
((textDiv.dataset.canvasWidth - textDiv.offsetWidth) /
|
||||||
|
(textDiv.dataset.textLength - 1)) + 'px';
|
||||||
|
}
|
||||||
|
} // textLength > 0
|
||||||
|
}
|
||||||
|
renderTimer = setInterval(renderTextLayer, renderInterval);
|
||||||
|
|
||||||
|
// Stop rendering when user scrolls. Resume after XXX milliseconds
|
||||||
|
// of no scroll events
|
||||||
|
var scrollTimer = null;
|
||||||
|
function textLayerOnScroll() {
|
||||||
|
if (renderingDone) {
|
||||||
|
window.removeEventListener('scroll', textLayerOnScroll, false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}, 0);
|
|
||||||
};
|
// Immediately pause rendering
|
||||||
|
clearInterval(renderTimer);
|
||||||
|
|
||||||
|
clearTimeout(scrollTimer);
|
||||||
|
scrollTimer = setTimeout(function textLayerScrollTimer() {
|
||||||
|
// Resume rendering
|
||||||
|
renderTimer = setInterval(renderTextLayer, renderInterval);
|
||||||
|
}, resumeInterval);
|
||||||
|
}; // textLayerOnScroll
|
||||||
|
|
||||||
|
window.addEventListener('scroll', textLayerOnScroll, false);
|
||||||
|
}; // endLayout
|
||||||
|
|
||||||
this.appendText = function textLayerBuilderAppendText(text,
|
this.appendText = function textLayerBuilderAppendText(text,
|
||||||
fontName, fontSize) {
|
fontName, fontSize) {
|
||||||
@ -1274,7 +1316,7 @@ window.addEventListener('keydown', function keydown(evt) {
|
|||||||
handled = true;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
case 48: // '0'
|
case 48: // '0'
|
||||||
PDFView.setScale(kDefaultScale, true);
|
PDFView.parseScale(kDefaultScale, true);
|
||||||
handled = true;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
case 37: // left arrow
|
case 37: // left arrow
|
||||||
|
Loading…
x
Reference in New Issue
Block a user