Browse Source

Only trigger warning bar on certain unsupported features.

Brendan Dahl 11 years ago
parent
commit
2228343f77
  1. 10
      src/core/evaluator.js
  2. 8
      src/core/fonts.js
  3. 6
      src/core/image.js
  4. 15
      src/core/worker.js
  5. 4
      src/display/canvas.js
  6. 8
      src/shared/annotation.js
  7. 4
      src/shared/colorspace.js
  8. 4
      src/shared/function.js
  9. 8
      src/shared/pattern.js
  10. 62
      src/shared/util.js
  11. 15
      web/viewer.js

10
src/core/evaluator.js

@ -19,8 +19,9 @@
info, isArray, isCmd, isDict, isEOF, isName, isNum, info, isArray, isCmd, isDict, isEOF, isName, isNum,
isStream, isString, JpegStream, Lexer, Metrics, Name, Parser, isStream, isString, JpegStream, Lexer, Metrics, Name, Parser,
Pattern, PDFImage, PDFJS, serifFonts, stdFontMap, symbolsFonts, Pattern, PDFImage, PDFJS, serifFonts, stdFontMap, symbolsFonts,
TilingPattern, TODO, warn, Util, Promise, TilingPattern, warn, Util, Promise, UnsupportedManager,
RefSetCache, isRef, TextRenderingMode, CMapFactory, OPS */ RefSetCache, isRef, TextRenderingMode, CMapFactory, OPS,
UNSUPPORTED_FEATURES */
'use strict'; 'use strict';
@ -407,9 +408,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
gStateObj.push([key, value]); gStateObj.push([key, value]);
break; break;
case 'SMask': case 'SMask':
// We support the default so don't trigger the TODO. // We support the default so don't trigger a warning bar.
if (!isName(value) || value.name != 'None') if (!isName(value) || value.name != 'None')
TODO('graphic state operator ' + key); UnsupportedManager.notify(UNSUPPORTED_FEATURES.smask);
break; break;
// Only generate info log messages for the following since // Only generate info log messages for the following since
// they are unlikey to have a big impact on the rendering. // they are unlikey to have a big impact on the rendering.
@ -499,6 +500,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
try { try {
translated = this.translateFont(font, xref); translated = this.translateFont(font, xref);
} catch (e) { } catch (e) {
UnsupportedManager.notify(UNSUPPORTED_FEATURES.font);
translated = new ErrorFont(e instanceof Error ? e.message : e); translated = new ErrorFont(e instanceof Error ? e.message : e);
} }
font.translated = translated; font.translated = translated;

8
src/core/fonts.js

