Split files into worker and main thread pieces.

This commit is contained in:
Brendan Dahl 2013-08-12 10:48:06 -07:00
parent e5cd027dce
commit 5ecce4996b
41 changed files with 817 additions and 786 deletions

View File

@ -4,32 +4,16 @@
<head>
<!-- In production, only one script (pdf.js) is necessary -->
<!-- In production, change the content of PDFJS.workerSrc below -->
<script type="text/javascript" src="../../src/network.js"></script>
<script type="text/javascript" src="../../src/chunked_stream.js"></script>
<script type="text/javascript" src="../../src/pdf_manager.js"></script>
<script type="text/javascript" src="../../src/core.js"></script>
<script type="text/javascript" src="../../src/util.js"></script>
<script type="text/javascript" src="../../src/api.js"></script>
<script type="text/javascript" src="../../src/canvas.js"></script>
<script type="text/javascript" src="../../src/obj.js"></script>
<script type="text/javascript" src="../../src/annotation.js"></script>
<script type="text/javascript" src="../../src/function.js"></script>
<script type="text/javascript" src="../../src/charsets.js"></script>
<script type="text/javascript" src="../../src/cidmaps.js"></script>
<script type="text/javascript" src="../../src/colorspace.js"></script>
<script type="text/javascript" src="../../src/crypto.js"></script>
<script type="text/javascript" src="../../src/evaluator.js"></script>
<script type="text/javascript" src="../../src/fonts.js"></script>
<script type="text/javascript" src="../../src/glyphlist.js"></script>
<script type="text/javascript" src="../../src/image.js"></script>
<script type="text/javascript" src="../../src/metrics.js"></script>
<script type="text/javascript" src="../../src/parser.js"></script>
<script type="text/javascript" src="../../src/pattern.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="../../external/jpgjs/jpg.js"></script>
<script type="text/javascript" src="../../src/jpx.js"></script>
<script type="text/javascript" src="../../src/jbig2.js"></script>
<script type="text/javascript" src="../../src/shared/util.js"></script>
<script type="text/javascript" src="../../src/shared/colorspace.js"></script>
<script type="text/javascript" src="../../src/shared/pattern.js"></script>
<script type="text/javascript" src="../../src/shared/function.js"></script>
<script type="text/javascript" src="../../src/shared/annotation.js"></script>
<script type="text/javascript" src="../../src/display/api.js"></script>
<script type="text/javascript" src="../../src/display/metadata.js"></script>
<script type="text/javascript" src="../../src/display/canvas.js"></script>
<script type="text/javascript" src="../../src/display/font_loader.js"></script>
<script type="text/javascript" src="../../src/display/font_renderer.js"></script>
<script type="text/javascript">
// Specify the main script used to create a new PDF.JS web worker.

View File

@ -4,32 +4,16 @@
<head>
<!-- In production, only one script (pdf.js) is necessary -->
<!-- In production, change the content of PDFJS.workerSrc below -->
<script type="text/javascript" src="../../src/network.js"></script>
<script type="text/javascript" src="../../src/chunked_stream.js"></script>
<script type="text/javascript" src="../../src/pdf_manager.js"></script>
<script type="text/javascript" src="../../src/core.js"></script>
<script type="text/javascript" src="../../src/util.js"></script>
<script type="text/javascript" src="../../src/api.js"></script>
<script type="text/javascript" src="../../src/canvas.js"></script>
<script type="text/javascript" src="../../src/obj.js"></script>
<script type="text/javascript" src="../../src/annotation.js"></script>
<script type="text/javascript" src="../../src/function.js"></script>
<script type="text/javascript" src="../../src/charsets.js"></script>
<script type="text/javascript" src="../../src/cidmaps.js"></script>
<script type="text/javascript" src="../../src/colorspace.js"></script>
<script type="text/javascript" src="../../src/crypto.js"></script>
<script type="text/javascript" src="../../src/evaluator.js"></script>
<script type="text/javascript" src="../../src/fonts.js"></script>
<script type="text/javascript" src="../../src/glyphlist.js"></script>
<script type="text/javascript" src="../../src/image.js"></script>
<script type="text/javascript" src="../../src/metrics.js"></script>
<script type="text/javascript" src="../../src/parser.js"></script>
<script type="text/javascript" src="../../src/pattern.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="../../external/jpgjs/jpg.js"></script>
<script type="text/javascript" src="../../src/jpx.js"></script>
<script type="text/javascript" src="../../src/jbig2.js"></script>
<script type="text/javascript" src="../../src/shared/util.js"></script>
<script type="text/javascript" src="../../src/shared/colorspace.js"></script>
<script type="text/javascript" src="../../src/shared/pattern.js"></script>
<script type="text/javascript" src="../../src/shared/function.js"></script>
<script type="text/javascript" src="../../src/shared/annotation.js"></script>
<script type="text/javascript" src="../../src/display/api.js"></script>
<script type="text/javascript" src="../../src/display/metadata.js"></script>
<script type="text/javascript" src="../../src/display/canvas.js"></script>
<script type="text/javascript" src="../../src/display/font_loader.js"></script>
<script type="text/javascript" src="../../src/display/font_renderer.js"></script>
<script type="text/javascript">
// Specify the main script used to create a new PDF.JS web worker.

155
make.js
View File

