Add a gulp image_decoders command to allow packaging/distributing the image decoders (i.e. jpg.js, jpx.js, jbig2.js) separately from the main PDF.js library

Please note that the standalone `pdf.image_decoders.js` file will be including the complete `src/shared/util.js` file, despite only using parts of it.[1] This was done *purposely*, to not negatively impact the readability/maintainability of the core PDF.js code.

Furthermore, to ensure that the compatibility is the same in the regular PDF.js library *and* in the the standalone image decoders, `src/shared/compatibility.js` was included as well.

To (hopefully) prevent future complaints about the size of the built `pdf.image_decoders.js` file, a few existing async-related polyfills are being skipped (since all of the image decoders are completely synchronous).
Obviously this required adding a couple of pre-processor statements, but given that these are all limited to "compatibility" code, I think this might be OK!?

---
[1] However, please note that previous commits moved `PageViewport` and `MessageHandler` out of `src/shared/util.js` which reduced its size.
This commit is contained in:
Jonas Jenwald 2018-05-16 13:49:26 +02:00
parent bfc88ead66
commit 303537bcb1
4 changed files with 111 additions and 4 deletions

View File

@ -50,6 +50,7 @@ var BASELINE_DIR = BUILD_DIR + 'baseline/';
var MOZCENTRAL_BASELINE_DIR = BUILD_DIR + 'mozcentral.baseline/';
var GENERIC_DIR = BUILD_DIR + 'generic/';
var COMPONENTS_DIR = BUILD_DIR + 'components/';
var IMAGE_DECODERS_DIR = BUILD_DIR + 'image_decoders';
var MINIFIED_DIR = BUILD_DIR + 'minified/';
var JSDOC_BUILD_DIR = BUILD_DIR + 'jsdoc/';
var GH_PAGES_DIR = BUILD_DIR + 'gh-pages/';
@ -70,7 +71,7 @@ var builder = require('./external/builder/builder.js');
var CONFIG_FILE = 'pdfjs.config';
var config = JSON.parse(fs.readFileSync(CONFIG_FILE).toString());
// Default Autoprefixer config used for generic, components, minifed-pre
// Default Autoprefixer config used for generic, components, minified-pre
var AUTOPREFIXER_CONFIG = {
browsers: [
'last 2 versions',
@ -96,6 +97,7 @@ var DEFINES = {
COMPONENTS: false,
LIB: false,
SKIP_BABEL: false,
IMAGE_DECODERS: false,
};
function safeSpawnSync(command, parameters, options) {
@ -306,6 +308,22 @@ function createComponentsBundle(defines) {
.pipe(replaceJSRootName(componentsAMDName, 'pdfjsViewer'));
}
function createImageDecodersBundle(defines) {
var imageDecodersAMDName = 'pdfjs-dist/image_decoders/pdf.image_decoders';
var imageDecodersOutputName = 'pdf.image_decoders.js';
var componentsFileConfig = createWebpackConfig(defines, {
filename: imageDecodersOutputName,
library: imageDecodersAMDName,
libraryTarget: 'umd',
umdNamedDefine: true,
});
return gulp.src('./src/pdf.image_decoders.js')
.pipe(webpack2Stream(componentsFileConfig))
.pipe(replaceWebpackRequire())
.pipe(replaceJSRootName(imageDecodersAMDName, 'pdfjsImageDecoders'));
}
function checkFile(path) {
try {
var stat = fs.lstatSync(path);
@ -631,6 +649,15 @@ gulp.task('components', ['buildnumber'], function () {
]);
});
gulp.task('image_decoders', ['buildnumber'], function() {
console.log();
console.log('### Creating image decoders');
var defines = builder.merge(DEFINES, { GENERIC: true,
IMAGE_DECODERS: true, });
return createImageDecodersBundle(defines).pipe(gulp.dest(IMAGE_DECODERS_DIR));
});
gulp.task('minified-pre', ['buildnumber', 'locale'], function () {
console.log();
console.log('### Creating minified viewer');
@ -641,6 +668,8 @@ gulp.task('minified-pre', ['buildnumber', 'locale'], function () {
return merge([
createBundle(defines).pipe(gulp.dest(MINIFIED_DIR + 'build')),
createWebBundle(defines).pipe(gulp.dest(MINIFIED_DIR + 'web')),
createImageDecodersBundle(builder.merge(defines, { IMAGE_DECODERS: true, }))
.pipe(gulp.dest(MINIFIED_DIR + 'image_decoders')),
gulp.src(COMMON_WEB_FILES, { base: 'web/', })
.pipe(gulp.dest(MINIFIED_DIR + 'web')),
gulp.src([
@ -666,6 +695,8 @@ gulp.task('minified-post', ['minified-pre'], function () {
var pdfFile = fs.readFileSync(MINIFIED_DIR + '/build/pdf.js').toString();
var pdfWorkerFile =
fs.readFileSync(MINIFIED_DIR + '/build/pdf.worker.js').toString();
var pdfImageDecodersFile = fs.readFileSync(MINIFIED_DIR +
'/image_decoders/pdf.image_decoders.js').toString();
var viewerFiles = {
'pdf.js': pdfFile,
'viewer.js': fs.readFileSync(MINIFIED_DIR + '/web/viewer.js').toString(),
@ -684,6 +715,8 @@ gulp.task('minified-post', ['minified-pre'], function () {
UglifyES.minify(pdfFile).code);
fs.writeFileSync(MINIFIED_DIR + '/build/pdf.worker.min.js',
UglifyES.minify(pdfWorkerFile, optsForHugeFile).code);
fs.writeFileSync(MINIFIED_DIR + 'image_decoders/pdf.image_decoders.min.js',
UglifyES.minify(pdfImageDecodersFile).code);
console.log();
console.log('### Cleaning js files');
@ -696,6 +729,8 @@ gulp.task('minified-post', ['minified-pre'], function () {
MINIFIED_DIR + '/build/pdf.js');
fs.renameSync(MINIFIED_DIR + '/build/pdf.worker.min.js',
MINIFIED_DIR + '/build/pdf.worker.js');
fs.renameSync(MINIFIED_DIR + '/image_decoders/pdf.image_decoders.min.js',
MINIFIED_DIR + '/image_decoders/pdf.image_decoders.js');
});
gulp.task('minified', ['minified-post']);
@ -1138,7 +1173,8 @@ gulp.task('gh-pages-git', ['gh-pages-prepare', 'wintersmith'], function () {
gulp.task('web', ['gh-pages-prepare', 'wintersmith', 'gh-pages-git']);
gulp.task('dist-pre', ['generic', 'components', 'lib', 'minified'], function() {
gulp.task('dist-pre',
['generic', 'components', 'image_decoders', 'lib', 'minified'], function() {
var VERSION = getVersionJSON().version;
console.log();
@ -1228,8 +1264,13 @@ gulp.task('dist-pre', ['generic', 'components', 'lib', 'minified'], function() {
gulp.src(MINIFIED_DIR + 'build/pdf.worker.js')
.pipe(rename('pdf.worker.min.js'))
.pipe(gulp.dest(DIST_DIR + 'build/')),
gulp.src(MINIFIED_DIR + 'image_decoders/pdf.image_decoders.js')
.pipe(rename('pdf.image_decoders.min.js'))
.pipe(gulp.dest(DIST_DIR + 'image_decoders/')),
gulp.src(COMPONENTS_DIR + '**/*', { base: COMPONENTS_DIR, })
.pipe(gulp.dest(DIST_DIR + 'web/')),
gulp.src(IMAGE_DECODERS_DIR + '**/*', { base: IMAGE_DECODERS_DIR, })
.pipe(gulp.dest(DIST_DIR + 'image_decoders')),
gulp.src(LIB_DIR + '**/*', { base: LIB_DIR, })
.pipe(gulp.dest(DIST_DIR + 'lib/')),
]);

45
src/pdf.image_decoders.js Normal file
View File

@ -0,0 +1,45 @@
/* Copyright 2018 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.
*/
/* eslint-disable no-unused-vars */
import { getVerbosityLevel, setVerbosityLevel } from './shared/util';
import { Jbig2mage } from './core/jbig2';
import { JpegImage } from './core/jpg';
import { JpxImage } from './core/jpx';
// To ensure that the standalone PDF.js image decoders have the same
// browser/environment compatibility as the regular PDF.js library,
// the standard set of polyfills are thus included in this build as well.
//
// Given that the (current) image decoders don't use all of the features
// of the complete PDF.js library, e.g. they are completely synchronous,
// some of the larger polyfills are thus unnecessary.
//
// In an attempt to reduce the size of the standalone PDF.js image decoders,
// the following polyfills are currently being excluded:
// - ReadableStream
// - Promise
// - URL
const pdfjsVersion = PDFJSDev.eval('BUNDLE_VERSION');
const pdfjsBuild = PDFJSDev.eval('BUNDLE_BUILD');
export {
Jbig2mage,
JpegImage,
JpxImage,
getVerbosityLevel,
setVerbosityLevel,
};

View File

@ -138,6 +138,11 @@ const hasDOM = typeof window === 'object' && typeof document === 'object';
// Support: IE, Safari<8, Chrome<32
(function checkPromise() {
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('IMAGE_DECODERS')) {
// The current image decoders are synchronous, hence `Promise` shouldn't
// need to be polyfilled for the IMAGE_DECODERS build target.
return;
}
if (globalScope.Promise) {
return;
}
@ -157,6 +162,11 @@ const hasDOM = typeof window === 'object' && typeof document === 'object';
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
(function checkURLConstructor() {
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('IMAGE_DECODERS')) {
// The current image decoders doesn't utilize the `URL` constructor, hence
// it shouldn't need to be polyfilled for the IMAGE_DECODERS build target.
return;
}
// feature detect for URL constructor
var hasWorkingUrl = false;
try {

View File

@ -31,6 +31,17 @@ if (typeof ReadableStream !== 'undefined') {
if (isReadableStreamSupported) {
exports.ReadableStream = ReadableStream;
} else {
exports.ReadableStream =
require('../../external/streams/streams-lib').ReadableStream;
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('IMAGE_DECODERS')) {
class DummyReadableStream {
constructor() {
throw new Error('The current image decoders are synchronous, ' +
'hence `ReadableStream` shouldn\'t need to be ' +
'polyfilled for the IMAGE_DECODERS build target.');
}
}
exports.ReadableStream = DummyReadableStream;
} else {
exports.ReadableStream =
require('../../external/streams/streams-lib').ReadableStream;
}
}