@ -17,7 +17,7 @@
/* globals assert, bytesToString, CIDToUnicodeMaps, error, ExpertCharset, /* globals assert, bytesToString, CIDToUnicodeMaps, error, ExpertCharset,
ExpertSubsetCharset, FileReaderSync, GlyphsUnicode, ExpertSubsetCharset, FileReaderSync, GlyphsUnicode,
info, isArray, isNum, ISOAdobeCharset, Stream, info, isArray, isNum, ISOAdobeCharset, Stream,
stringToBytes, TextDecoder, TODO, warn, Lexer, Util, stringToBytes, TextDecoder, warn, Lexer, Util,
FONT_IDENTITY_MATRIX, FontRendererFactory, shadow, isString */ FONT_IDENTITY_MATRIX, FontRendererFactory, shadow, isString */
'use strict'; 'use strict';
@ -495,7 +495,7 @@ function sjis83pvToUnicode(str) {
// TODO: 83pv has incompatible mappings in ed40..ee9c range. // TODO: 83pv has incompatible mappings in ed40..ee9c range.
return decodeBytes(bytes, 'shift_jis', true); return decodeBytes(bytes, 'shift_jis', true);
} catch (e) { } catch (e) {
TODO('Unsupported 83pv character found'); warn('Unsupported 83pv character found');
// Just retry without checking errors for now. // Just retry without checking errors for now.
return decodeBytes(bytes, 'shift_jis'); return decodeBytes(bytes, 'shift_jis');
} }
@ -507,7 +507,7 @@ function sjis90pvToUnicode(str) {
// TODO: 90pv has incompatible mappings in 8740..879c and eb41..ee9c. // TODO: 90pv has incompatible mappings in 8740..879c and eb41..ee9c.
return decodeBytes(bytes, 'shift_jis', true); return decodeBytes(bytes, 'shift_jis', true);
} catch (e) { } catch (e) {
TODO('Unsupported 90pv character found'); warn('Unsupported 90pv character found');
// Just retry without checking errors for now. // Just retry without checking errors for now.
return decodeBytes(bytes, 'shift_jis'); return decodeBytes(bytes, 'shift_jis');
} }
@ -4339,7 +4339,7 @@ var Font = (function FontClosure() {
var cidEncoding = properties.cidEncoding; var cidEncoding = properties.cidEncoding;
if (properties.toUnicode) { if (properties.toUnicode) {
if (cidEncoding && cidEncoding.indexOf('Identity-') !== 0) { if (cidEncoding && cidEncoding.indexOf('Identity-') !== 0) {
TODO('Need to create a reverse mapping from \'ToUnicode\' CMap'); warn('Need to create a reverse mapping from \'ToUnicode\' CMap');
} }
return; // 'ToUnicode' CMap will be used return; // 'ToUnicode' CMap will be used
} }

6
src/core/image.js

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
/* globals ColorSpace, error, isArray, isStream, JpegStream, Name, Promise, /* globals ColorSpace, error, isArray, isStream, JpegStream, Name, Promise,
Stream, TODO, warn */ Stream, warn */
'use strict'; 'use strict';
@ -54,7 +54,7 @@ var PDFImage = (function PDFImageClosure() {
if (image.getParams) { if (image.getParams) {
// JPX/JPEG2000 streams directly contain bits per component // JPX/JPEG2000 streams directly contain bits per component
// and color space mode information. // and color space mode information.
TODO('get params from actual stream'); warn('get params from actual stream');
// var bits = ... // var bits = ...
// var colorspace = ... // var colorspace = ...
} }
@ -87,7 +87,7 @@ var PDFImage = (function PDFImageClosure() {
if (!this.imageMask) { if (!this.imageMask) {
var colorSpace = dict.get('ColorSpace', 'CS'); var colorSpace = dict.get('ColorSpace', 'CS');
if (!colorSpace) { if (!colorSpace) {
TODO('JPX images (which don"t require color spaces'); warn('JPX images (which don"t require color spaces');
colorSpace = new Name('DeviceRGB'); colorSpace = new Name('DeviceRGB');
} }
this.colorSpace = ColorSpace.parse(colorSpace, xref, res); this.colorSpace = ColorSpace.parse(colorSpace, xref, res);

15
src/core/worker.js

@ -429,15 +429,12 @@ var workerConsole = {
if (typeof window === 'undefined') { if (typeof window === 'undefined') {
globalScope.console = workerConsole; globalScope.console = workerConsole;
// Add a logger so we can pass warnings on to the main thread, errors will // Listen for unsupported features so we can pass them on to the main thread.
// throw an exception which will be forwarded on automatically. PDFJS.UnsupportedManager.listen(function (msg) {
PDFJS.LogManager.addLogger({ globalScope.postMessage({
warn: function(msg) { action: '_unsupported_feature',
globalScope.postMessage({ data: msg
action: '_warn', });
data: msg
});
}
}); });
var handler = new MessageHandler('worker_processor', this); var handler = new MessageHandler('worker_processor', this);

4
src/display/canvas.js

@ -16,7 +16,7 @@
*/ */
/* globals ColorSpace, DeviceCmykCS, DeviceGrayCS, DeviceRgbCS, error, /* globals ColorSpace, DeviceCmykCS, DeviceGrayCS, DeviceRgbCS, error,
FONT_IDENTITY_MATRIX, IDENTITY_MATRIX, ImageData, isArray, isNum, FONT_IDENTITY_MATRIX, IDENTITY_MATRIX, ImageData, isArray, isNum,
Pattern, TilingPattern, TODO, Util, warn, assert, info, Pattern, TilingPattern, Util, warn, assert, info,
TextRenderingMode, OPS */ TextRenderingMode, OPS */
'use strict'; 'use strict';
@ -1460,7 +1460,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// TODO knockout - supposedly possible with the clever use of compositing // TODO knockout - supposedly possible with the clever use of compositing
// modes. // modes.
if (group.knockout) { if (group.knockout) {
TODO('Support knockout groups.'); warn('Knockout groups not supported.');
} }
var currentTransform = currentCtx.mozCurrentTransform; var currentTransform = currentCtx.mozCurrentTransform;

8
src/shared/annotation.js

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* globals Util, isDict, isName, stringToPDFString, TODO, Dict, Stream, /* globals Util, isDict, isName, stringToPDFString, warn, Dict, Stream,
stringToBytes, PDFJS, isWorker, assert, NotImplementedException, stringToBytes, PDFJS, isWorker, assert, NotImplementedException,
Promise, isArray, ObjectLoader, isValidUrl, OperatorList, OPS */ Promise, isArray, ObjectLoader, isValidUrl, OperatorList, OPS */
@ -266,7 +266,7 @@ var Annotation = (function AnnotationClosure() {
if (annotation.isViewable()) { if (annotation.isViewable()) {
return annotation; return annotation;
} else { } else {
TODO('unimplemented annotation type: ' + subtype); warn('unimplemented annotation type: ' + subtype);
} }
}; };
@ -358,7 +358,7 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
Util.inherit(WidgetAnnotation, Annotation, { Util.inherit(WidgetAnnotation, Annotation, {
isViewable: function WidgetAnnotation_isViewable() { isViewable: function WidgetAnnotation_isViewable() {
if (this.data.fieldType === 'Sig') { if (this.data.fieldType === 'Sig') {
TODO('unimplemented annotation type: Widget signature'); warn('unimplemented annotation type: Widget signature');
return false; return false;
} }
@ -643,7 +643,7 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
} else if (linkType === 'Named') { } else if (linkType === 'Named') {
data.action = action.get('N').name; data.action = action.get('N').name;
} else { } else {
TODO('unrecognized link type: ' + linkType); warn('unrecognized link type: ' + linkType);
} }
} else if (dict.has('Dest')) { } else if (dict.has('Dest')) {
// simple destination link // simple destination link

4
src/shared/colorspace.js

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
/* globals error, info, isArray, isDict, isName, isStream, isString, /* globals error, info, isArray, isDict, isName, isStream, isString,
PDFFunction, warn, shadow, TODO */ PDFFunction, warn, shadow */
'use strict'; 'use strict';
@ -671,7 +671,7 @@ var CalGrayCS = (function CalGrayCSClosure() {
} }
if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
TODO(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB + warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB +
', ZB: ' + this.ZB + ', only default values are supported.'); ', ZB: ' + this.ZB + ', only default values are supported.');
} }

4
src/shared/function.js

@ -1,6 +1,5 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* globals EOF, error, isArray, isBool, Lexer, TODO */
/* Copyright 2012 Mozilla Foundation /* Copyright 2012 Mozilla Foundation
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -15,6 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* globals EOF, error, isArray, isBool, Lexer, info */
'use strict'; 'use strict';
@ -122,7 +122,7 @@ var PDFFunction = (function PDFFunctionClosure() {
if (order !== 1) { if (order !== 1) {
// No description how cubic spline interpolation works in PDF32000:2008 // No description how cubic spline interpolation works in PDF32000:2008
// As in poppler, ignoring order, linear interpolation may work as good // As in poppler, ignoring order, linear interpolation may work as good
TODO('No support for cubic spline interpolation: ' + order); info('No support for cubic spline interpolation: ' + order);
} }
var encode = dict.get('Encode'); var encode = dict.get('Encode');

8
src/shared/pattern.js

@ -15,8 +15,8 @@
* limitations under the License. * limitations under the License.
*/ */
/* globals CanvasGraphics, ColorSpace, DeviceRgbCS, error, /* globals CanvasGraphics, ColorSpace, DeviceRgbCS, error,
info, isArray, isPDFFunction, isStream, PDFFunction, TODO, Util, info, isArray, isPDFFunction, isStream, PDFFunction, Util,
warn, CachedCanvases */ warn, CachedCanvases, UnsupportedManager, UNSUPPORTED_FEATURES */
'use strict'; 'use strict';
@ -55,7 +55,7 @@ var Pattern = (function PatternClosure() {
// Both radial and axial shadings are handled by RadialAxial shading. // Both radial and axial shadings are handled by RadialAxial shading.
return new Shadings.RadialAxial(dict, matrix, xref, res); return new Shadings.RadialAxial(dict, matrix, xref, res);
default: default:
TODO('Unsupported shading type: ' + type); UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
return new Shadings.Dummy(); return new Shadings.Dummy();
} }
}; };
@ -315,7 +315,7 @@ var TilingPattern = (function TilingPatternClosure() {
var commonObjs = this.commonObjs; var commonObjs = this.commonObjs;
var ctx = this.ctx; var ctx = this.ctx;
TODO('TilingType: ' + tilingType); info('TilingType: ' + tilingType);
var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3]; var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];

62
src/shared/util.js

@ -156,21 +156,19 @@ var log = (function() {
} }
})(); })();
// A notice for devs that will not trigger the fallback UI. These are good // A notice for devs. These are good for things that are helpful to devs, such
// for things that are helpful to devs, such as warning that Workers were // as warning that Workers were disabled, which is important to devs but not
// disabled, which is important to devs but not end users. // end users.
function info(msg) { function info(msg) {
if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) { if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) {
log('Info: ' + msg); log('Info: ' + msg);
PDFJS.LogManager.notify('info', msg);
} }
} }
// Non-fatal warnings that should trigger the fallback UI. // Non-fatal warnings.
function warn(msg) { function warn(msg) {
if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) { if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) {
log('Warning: ' + msg); log('Warning: ' + msg);
PDFJS.LogManager.notify('warn', msg);
} }
} }
@ -188,15 +186,10 @@ function error(msg) {
log('Error: ' + msg); log('Error: ' + msg);
} }
log(backtrace()); log(backtrace());
PDFJS.LogManager.notify('error', msg); UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
throw new Error(msg); throw new Error(msg);
} }
// Missing features that should trigger the fallback UI.
function TODO(what) {
warn('TODO: ' + what);
}
function backtrace() { function backtrace() {
try { try {
throw new Error(); throw new Error();
@ -210,6 +203,31 @@ function assert(cond, msg) {
error(msg); error(msg);
} }
var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
unknown: 'unknown',
forms: 'forms',
javaScript: 'javaScript',
smask: 'smask',
shadingPattern: 'shadingPattern',
font: 'font'
};
var UnsupportedManager = PDFJS.UnsupportedManager =
(function UnsupportedManagerClosure() {
var listeners = [];
return {
listen: function (cb) {
listeners.push(cb);
},
notify: function (featureId) {
warn('Unsupported feature "' + featureId + '"');
for (var i = 0, ii = listeners.length; i < ii; i++) {
listeners[i](featureId);
}
}
};
})();
// Combines two URLs. The baseUrl shall be absolute URL. If the url is an // Combines two URLs. The baseUrl shall be absolute URL. If the url is an
// absolute URL, it will be returned as is. // absolute URL, it will be returned as is.
function combineUrl(baseUrl, url) { function combineUrl(baseUrl, url) {
@ -263,22 +281,6 @@ function assertWellFormed(cond, msg) {
error(msg); error(msg);
} }
var LogManager = PDFJS.LogManager = (function LogManagerClosure() {
var loggers = [];
return {
addLogger: function logManager_addLogger(logger) {
loggers.push(logger);
},
notify: function(type, message) {
for (var i = 0, ii = loggers.length; i < ii; i++) {
var logger = loggers[i];
if (logger[type])
logger[type](message);
}
}
};
})();
function shadow(obj, prop, value) { function shadow(obj, prop, value) {
Object.defineProperty(obj, prop, { value: value, Object.defineProperty(obj, prop, { value: value,
enumerable: true, enumerable: true,
@ -1152,8 +1154,8 @@ function MessageHandler(name, comObj) {
log.apply(null, data); log.apply(null, data);
}]; }];
} }
ah['_warn'] = [function ah_Warn(data) { ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
warn(data); UnsupportedManager.notify(data);
}]; }];
comObj.onmessage = function messageHandlerComObjOnMessage(event) { comObj.onmessage = function messageHandlerComObjOnMessage(event) {

15
web/viewer.js

@ -599,7 +599,7 @@ var PDFView = {
).then(null, noData); ).then(null, noData);
}, },
fallback: function pdfViewFallback() { fallback: function pdfViewFallback(featureId) {
//#if !(FIREFOX || MOZCENTRAL) //#if !(FIREFOX || MOZCENTRAL)
// return; // return;
//#else //#else
@ -935,7 +935,7 @@ var PDFView = {
pdfDocument.getJavaScript().then(function(javaScript) { pdfDocument.getJavaScript().then(function(javaScript) {
if (javaScript.length) { if (javaScript.length) {
console.warn('Warning: JavaScript is not supported'); console.warn('Warning: JavaScript is not supported');
PDFView.fallback(); PDFView.fallback(PDFJS.UNSUPPORTED_FEATURES.javaScript);
} }
// Hack to support auto printing. // Hack to support auto printing.
var regex = /\bprint\s*\(/g; var regex = /\bprint\s*\(/g;
@ -1000,7 +1000,7 @@ var PDFView = {
if (info.IsAcroFormPresent) { if (info.IsAcroFormPresent) {
console.warn('Warning: AcroForm/XFA is not supported'); console.warn('Warning: AcroForm/XFA is not supported');
PDFView.fallback(); PDFView.fallback(PDFJS.UNSUPPORTED_FEATURES.forms);
} }
//#if (FIREFOX || MOZCENTRAL) //#if (FIREFOX || MOZCENTRAL)
@ -1661,13 +1661,8 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
document.getElementById('viewFind').classList.add('hidden'); document.getElementById('viewFind').classList.add('hidden');
} }
// Listen for warnings to trigger the fallback UI. Errors should be caught // Listen for unsuporrted features to trigger the fallback UI.
// and call PDFView.error() so we don't need to listen for those. PDFJS.UnsupportedManager.listen(PDFView.fallback.bind(PDFView));
PDFJS.LogManager.addLogger({
warn: function() {
PDFView.fallback();
}
});
// Suppress context menus for some controls // Suppress context menus for some controls
document.getElementById('scaleSelect').oncontextmenu = noContextMenuHandler; document.getElementById('scaleSelect').oncontextmenu = noContextMenuHandler;

Loading…
Cancel
Save