@ -29,6 +29,8 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root
BUILD_DIR = 'build/',
SRC_DIR = 'src/',
BUILD_TARGET = BUILD_DIR + 'pdf.js',
BUILD_WORKER_TARGET = BUILD_DIR + 'pdf.worker.js',
BUILD_TARGETS = [BUILD_TARGET, BUILD_WORKER_TARGET],
FIREFOX_BUILD_DIR = BUILD_DIR + '/firefox/',
CHROME_BUILD_DIR = BUILD_DIR + '/chrome/',
EXTENSION_SRC_DIR = 'extensions/',
@ -107,7 +109,7 @@ target.generic = function() {
['web/locale', GENERIC_DIR + '/web']
],
preprocess: [
[BUILD_TARGET, GENERIC_DIR + BUILD_TARGET],
[BUILD_TARGETS, GENERIC_DIR + BUILD_DIR],
[COMMON_WEB_FILES_PREPROCESS, GENERIC_DIR + '/web']
]
};
@ -231,72 +233,93 @@ target.bundle = function(args) {
cd(ROOT_DIR);
echo();
echo('### Bundling files into ' + BUILD_TARGET);
var reg = /\n\/\* -\*- Mode(.|\n)*?Mozilla Foundation(.|\n)*?'use strict';/g;
var SRC_FILES =
['network.js',
'chunked_stream.js',
'pdf_manager.js',
'core.js',
'util.js',
'api.js',
'canvas.js',
'obj.js',
'annotation.js',
'function.js',
'charsets.js',
'cidmaps.js',
'colorspace.js',
'crypto.js',
'evaluator.js',
'fonts.js',
'font_renderer.js',
'glyphlist.js',
'image.js',
'metrics.js',
'parser.js',
'pattern.js',
'stream.js',
'worker.js',
'jpx.js',
'jbig2.js',
'bidi.js',
'metadata.js'];
for (var i = 0, length = excludes.length; i < length; ++i) {
var exclude = excludes[i];
var index = SRC_FILES.indexOf(exclude);
if (index >= 0) {
SRC_FILES.splice(index, 1);
function bundle(filename, dir, SRC_FILES, EXT_SRC_FILES) {
for (var i = 0, length = excludes.length; i < length; ++i) {
var exclude = excludes[i];
var index = SRC_FILES.indexOf(exclude);
if (index >= 0) {
SRC_FILES.splice(index, 1);
}
}
}
var EXT_SRC_FILES = [
'../external/jpgjs/jpg.js'];
var bundle = cat(SRC_FILES),
bundleVersion = EXTENSION_VERSION,
bundleBuild = exec('git log --format="%h" -n 1',
{silent: true}).output.replace('\n', '');
crlfchecker.checkIfCrlfIsPresent(SRC_FILES);
// Strip out all the vim/license headers.
bundle = bundle.replace(reg, '');
// Append external files last since we don't want to modify them.
bundle += cat(EXT_SRC_FILES);
// This just preprocesses the empty pdf.js file, we don't actually want to
// preprocess everything yet since other build targets use this file.
builder.preprocess(filename, dir,
{BUNDLE: bundle,
BUNDLE_VERSION: bundleVersion,
BUNDLE_BUILD: bundleBuild});
}
if (!test('-d', BUILD_DIR))
mkdir(BUILD_DIR);
var MAIN_SRC_FILES = [
'shared/util.js',
'shared/colorspace.js',
'shared/pattern.js',
'shared/function.js',
'shared/annotation.js',
'display/api.js',
'display/metadata.js',
'display/canvas.js',
'display/font_loader.js',
'display/font_renderer.js'
];
var WORKER_SRC_FILES = [
'shared/util.js',
'shared/pattern.js',
'shared/function.js',
'shared/annotation.js',
'core/network.js',
'core/chunked_stream.js',
'core/pdf_manager.js',
'core/core.js',
'core/obj.js',
'core/charsets.js',
'core/cidmaps.js',
'shared/colorspace.js',
'core/crypto.js',
'core/evaluator.js',
'core/fonts.js',
'core/glyphlist.js',
'core/image.js',
'core/metrics.js',
'core/parser.js',
'core/stream.js',
'core/worker.js',
'core/jpx.js',
'core/jbig2.js',
'core/bidi.js'
];
var EXT_SRC_FILES = [
'../external/jpgjs/jpg.js'
];
cd(SRC_DIR);
var bundle = cat(SRC_FILES),
bundleVersion = EXTENSION_VERSION,
bundleBuild = exec('git log --format="%h" -n 1',
{silent: true}).output.replace('\n', '');
crlfchecker.checkIfCrlfIsPresent(SRC_FILES);
// Strip out all the vim/license headers.
var reg = /\n\/\* -\*- Mode(.|\n)*?Mozilla Foundation(.|\n)*?'use strict';/g;
bundle = bundle.replace(reg, '');
// Append external files last since we don't want to modify them.
bundle += cat(EXT_SRC_FILES);
// This just preprocesses the empty pdf.js file, we don't actually want to
// preprocess everything yet since other build targets use this file.
builder.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET,
{BUNDLE: bundle,
BUNDLE_VERSION: bundleVersion,
BUNDLE_BUILD: bundleBuild});
bundle('pdf.js', ROOT_DIR + BUILD_TARGET, MAIN_SRC_FILES, []);
var srcCopy = ROOT_DIR + BUILD_DIR + 'pdf.worker.js.temp';
cp('pdf.js', srcCopy);
bundle(srcCopy, ROOT_DIR + BUILD_WORKER_TARGET, WORKER_SRC_FILES,
EXT_SRC_FILES);
rm(srcCopy);
};
function cleanupJSSource(file) {
@ -382,7 +405,7 @@ target.firefox = function() {
FIREFOX_AMO_EXTENSION_NAME = 'pdf.js.amo.xpi';
target.locale();
target.bundle({ excludes: ['network.js'] });
target.bundle({ excludes: ['core/network.js'] });
cd(ROOT_DIR);
// Clear out everything in the firefox extension build directory
@ -408,8 +431,8 @@ target.firefox = function() {
],
preprocess: [
[COMMON_WEB_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR + '/web'],
[BUILD_TARGET, FIREFOX_BUILD_CONTENT_DIR + BUILD_TARGET],
[SRC_DIR + 'network.js', FIREFOX_BUILD_CONTENT_DIR]
[BUILD_TARGETS, FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR],
[SRC_DIR + 'core/network.js', FIREFOX_BUILD_CONTENT_DIR]
],
preprocessCSS: [
['firefox', 'web/viewer.css',
@ -494,7 +517,7 @@ target.mozcentral = function() {
'content',
'LICENSE'];
target.bundle({ excludes: ['network.js'] });
target.bundle({ excludes: ['core/network.js'] });
cd(ROOT_DIR);
// Clear out everything in the firefox extension build directory
@ -522,8 +545,8 @@ target.mozcentral = function() {
],
preprocess: [
[COMMON_WEB_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR + '/web'],
[BUILD_TARGET, MOZCENTRAL_CONTENT_DIR + BUILD_TARGET],
[SRC_DIR + 'network.js', MOZCENTRAL_CONTENT_DIR]
[BUILD_TARGETS, MOZCENTRAL_CONTENT_DIR + BUILD_DIR],
[SRC_DIR + 'core/network.js', MOZCENTRAL_CONTENT_DIR]
],
preprocessCSS: [
['firefox', 'web/viewer.css', MOZCENTRAL_CONTENT_DIR + '/web/viewer.css']
@ -596,7 +619,7 @@ target.b2g = function() {
],
preprocess: [
['web/viewer.js', B2G_BUILD_CONTENT_DIR + '/web'],
[BUILD_TARGET, B2G_BUILD_CONTENT_DIR + BUILD_TARGET]
[BUILD_TARGETS, B2G_BUILD_CONTENT_DIR + BUILD_DIR]
]
};
builder.build(setup);
@ -640,7 +663,7 @@ target.chrome = function() {
['web/locale', CHROME_BUILD_CONTENT_DIR + '/web']
],
preprocess: [
[BUILD_TARGET, CHROME_BUILD_CONTENT_DIR + BUILD_TARGET],
[BUILD_TARGETS, CHROME_BUILD_CONTENT_DIR + BUILD_DIR],
[COMMON_WEB_FILES_PREPROCESS, CHROME_BUILD_CONTENT_DIR + '/web']
]
};

View File

@ -15,31 +15,14 @@
* limitations under the License.
*/
/* globals assertWellFormed, calculateMD5, Catalog, error, info, isArray,
isArrayBuffer, isDict, isName, isStream, isString, Lexer,
isArrayBuffer, isName, isStream, isString, Lexer,
Linearization, NullStream, PartialEvaluator, shadow, Stream,
StreamsSequenceStream, stringToPDFString, TODO, Util, warn, XRef,
StreamsSequenceStream, stringToPDFString, Util, XRef,
MissingDataException, Promise, Annotation, ObjectLoader, OperatorList
*/
'use strict';
var globalScope = (typeof window === 'undefined') ? this : window;
var isWorker = (typeof window == 'undefined');
var ERRORS = 0, WARNINGS = 1, INFOS = 5;
var verbosity = WARNINGS;
// The global PDFJS object exposes the API
// In production, it will be declared outside a global wrapper
// In development, it will be declared here
if (!globalScope.PDFJS) {
globalScope.PDFJS = {};
}
globalScope.PDFJS.pdfBug = false;
var Page = (function PageClosure() {
function Page(pdfManager, xref, pageIndex, pageDict, ref) {

View File

@ -16,10 +16,10 @@
*/
/* globals assert, assertWellFormed, ColorSpace, Dict, Encodings, error,
ErrorFont, Font, FONT_IDENTITY_MATRIX, fontCharsToUnicode, FontFlags,
IDENTITY_MATRIX, info, isArray, isCmd, isDict, isEOF, isName, isNum,
info, isArray, isCmd, isDict, isEOF, isName, isNum,
isStream, isString, JpegStream, Lexer, Metrics, Name, Parser,
Pattern, PDFImage, PDFJS, serifFonts, stdFontMap, symbolsFonts,
TilingPattern, TODO, warn, Util, MissingDataException, Promise,
TilingPattern, TODO, warn, Util, Promise,
RefSetCache, isRef */
'use strict';

View File

@ -15,10 +15,10 @@
* limitations under the License.
*/
/* globals assert, bytesToString, CIDToUnicodeMaps, error, ExpertCharset,
ExpertSubsetCharset, FileReaderSync, globalScope, GlyphsUnicode,
info, isArray, isNum, ISOAdobeCharset, isWorker, PDFJS, Stream,
stringToBytes, TextDecoder, TODO, warn, Lexer, Util, shadow,
FontRendererFactory */
ExpertSubsetCharset, FileReaderSync, GlyphsUnicode,
info, isArray, isNum, ISOAdobeCharset, Stream,
stringToBytes, TextDecoder, TODO, warn, Lexer, Util,
FONT_IDENTITY_MATRIX */
'use strict';
@ -39,10 +39,6 @@ var HINTING_ENABLED = false;
// to control analysis of seac charstrings.
var SEAC_ANALYSIS_ENABLED = false;
var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
PDFJS.disableFontFace = false;
var FontFlags = {
FixedPitch: 1,
Serif: 2,
@ -538,250 +534,6 @@ function mapPrivateUseChars(code) {
}
}
var FontLoader = {
insertRule: function fontLoaderInsertRule(rule) {
var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
if (!styleElement) {
styleElement = document.createElement('style');
styleElement.id = 'PDFJS_FONT_STYLE_TAG';
document.documentElement.getElementsByTagName('head')[0].appendChild(
styleElement);
}
var styleSheet = styleElement.sheet;
styleSheet.insertRule(rule, styleSheet.cssRules.length);
},
//#if !(MOZCENTRAL)
get loadTestFont() {
// This is a CFF font with 1 glyph for '.' that fills its entire width and
// height.
return shadow(this, 'loadTestFont', atob(
'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' +
'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' +
'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' +
'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' +
'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' +
'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' +
'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' +
'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' +
'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' +
'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' +
'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' +
'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' +
'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' +
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' +
'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' +
'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' +
'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' +
'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' +
'ABAAAAAAAAAAAD6AAAAAAAAA=='
));
},
loadTestFontId: 0,
loadingContext: {
requests: [],
nextRequestId: 0
},
isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() {
if (isWorker)
return false;
// User agent string sniffing is bad, but there is no reliable way to tell
// if font is fully loaded and ready to be used with canvas.
var userAgent = window.navigator.userAgent;
var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent);
if (m && m[1] >= 14)
return true;
// TODO other browsers
return false;
})(),
bind: function fontLoaderBind(fonts, callback) {
assert(!isWorker, 'bind() shall be called from main thread');
var rules = [], fontsToLoad = [];
for (var i = 0, ii = fonts.length; i < ii; i++) {
var font = fonts[i];
// Add the font to the DOM only once or skip if the font
// is already loaded.
if (font.attached || font.loading === false) {
continue;
}
font.attached = true;
var rule = font.bindDOM();
if (rule) {
rules.push(rule);
fontsToLoad.push(font);
}
}
var request = FontLoader.queueLoadingCallback(callback);
if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request);
} else {
request.complete();
}
},
queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) {
function LoadLoader_completeRequest() {
assert(!request.end, 'completeRequest() cannot be called twice');
request.end = Date.now();
// sending all completed requests in order how they were queued
while (context.requests.length > 0 && context.requests[0].end) {
var otherRequest = context.requests.shift();
setTimeout(otherRequest.callback, 0);
}
}
var context = FontLoader.loadingContext;
var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++);
var request = {
id: requestId,
complete: LoadLoader_completeRequest,
callback: callback,
started: Date.now()
};
context.requests.push(request);
return request;
},
prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules,
fonts,
request) {
/** Hack begin */
// There's currently no event when a font has finished downloading so the
// following code is a dirty hack to 'guess' when a font is
// ready. It's assumed fonts are loaded in order, so add a known test
// font after the desired fonts and then test for the loading of that
// test font.
function int32(data, offset) {
return (data.charCodeAt(offset) << 24) |
(data.charCodeAt(offset + 1) << 16) |
(data.charCodeAt(offset + 2) << 8) |
(data.charCodeAt(offset + 3) & 0xff);
}
function string32(value) {
return String.fromCharCode((value >> 24) & 0xff) +
String.fromCharCode((value >> 16) & 0xff) +
String.fromCharCode((value >> 8) & 0xff) +
String.fromCharCode(value & 0xff);
}
function spliceString(s, offset, remove, insert) {
var chunk1 = data.substr(0, offset);
var chunk2 = data.substr(offset + remove);
return chunk1 + insert + chunk2;
}
var i, ii;
var canvas = document.createElement('canvas');
canvas.width = 1;
canvas.height = 1;
var ctx = canvas.getContext('2d');
var called = 0;
function isFontReady(name, callback) {
called++;
// With setTimeout clamping this gives the font ~100ms to load.
if(called > 30) {
warn('Load test font never loaded.');
callback();
return;
}
ctx.font = '30px ' + name;
ctx.fillText('.', 0, 20);
var imageData = ctx.getImageData(0, 0, 1, 1);
if (imageData.data[3] > 0) {
callback();
return;
}
setTimeout(isFontReady.bind(null, name, callback));
}
var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++;
// Chromium seems to cache fonts based on a hash of the actual font data,
// so the font must be modified for each load test else it will appear to
// be loaded already.
// TODO: This could maybe be made faster by avoiding the btoa of the full
// font by splitting it in chunks before hand and padding the font id.
var data = this.loadTestFont;
var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length,
loadTestFontId);
// CFF checksum is important for IE, adjusting it
var CFF_CHECKSUM_OFFSET = 16;
var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X'
var checksum = int32(data, CFF_CHECKSUM_OFFSET);
for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0;
}
if (i < loadTestFontId.length) { // align to 4 bytes boundary
checksum = (checksum - XXXX_VALUE +
int32(loadTestFontId + 'XXX', i)) | 0;
}
data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
var url = 'url(data:font/opentype;base64,' + btoa(data) + ');';
var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' +
url + '}';
FontLoader.insertRule(rule);
var names = [];
for (i = 0, ii = fonts.length; i < ii; i++) {
names.push(fonts[i].loadedName);
}
names.push(loadTestFontId);
var div = document.createElement('div');
div.setAttribute('style',
'visibility: hidden;' +
'width: 10px; height: 10px;' +
'position: absolute; top: 0px; left: 0px;');
for (i = 0, ii = names.length; i < ii; ++i) {
var span = document.createElement('span');
span.textContent = 'Hi';
span.style.fontFamily = names[i];
div.appendChild(span);
}
document.body.appendChild(div);
isFontReady(loadTestFontId, function() {
document.body.removeChild(div);
request.complete();
});
/** Hack end */
}
//#else
//bind: function fontLoaderBind(fonts, callback) {
// assert(!isWorker, 'bind() shall be called from main thread');
//
// for (var i = 0, ii = fonts.length; i < ii; i++) {
// var font = fonts[i];
// if (font.attached)
// continue;
//
// font.attached = true;
// font.bindDOM()
// }
//
// setTimeout(callback);
//}
//#endif
};
var UnicodeRanges = [
{ 'begin': 0x0000, 'end': 0x007F }, // Basic Latin
{ 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement
@ -2404,14 +2156,6 @@ function adjustWidths(properties) {
*/
var Font = (function FontClosure() {
function Font(name, file, properties) {
if (arguments.length === 1) {
// importing translated data
var data = arguments[0];
for (var i in data) {
this[i] = data[i];
}
return;
}
this.name = name;
this.loadedName = properties.loadedName;
@ -3048,11 +2792,6 @@ var Font = (function FontClosure() {
mimetype: null,
encoding: null,
get renderer() {
var renderer = FontRendererFactory.create(this);
return shadow(this, 'renderer', renderer);
},
exportData: function Font_exportData() {
var data = {};
for (var i in this) {
@ -4616,32 +4355,6 @@ var Font = (function FontClosure() {
}
},
bindDOM: function Font_bindDOM() {
if (!this.data)
return null;
if (PDFJS.disableFontFace) {
this.disableFontFace = true;
return null;
}
var data = bytesToString(this.data);
var fontName = this.loadedName;
// Add the font-face rule to the document
var url = ('url(data:' + this.mimetype + ';base64,' +
window.btoa(data) + ');');
var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
FontLoader.insertRule(rule);
if (PDFJS.pdfBug && 'FontInspector' in globalScope &&
globalScope['FontInspector'].enabled)
globalScope['FontInspector'].fontAdded(this, url);
return rule;
},
get spaceWidth() {
if ('_shadowWidth' in this) {
return this._shadowWidth;

View File

@ -496,12 +496,3 @@ var PDFImage = (function PDFImageClosure() {
};
return PDFImage;
})();
function loadJpegStream(id, imageData, objs) {
var img = new Image();
img.onload = (function loadJpegStream_onloadClosure() {
objs.resolve(id, img);
});
img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
}

View File

@ -16,7 +16,7 @@
*/
/* globals assertWellFormed, bytesToString, CipherTransformFactory, error, info,
InvalidPDFException, isArray, isCmd, isDict, isInt, isName, isRef,
isStream, JpegStream, Lexer, log, Page, Parser, Promise, shadow,
isStream, Lexer, log, Page, Parser, Promise, shadow,
stringToPDFString, stringToUTF8String, warn, isString, assert,
Promise, MissingDataException, XRefParseException, Stream,
ChunkedStream */
@ -1090,109 +1090,6 @@ var NameTree = (function NameTreeClosure() {
return NameTree;
})();
/**
* A PDF document and page is built of many objects. E.g. there are objects
* for fonts, images, rendering code and such. These objects might get processed
* inside of a worker. The `PDFObjects` implements some basic functions to
* manage these objects.
*/
var PDFObjects = (function PDFObjectsClosure() {
function PDFObjects() {
this.objs = {};
}
PDFObjects.prototype = {
/**
* Internal function.
* Ensures there is an object defined for `objId`.
*/
ensureObj: function PDFObjects_ensureObj(objId) {
if (this.objs[objId])
return this.objs[objId];
var obj = {
promise: new Promise(objId),
data: null,
resolved: false
};
this.objs[objId] = obj;
return obj;
},
/**
* If called *without* callback, this returns the data of `objId` but the
* object needs to be resolved. If it isn't, this function throws.
*
* If called *with* a callback, the callback is called with the data of the
* object once the object is resolved. That means, if you call this
* function and the object is already resolved, the callback gets called
* right away.
*/
get: function PDFObjects_get(objId, callback) {
// If there is a callback, then the get can be async and the object is
// not required to be resolved right now
if (callback) {
this.ensureObj(objId).promise.then(callback);
return null;
}
// If there isn't a callback, the user expects to get the resolved data
// directly.
var obj = this.objs[objId];
// If there isn't an object yet or the object isn't resolved, then the
// data isn't ready yet!
if (!obj || !obj.resolved)
error('Requesting object that isn\'t resolved yet ' + objId);
return obj.data;
},
/**
* Resolves the object `objId` with optional `data`.
*/
resolve: function PDFObjects_resolve(objId, data) {
var obj = this.ensureObj(objId);
obj.resolved = true;
obj.data = data;
obj.promise.resolve(data);
},
isResolved: function PDFObjects_isResolved(objId) {
var objs = this.objs;
if (!objs[objId]) {
return false;
} else {
return objs[objId].resolved;
}
},
hasData: function PDFObjects_hasData(objId) {
return this.isResolved(objId);
},
/**
* Returns the data of `objId` if object exists, null otherwise.
*/
getData: function PDFObjects_getData(objId) {
var objs = this.objs;
if (!objs[objId] || !objs[objId].resolved) {
return null;
} else {
return objs[objId].data;
}
},
clear: function PDFObjects_clear() {
this.objs = {};
}
};
return PDFObjects;
})();
/**
* A helper for loading missing data in object graphs. It traverses the graph
* depth first and queues up any objects that have missing data. Once it has

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
/* globals NotImplementedException, MissingDataException, Promise, Stream,
PDFDocument, ChunkedStream, ChunkedStreamManager */
PDFDocument, ChunkedStreamManager */
'use strict';

View File

@ -15,99 +15,14 @@
* limitations under the License.
*/
/* globals error, globalScope, InvalidPDFException, log,
MissingPDFException, PasswordException, PDFDocument, PDFJS, Promise,
Stream, UnknownErrorException, warn, NetworkManager, LocalPdfManager,
NetworkPdfManager, XRefParseException, NotImplementedException,
isInt, PasswordResponses */
MissingPDFException, PasswordException, PDFJS, Promise,
UnknownErrorException, NetworkManager, LocalPdfManager,
NetworkPdfManager, XRefParseException,
isInt, PasswordResponses, MessageHandler */
'use strict';
function MessageHandler(name, comObj) {
this.name = name;
this.comObj = comObj;
this.callbackIndex = 1;
var callbacks = this.callbacks = {};
var ah = this.actionHandler = {};
ah['console_log'] = [function ahConsoleLog(data) {
log.apply(null, data);
}];
// If there's no console available, console_error in the
// action handler will do nothing.
if ('console' in globalScope) {
ah['console_error'] = [function ahConsoleError(data) {
globalScope['console'].error.apply(null, data);
}];
} else {
ah['console_error'] = [function ahConsoleError(data) {
log.apply(null, data);
}];
}
ah['_warn'] = [function ah_Warn(data) {
warn(data);
}];
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
var data = event.data;
if (data.isReply) {
var callbackId = data.callbackId;
if (data.callbackId in callbacks) {
var callback = callbacks[callbackId];
delete callbacks[callbackId];
callback(data.data);
} else {
error('Cannot resolve callback ' + callbackId);
}
} else if (data.action in ah) {
var action = ah[data.action];
if (data.callbackId) {
var promise = new Promise();
promise.then(function(resolvedData) {
comObj.postMessage({
isReply: true,
callbackId: data.callbackId,
data: resolvedData
});
});
action[0].call(action[1], data.data, promise);
} else {
action[0].call(action[1], data.data);
}
} else {
error('Unkown action from worker: ' + data.action);
}
};
}
MessageHandler.prototype = {
on: function messageHandlerOn(actionName, handler, scope) {
var ah = this.actionHandler;
if (ah[actionName]) {
error('There is already an actionName called "' + actionName + '"');
}
ah[actionName] = [handler, scope];
},
/**
* Sends a message to the comObj to invoke the action with the supplied data.
* @param {String} actionName Action to call.
* @param {JSON} data JSON data to send.
* @param {function} [callback] Optional callback that will handle a reply.
*/
send: function messageHandlerSend(actionName, data, callback) {
var message = {
action: actionName,
data: data
};
if (callback) {
var callbackId = this.callbackIndex++;
this.callbacks[callbackId] = callback;
message.callbackId = callbackId;
}
this.comObj.postMessage(message);
}
};
var WorkerMessageHandler = {
var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
setup: function wphSetup(handler) {
var pdfManager;

View File

@ -14,10 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals CanvasGraphics, combineUrl, createScratchCanvas, error, ErrorFont,
Font, FontLoader, globalScope, info, isArrayBuffer, loadJpegStream,
MessageHandler, PDFJS, PDFObjects, Promise, StatTimer, warn,
WorkerMessageHandler, PasswordResponses, Util */
/* globals CanvasGraphics, combineUrl, createScratchCanvas, error,
FontLoader, globalScope, info, isArrayBuffer, loadJpegStream,
MessageHandler, PDFJS, Promise, StatTimer, warn,
PasswordResponses, Util, loadScript,
FontFace */
'use strict';
@ -344,7 +345,7 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
function complete(error) {
var i = self.renderTasks.indexOf(internalRenderTask);
if (i >= 0) {
self.renderTasks.splice(i, 1);
self.renderTasks.splice(i, 1);
}
if (self.cleanupAfterRender) {
@ -502,8 +503,10 @@ var WorkerTransport = (function WorkerTransportClosure() {
// Either workers are disabled, not supported or have thrown an exception.
// Thus, we fallback to a faked worker.
globalScope.PDFJS.disableWorker = true;
this.setupFakeWorker();
workerInitializedPromise.resolve();
this.loadFakeWorkerFiles().then(function() {
this.setupFakeWorker();
workerInitializedPromise.resolve();
}.bind(this));
}
WorkerTransport.prototype = {
destroy: function WorkerTransport_destroy() {
@ -516,6 +519,24 @@ var WorkerTransport = (function WorkerTransportClosure() {
}
});
},
loadFakeWorkerFiles: function WorkerTransport_loadFakeWorkerFiles() {
if (!PDFJS.fakeWorkerFilesLoadedPromise) {
PDFJS.fakeWorkerFilesLoadedPromise = new Promise();
// In the developer build load worker_loader which in turn loads all the
// other files and resolves the promise. In production only the
// pdf.worker.js file is needed.
//#if !PRODUCTION
Util.loadScript(PDFJS.workerSrc);
//#else
// Util.loadScript(PDFJS.workerSrc, function() {
// PDFJS.fakeWorkerFilesLoadedPromise.resolve();
// });
//#endif
}
return PDFJS.fakeWorkerFilesLoadedPromise;
},
setupFakeWorker: function WorkerTransport_setupFakeWorker() {
warn('Setting up fake worker.');
// If we don't use a worker, just post/sendMessage to the main thread.
@ -531,7 +552,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
// If the main thread is our worker, setup the handling for the messages
// the main thread sends to it self.
WorkerMessageHandler.setup(messageHandler);
PDFJS.WorkerMessageHandler.setup(messageHandler);
},
setupMessageHandler:
@ -642,7 +663,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
this.commonObjs.resolve(id, error);
break;
} else {
font = new Font(exportedData);
font = new FontFace(exportedData);
}
FontLoader.bind(
@ -797,6 +818,108 @@ var WorkerTransport = (function WorkerTransportClosure() {
})();
/**
* A PDF document and page is built of many objects. E.g. there are objects
* for fonts, images, rendering code and such. These objects might get processed
* inside of a worker. The `PDFObjects` implements some basic functions to
* manage these objects.
*/
var PDFObjects = (function PDFObjectsClosure() {
function PDFObjects() {
this.objs = {};
}
PDFObjects.prototype = {
/**
* Internal function.
* Ensures there is an object defined for `objId`.
*/
ensureObj: function PDFObjects_ensureObj(objId) {
if (this.objs[objId])
return this.objs[objId];
var obj = {
promise: new Promise(objId),
data: null,
resolved: false
};
this.objs[objId] = obj;
return obj;
},
/**
* If called *without* callback, this returns the data of `objId` but the
* object needs to be resolved. If it isn't, this function throws.
*
* If called *with* a callback, the callback is called with the data of the
* object once the object is resolved. That means, if you call this
* function and the object is already resolved, the callback gets called
* right away.
*/
get: function PDFObjects_get(objId, callback) {
// If there is a callback, then the get can be async and the object is
// not required to be resolved right now
if (callback) {
this.ensureObj(objId).promise.then(callback);
return null;
}
// If there isn't a callback, the user expects to get the resolved data
// directly.
var obj = this.objs[objId];
// If there isn't an object yet or the object isn't resolved, then the
// data isn't ready yet!
if (!obj || !obj.resolved)
error('Requesting object that isn\'t resolved yet ' + objId);
return obj.data;
},
/**
* Resolves the object `objId` with optional `data`.
*/
resolve: function PDFObjects_resolve(objId, data) {
var obj = this.ensureObj(objId);
obj.resolved = true;
obj.data = data;
obj.promise.resolve(data);
},
isResolved: function PDFObjects_isResolved(objId) {
var objs = this.objs;
if (!objs[objId]) {
return false;
} else {
return objs[objId].resolved;
}
},
hasData: function PDFObjects_hasData(objId) {
return this.isResolved(objId);
},
/**
* Returns the data of `objId` if object exists, null otherwise.
*/
getData: function PDFObjects_getData(objId) {
var objs = this.objs;
if (!objs[objId] || !objs[objId].resolved) {
return null;
} else {
return objs[objId].data;
}
},
clear: function PDFObjects_clear() {
this.objs = {};
}
};
return PDFObjects;
})();
/*
* RenderTask is basically a promise but adds a cancel function to terminate it.
*/
var RenderTask = (function RenderTaskClosure() {

View File

@ -16,7 +16,7 @@
*/
/* globals ColorSpace, DeviceCmykCS, DeviceGrayCS, DeviceRgbCS, error,
FONT_IDENTITY_MATRIX, IDENTITY_MATRIX, ImageData, isArray, isNum,
isString, Pattern, TilingPattern, TODO, Util, warn, assert, info */
Pattern, TilingPattern, TODO, Util, warn, assert, info */
'use strict';

311
src/display/font_loader.js Normal file
View File

@ -0,0 +1,311 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals PDFJS, shadow, isWorker, assert, warn, FontRendererFactory,
bytesToString, globalScope */
'use strict';
PDFJS.disableFontFace = false;
var FontLoader = {
insertRule: function fontLoaderInsertRule(rule) {
var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
if (!styleElement) {
styleElement = document.createElement('style');
styleElement.id = 'PDFJS_FONT_STYLE_TAG';
document.documentElement.getElementsByTagName('head')[0].appendChild(
styleElement);
}
var styleSheet = styleElement.sheet;
styleSheet.insertRule(rule, styleSheet.cssRules.length);
},
//#if !(MOZCENTRAL)
get loadTestFont() {
// This is a CFF font with 1 glyph for '.' that fills its entire width and
// height.
return shadow(this, 'loadTestFont', atob(
'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' +
'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' +
'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' +
'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' +
'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' +
'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' +
'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' +
'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' +
'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' +
'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' +
'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' +
'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' +
'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' +
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' +
'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' +
'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' +
'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' +
'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' +
'ABAAAAAAAAAAAD6AAAAAAAAA=='
));
},
loadTestFontId: 0,
loadingContext: {
requests: [],
nextRequestId: 0
},
isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() {
if (isWorker)
return false;
// User agent string sniffing is bad, but there is no reliable way to tell
// if font is fully loaded and ready to be used with canvas.
var userAgent = window.navigator.userAgent;
var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent);
if (m && m[1] >= 14)
return true;
// TODO other browsers
return false;
})(),
bind: function fontLoaderBind(fonts, callback) {
assert(!isWorker, 'bind() shall be called from main thread');
var rules = [], fontsToLoad = [];
for (var i = 0, ii = fonts.length; i < ii; i++) {
var font = fonts[i];
// Add the font to the DOM only once or skip if the font
// is already loaded.
if (font.attached || font.loading === false) {
continue;
}
font.attached = true;
var rule = font.bindDOM();
if (rule) {
rules.push(rule);
fontsToLoad.push(font);
}
}
var request = FontLoader.queueLoadingCallback(callback);
if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request);
} else {
request.complete();
}
},
queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) {
function LoadLoader_completeRequest() {
assert(!request.end, 'completeRequest() cannot be called twice');
request.end = Date.now();
// sending all completed requests in order how they were queued
while (context.requests.length > 0 && context.requests[0].end) {
var otherRequest = context.requests.shift();
setTimeout(otherRequest.callback, 0);
}
}
var context = FontLoader.loadingContext;
var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++);
var request = {
id: requestId,
complete: LoadLoader_completeRequest,
callback: callback,
started: Date.now()
};
context.requests.push(request);
return request;
},
prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules,
fonts,
request) {
/** Hack begin */
// There's currently no event when a font has finished downloading so the
// following code is a dirty hack to 'guess' when a font is
// ready. It's assumed fonts are loaded in order, so add a known test
// font after the desired fonts and then test for the loading of that
// test font.
function int32(data, offset) {
return (data.charCodeAt(offset) << 24) |
(data.charCodeAt(offset + 1) << 16) |
(data.charCodeAt(offset + 2) << 8) |
(data.charCodeAt(offset + 3) & 0xff);
}
function string32(value) {
return String.fromCharCode((value >> 24) & 0xff) +
String.fromCharCode((value >> 16) & 0xff) +
String.fromCharCode((value >> 8) & 0xff) +
String.fromCharCode(value & 0xff);
}
function spliceString(s, offset, remove, insert) {
var chunk1 = data.substr(0, offset);
var chunk2 = data.substr(offset + remove);
return chunk1 + insert + chunk2;
}
var i, ii;
var canvas = document.createElement('canvas');
canvas.width = 1;
canvas.height = 1;
var ctx = canvas.getContext('2d');
var called = 0;
function isFontReady(name, callback) {
called++;
// With setTimeout clamping this gives the font ~100ms to load.
if(called > 30) {
warn('Load test font never loaded.');
callback();
return;
}
ctx.font = '30px ' + name;
ctx.fillText('.', 0, 20);
var imageData = ctx.getImageData(0, 0, 1, 1);
if (imageData.data[3] > 0) {
callback();
return;
}
setTimeout(isFontReady.bind(null, name, callback));
}
var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++;
// Chromium seems to cache fonts based on a hash of the actual font data,
// so the font must be modified for each load test else it will appear to
// be loaded already.
// TODO: This could maybe be made faster by avoiding the btoa of the full
// font by splitting it in chunks before hand and padding the font id.
var data = this.loadTestFont;
var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length,
loadTestFontId);
// CFF checksum is important for IE, adjusting it
var CFF_CHECKSUM_OFFSET = 16;
var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X'
var checksum = int32(data, CFF_CHECKSUM_OFFSET);
for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0;
}
if (i < loadTestFontId.length) { // align to 4 bytes boundary
checksum = (checksum - XXXX_VALUE +
int32(loadTestFontId + 'XXX', i)) | 0;
}
data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
var url = 'url(data:font/opentype;base64,' + btoa(data) + ');';
var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' +
url + '}';
FontLoader.insertRule(rule);
var names = [];
for (i = 0, ii = fonts.length; i < ii; i++) {
names.push(fonts[i].loadedName);
}
names.push(loadTestFontId);
var div = document.createElement('div');
div.setAttribute('style',
'visibility: hidden;' +
'width: 10px; height: 10px;' +
'position: absolute; top: 0px; left: 0px;');
for (i = 0, ii = names.length; i < ii; ++i) {
var span = document.createElement('span');
span.textContent = 'Hi';
span.style.fontFamily = names[i];
div.appendChild(span);
}
document.body.appendChild(div);
isFontReady(loadTestFontId, function() {
document.body.removeChild(div);
request.complete();
});
/** Hack end */
}
//#else
//bind: function fontLoaderBind(fonts, callback) {
// assert(!isWorker, 'bind() shall be called from main thread');
//
// for (var i = 0, ii = fonts.length; i < ii; i++) {
// var font = fonts[i];
// if (font.attached)
// continue;
//
// font.attached = true;
// font.bindDOM()
// }
//
// setTimeout(callback);
//}
//#endif
};
var FontFace = (function FontFaceClosure() {
function FontFace(name, file, properties) {
if (arguments.length === 1) {
// importing translated data
var data = arguments[0];
for (var i in data) {
this[i] = data[i];
}
return;
}
}
FontFace.prototype = {
get renderer() {
var renderer = FontRendererFactory.create(this);
return shadow(this, 'renderer', renderer);
},
bindDOM: function FontFace_bindDOM() {
if (!this.data)
return null;
if (PDFJS.disableFontFace) {
this.disableFontFace = true;
return null;
}
var data = bytesToString(this.data);
var fontName = this.loadedName;
// Add the font-face rule to the document
var url = ('url(data:' + this.mimetype + ';base64,' +
window.btoa(data) + ');');
var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
FontLoader.insertRule(rule);
if (PDFJS.pdfBug && 'FontInspector' in globalScope &&
globalScope['FontInspector'].enabled)
globalScope['FontInspector'].fontAdded(this, url);
return rule;
}
};
return FontFace;
})();

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals error, info, input, isArray, isDict, isName, isStream, isString,
/* globals error, info, isArray, isDict, isName, isStream, isString,
PDFFunction, warn, shadow */
'use strict';

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
/* globals CFFDictDataMap, CFFDictPrivateDataMap, CFFEncodingMap, CFFStrings,
Components, Dict, dump, error, isNum, log, netscape, Stream, warn */
Components, Dict, dump, error, isNum, log, netscape, Stream */
'use strict';

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals CanvasGraphics, ColorSpace, createScratchCanvas, DeviceRgbCS, error,
/* globals CanvasGraphics, ColorSpace, DeviceRgbCS, error,
info, isArray, isPDFFunction, isStream, PDFFunction, TODO, Util,
warn, CachedCanvases */

View File

@ -14,11 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals Cmd, ColorSpace, Dict, globalScope, INFOS, MozBlobBuilder, Name,
PDFJS, Ref, WARNINGS, verbosity */
/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref */
'use strict';
var globalScope = (typeof window === 'undefined') ? this : window;
var isWorker = (typeof window == 'undefined');
var ERRORS = 0, WARNINGS = 1, INFOS = 5;
var verbosity = WARNINGS;
var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
// The global PDFJS object exposes the API
// In production, it will be declared outside a global wrapper
// In development, it will be declared here
if (!globalScope.PDFJS) {
globalScope.PDFJS = {};
}
globalScope.PDFJS.pdfBug = false;
// Use only for debugging purposes. This should not be used in any code that is
// in mozilla master.
var log = (function() {
@ -466,6 +484,21 @@ var Util = PDFJS.Util = (function UtilClosure() {
}
};
Util.loadScript = function Util_loadScript(src, callback) {
var script = document.createElement('script');
var loaded = false;
script.setAttribute('src', src);
if (callback) {
script.onreadystatechange = script.onload = function() {
if (!loaded) {
callback();
}
loaded = true;
};
}
document.getElementsByTagName('head')[0].appendChild(script);
};
return Util;
})();
@ -948,3 +981,96 @@ PDFJS.createBlob = function createBlob(data, contentType) {
bb.append(data);
return bb.getBlob(contentType);
};
function MessageHandler(name, comObj) {
this.name = name;
this.comObj = comObj;
this.callbackIndex = 1;
var callbacks = this.callbacks = {};
var ah = this.actionHandler = {};
ah['console_log'] = [function ahConsoleLog(data) {
log.apply(null, data);
}];
// If there's no console available, console_error in the
// action handler will do nothing.
if ('console' in globalScope) {
ah['console_error'] = [function ahConsoleError(data) {
globalScope['console'].error.apply(null, data);
}];
} else {
ah['console_error'] = [function ahConsoleError(data) {
log.apply(null, data);
}];
}
ah['_warn'] = [function ah_Warn(data) {
warn(data);
}];
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
var data = event.data;
if (data.isReply) {
var callbackId = data.callbackId;
if (data.callbackId in callbacks) {
var callback = callbacks[callbackId];
delete callbacks[callbackId];
callback(data.data);
} else {
error('Cannot resolve callback ' + callbackId);
}
} else if (data.action in ah) {
var action = ah[data.action];
if (data.callbackId) {
var promise = new Promise();
promise.then(function(resolvedData) {
comObj.postMessage({
isReply: true,
callbackId: data.callbackId,
data: resolvedData
});
});
action[0].call(action[1], data.data, promise);
} else {
action[0].call(action[1], data.data);
}
} else {
error('Unkown action from worker: ' + data.action);
}
};
}
MessageHandler.prototype = {
on: function messageHandlerOn(actionName, handler, scope) {
var ah = this.actionHandler;
if (ah[actionName]) {
error('There is already an actionName called "' + actionName + '"');
}
ah[actionName] = [handler, scope];
},
/**
* Sends a message to the comObj to invoke the action with the supplied data.
* @param {String} actionName Action to call.
* @param {JSON} data JSON data to send.
* @param {function} [callback] Optional callback that will handle a reply.
*/
send: function messageHandlerSend(actionName, data, callback) {
var message = {
action: actionName,
data: data
};
if (callback) {
var callbackId = this.callbackIndex++;
this.callbacks[callbackId] = callback;
message.callbackId = callbackId;
}
this.comObj.postMessage(message);
}
};
function loadJpegStream(id, imageData, objs) {
var img = new Image();
img.onload = (function loadJpegStream_onloadClosure() {
objs.resolve(id, img);
});
img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
}

View File

@ -14,40 +14,59 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals PDFJS, Util */
'use strict';
// List of files to include;
var files = [
'network.js',
'chunked_stream.js',
'pdf_manager.js',
'core.js',
'util.js',
'canvas.js',
'obj.js',
'annotation.js',
'function.js',
'charsets.js',
'cidmaps.js',
'colorspace.js',
'crypto.js',
'evaluator.js',
'fonts.js',
'glyphlist.js',
'image.js',
'metrics.js',
'parser.js',
'pattern.js',
'stream.js',
'worker.js',
'jpx.js',
'jbig2.js',
'bidi.js',
'shared/util.js',
'shared/colorspace.js',
'shared/pattern.js',
'shared/function.js',
'shared/annotation.js',
'core/network.js',
'core/chunked_stream.js',
'core/pdf_manager.js',
'core/core.js',
'core/obj.js',
'core/charsets.js',
'core/cidmaps.js',
'core/crypto.js',
'core/evaluator.js',
'core/fonts.js',
'core/glyphlist.js',
'core/image.js',
'core/metrics.js',
'core/parser.js',
'core/stream.js',
'core/worker.js',
'core/jpx.js',
'core/jbig2.js',
'core/bidi.js',
'../external/jpgjs/jpg.js'
];
// Load all the files.
for (var i = 0; i < files.length; i++) {
importScripts(files[i]);
function loadInOrder(index, path, files) {
if (index >= files.length) {
PDFJS.fakeWorkerFilesLoadedPromise.resolve();
return;
}
// Skip shared files since they will already be loaded.
if (files[index].indexOf('shared/') >= 0) {
loadInOrder(++index, path, files);
return;
}
Util.loadScript(path + files[index],
loadInOrder.bind(null, ++index, path, files));
}
// Load all the files.
if (typeof PDFJS === 'undefined' || !PDFJS.fakeWorkerFilesLoadedPromise) {
for (var i = 0; i < files.length; i++) {
importScripts(files[i]);
}
} else {
var src = PDFJS.workerSrc;
loadInOrder(0, src.substr(0, src.indexOf('worker_loader.js')), files);
}

View File

@ -12,33 +12,33 @@
<script type="text/javascript" src="fontutils.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="../../src/network.js"></script>
<script type="text/javascript" src="../../src/chunked_stream.js"></script>
<script type="text/javascript" src="../../src/pdf_manager.js"></script>
<script type="text/javascript" src="../../src/core.js"></script>
<script type="text/javascript" src="../../src/api.js"></script>
<script type="text/javascript" src="../../src/util.js"></script>
<script type="text/javascript" src="../../src/canvas.js"></script>
<script type="text/javascript" src="../../src/obj.js"></script>
<script type="text/javascript" src="../../src/annotation.js"></script>
<script type="text/javascript" src="../../src/function.js"></script>
<script type="text/javascript" src="../../src/charsets.js"></script>
<script type="text/javascript" src="../../src/cidmaps.js"></script>
<script type="text/javascript" src="../../src/colorspace.js"></script>
<script type="text/javascript" src="../../src/crypto.js"></script>
<script type="text/javascript" src="../../src/evaluator.js"></script>
<script type="text/javascript" src="../../src/fonts.js"></script>
<script type="text/javascript" src="../../src/glyphlist.js"></script>
<script type="text/javascript" src="../../src/image.js"></script>
<script type="text/javascript" src="../../src/metrics.js"></script>
<script type="text/javascript" src="../../src/parser.js"></script>
<script type="text/javascript" src="../../src/pattern.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/metadata.js"></script>
<script type="text/javascript" src="../../src/core/network.js"></script>
<script type="text/javascript" src="../../src/core/chunked_stream.js"></script>
<script type="text/javascript" src="../../src/core/pdf_manager.js"></script>
<script type="text/javascript" src="../../src/core/core.js"></script>
<script type="text/javascript" src="../../src/shared/util.js"></script>
<script type="text/javascript" src="../../src/display/api.js"></script>
<script type="text/javascript" src="../../src/display/canvas.js"></script>
<script type="text/javascript" src="../../src/core/obj.js"></script>
<script type="text/javascript" src="../../src/shared/annotation.js"></script>
<script type="text/javascript" src="../../src/shared/function.js"></script>
<script type="text/javascript" src="../../src/core/charsets.js"></script>
<script type="text/javascript" src="../../src/core/cidmaps.js"></script>
<script type="text/javascript" src="../../src/shared/colorspace.js"></script>
<script type="text/javascript" src="../../src/core/crypto.js"></script>
<script type="text/javascript" src="../../src/core/evaluator.js"></script>
<script type="text/javascript" src="../../src/core/fonts.js"></script>
<script type="text/javascript" src="../../src/core/glyphlist.js"></script>
<script type="text/javascript" src="../../src/core/image.js"></script>
<script type="text/javascript" src="../../src/core/metrics.js"></script>
<script type="text/javascript" src="../../src/core/parser.js"></script>
<script type="text/javascript" src="../../src/shared/pattern.js"></script>
<script type="text/javascript" src="../../src/core/stream.js"></script>
<script type="text/javascript" src="../../src/core/worker.js"></script>
<script type="text/javascript" src="../../src/display/metadata.js"></script>
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
<script type="text/javascript">PDFJS.workerSrc = '../../src/worker_loader.js';</script>
<!-- include spec files here... -->
<script type="text/javascript" src="font_core_spec.js"></script>
<script type="text/javascript" src="font_os2_spec.js"></script>

View File

@ -19,34 +19,16 @@ limitations under the License.
<head>
<title>pdf.js test slave</title>
<style type="text/css"></style>
<script type="text/javascript" src="/src/network.js"></script>
<script type="text/javascript" src="/src/chunked_stream.js"></script>
<script type="text/javascript" src="/src/pdf_manager.js"></script>
<script type="text/javascript" src="/src/core.js"></script>
<script type="text/javascript" src="/src/util.js"></script>
<script type="text/javascript" src="/src/api.js"></script>
<script type="text/javascript" src="/src/canvas.js"></script>
<script type="text/javascript" src="/src/obj.js"></script>
<script type="text/javascript" src="/src/annotation.js"></script>
<script type="text/javascript" src="/src/function.js"></script>
<script type="text/javascript" src="/src/charsets.js"></script>
<script type="text/javascript" src="/src/cidmaps.js"></script>
<script type="text/javascript" src="/src/colorspace.js"></script>
<script type="text/javascript" src="/src/crypto.js"></script>
<script type="text/javascript" src="/src/evaluator.js"></script>
<script type="text/javascript" src="/src/fonts.js"></script>
<script type="text/javascript" src="/src/font_renderer.js"></script>
<script type="text/javascript" src="/src/glyphlist.js"></script>
<script type="text/javascript" src="/src/image.js"></script>
<script type="text/javascript" src="/src/metrics.js"></script>
<script type="text/javascript" src="/src/parser.js"></script>
<script type="text/javascript" src="/src/pattern.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="/external/jpgjs/jpg.js"></script>
<script type="text/javascript" src="/src/jpx.js"></script>
<script type="text/javascript" src="/src/jbig2.js"></script>
<script type="text/javascript" src="/src/bidi.js"></script>
<script type="text/javascript" src="/src/shared/util.js"></script>
<script type="text/javascript" src="/src/shared/colorspace.js"></script>
<script type="text/javascript" src="/src/shared/pattern.js"></script>
<script type="text/javascript" src="/src/shared/function.js"></script>
<script type="text/javascript" src="/src/shared/annotation.js"></script>
<script type="text/javascript" src="/src/display/api.js"></script>
<script type="text/javascript" src="/src/display/metadata.js"></script>
<script type="text/javascript" src="/src/display/canvas.js"></script>
<script type="text/javascript" src="/src/display/font_loader.js"></script>
<script type="text/javascript" src="/src/display/font_renderer.js"></script>
<script type="text/javascript" src="driver.js"></script>
<script type="text/javascript">

View File

@ -6,7 +6,6 @@
describe('api', function() {
// TODO run with worker enabled
PDFJS.disableWorker = true;
var basicApiUrl = combineUrl(window.location.href, '../pdfs/basicapi.pdf');
function waitsForPromise(promise, successCallback) {
var data;

View File

@ -11,33 +11,33 @@
<script type="text/javascript" src="testreporter.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="../../src/network.js"></script>
<script type="text/javascript" src="../../src/chunked_stream.js"></script>
<script type="text/javascript" src="../../src/pdf_manager.js"></script>
<script type="text/javascript" src="../../src/core.js"></script>
<script type="text/javascript" src="../../src/util.js"></script>
<script type="text/javascript" src="../../src/api.js"></script>
<script type="text/javascript" src="../../src/canvas.js"></script>
<script type="text/javascript" src="../../src/obj.js"></script>
<script type="text/javascript" src="../../src/annotation.js"></script>
<script type="text/javascript" src="../../src/function.js"></script>
<script type="text/javascript" src="../../src/charsets.js"></script>
<script type="text/javascript" src="../../src/cidmaps.js"></script>
<script type="text/javascript" src="../../src/colorspace.js"></script>
<script type="text/javascript" src="../../src/crypto.js"></script>
<script type="text/javascript" src="../../src/evaluator.js"></script>
<script type="text/javascript" src="../../src/fonts.js"></script>
<script type="text/javascript" src="../../src/glyphlist.js"></script>
<script type="text/javascript" src="../../src/image.js"></script>
<script type="text/javascript" src="../../src/metrics.js"></script>
<script type="text/javascript" src="../../src/parser.js"></script>
<script type="text/javascript" src="../../src/pattern.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/metadata.js"></script>
<script type="text/javascript" src="../../src/core/network.js"></script>
<script type="text/javascript" src="../../src/core/chunked_stream.js"></script>
<script type="text/javascript" src="../../src/core/pdf_manager.js"></script>
<script type="text/javascript" src="../../src/core/core.js"></script>
<script type="text/javascript" src="../../src/shared/util.js"></script>
<script type="text/javascript" src="../../src/display/api.js"></script>
<script type="text/javascript" src="../../src/display/canvas.js"></script>
<script type="text/javascript" src="../../src/core/obj.js"></script>
<script type="text/javascript" src="../../src/shared/annotation.js"></script>
<script type="text/javascript" src="../../src/shared/function.js"></script>
<script type="text/javascript" src="../../src/core/charsets.js"></script>
<script type="text/javascript" src="../../src/core/cidmaps.js"></script>
<script type="text/javascript" src="../../src/shared/colorspace.js"></script>
<script type="text/javascript" src="../../src/core/crypto.js"></script>
<script type="text/javascript" src="../../src/core/evaluator.js"></script>
<script type="text/javascript" src="../../src/core/fonts.js"></script>
<script type="text/javascript" src="../../src/core/glyphlist.js"></script>
<script type="text/javascript" src="../../src/core/image.js"></script>
<script type="text/javascript" src="../../src/core/metrics.js"></script>
<script type="text/javascript" src="../../src/core/parser.js"></script>
<script type="text/javascript" src="../../src/shared/pattern.js"></script>
<script type="text/javascript" src="../../src/core/stream.js"></script>
<script type="text/javascript" src="../../src/core/worker.js"></script>
<script type="text/javascript" src="../../src/display/metadata.js"></script>
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
<script type="text/javascript">PDFJS.workerSrc = '../../src/worker_loader.js';</script>
<!-- include spec files here... -->
<script type="text/javascript" src="obj_spec.js"></script>
<script type="text/javascript" src="font_spec.js"></script>

View File

@ -41,35 +41,16 @@ limitations under the License.
<!--#endif-->
<!--#if !PRODUCTION-->
<script type="text/javascript" src="../src/network.js"></script>
<script type="text/javascript" src="../src/chunked_stream.js"></script>
<script type="text/javascript" src="../src/pdf_manager.js"></script>
<script type="text/javascript" src="../src/core.js"></script>
<script type="text/javascript" src="../src/util.js"></script>
<script type="text/javascript" src="../src/api.js"></script>
<script type="text/javascript" src="../src/canvas.js"></script>
<script type="text/javascript" src="../src/obj.js"></script>
<script type="text/javascript" src="../src/annotation.js"></script>
<script type="text/javascript" src="../src/function.js"></script>
<script type="text/javascript" src="../src/charsets.js"></script>
<script type="text/javascript" src="../src/cidmaps.js"></script>
<script type="text/javascript" src="../src/colorspace.js"></script>
<script type="text/javascript" src="../src/crypto.js"></script>
<script type="text/javascript" src="../src/evaluator.js"></script>
<script type="text/javascript" src="../src/fonts.js"></script>
<script type="text/javascript" src="../src/font_renderer.js"></script>
<script type="text/javascript" src="../src/glyphlist.js"></script>
<script type="text/javascript" src="../src/image.js"></script>
<script type="text/javascript" src="../src/metrics.js"></script>
<script type="text/javascript" src="../src/parser.js"></script>
<script type="text/javascript" src="../src/pattern.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/jpx.js"></script>
<script type="text/javascript" src="../src/jbig2.js"></script>
<script type="text/javascript" src="../src/bidi.js"></script>
<script type="text/javascript" src="../src/metadata.js"></script>
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script>
<script type="text/javascript" src="../src/shared/util.js"></script>
<script type="text/javascript" src="../src/shared/colorspace.js"></script>
<script type="text/javascript" src="../src/shared/pattern.js"></script>
<script type="text/javascript" src="../src/shared/function.js"></script>
<script type="text/javascript" src="../src/shared/annotation.js"></script>
<script type="text/javascript" src="../src/display/api.js"></script>
<script type="text/javascript" src="../src/display/metadata.js"></script>
<script type="text/javascript" src="../src/display/canvas.js"></script>
<script type="text/javascript" src="../src/display/font_loader.js"></script>
<script type="text/javascript" src="../src/display/font_renderer.js"></script>
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script>
<!--#endif-->

View File

@ -49,7 +49,7 @@ var FindStates = {
PDFJS.imageResourcesPath = './images/';
//#if (FIREFOX || MOZCENTRAL || B2G || GENERIC || CHROME)
//PDFJS.workerSrc = '../build/pdf.js';
//PDFJS.workerSrc = '../build/pdf.worker.js';
//#endif
var mozL10n = document.mozL10n || document.webL10n;