Adds thread abort capabilities.
This commit is contained in:
parent
59c13b32aa
commit
58c3ea0820
@ -281,7 +281,7 @@ var Annotation = (function AnnotationClosure() {
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
getOperatorList: function Annotation_getOperatorList(evaluator) {
|
getOperatorList: function Annotation_getOperatorList(evaluator, task) {
|
||||||
|
|
||||||
if (!this.appearance) {
|
if (!this.appearance) {
|
||||||
return Promise.resolve(new OperatorList());
|
return Promise.resolve(new OperatorList());
|
||||||
@ -308,7 +308,8 @@ var Annotation = (function AnnotationClosure() {
|
|||||||
return resourcesPromise.then(function(resources) {
|
return resourcesPromise.then(function(resources) {
|
||||||
var opList = new OperatorList();
|
var opList = new OperatorList();
|
||||||
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
|
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
|
||||||
return evaluator.getOperatorList(self.appearance, resources, opList).
|
return evaluator.getOperatorList(self.appearance, task,
|
||||||
|
resources, opList).
|
||||||
then(function () {
|
then(function () {
|
||||||
opList.addOp(OPS.endAnnotation, []);
|
opList.addOp(OPS.endAnnotation, []);
|
||||||
self.appearance.reset();
|
self.appearance.reset();
|
||||||
@ -319,7 +320,7 @@ var Annotation = (function AnnotationClosure() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
|
Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
|
||||||
annotations, opList, pdfManager, partialEvaluator, intent) {
|
annotations, opList, pdfManager, partialEvaluator, task, intent) {
|
||||||
|
|
||||||
function reject(e) {
|
function reject(e) {
|
||||||
annotationsReadyCapability.reject(e);
|
annotationsReadyCapability.reject(e);
|
||||||
@ -332,7 +333,7 @@ var Annotation = (function AnnotationClosure() {
|
|||||||
if (intent === 'display' && annotations[i].isViewable() ||
|
if (intent === 'display' && annotations[i].isViewable() ||
|
||||||
intent === 'print' && annotations[i].isPrintable()) {
|
intent === 'print' && annotations[i].isPrintable()) {
|
||||||
annotationPromises.push(
|
annotationPromises.push(
|
||||||
annotations[i].getOperatorList(partialEvaluator));
|
annotations[i].getOperatorList(partialEvaluator, task));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Promise.all(annotationPromises).then(function(datas) {
|
Promise.all(annotationPromises).then(function(datas) {
|
||||||
@ -564,9 +565,10 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
|
Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
|
||||||
getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
|
getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator,
|
||||||
|
task) {
|
||||||
if (this.appearance) {
|
if (this.appearance) {
|
||||||
return Annotation.prototype.getOperatorList.call(this, evaluator);
|
return Annotation.prototype.getOperatorList.call(this, evaluator, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
var opList = new OperatorList();
|
var opList = new OperatorList();
|
||||||
@ -579,7 +581,8 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var stream = new Stream(stringToBytes(data.defaultAppearance));
|
var stream = new Stream(stringToBytes(data.defaultAppearance));
|
||||||
return evaluator.getOperatorList(stream, this.fieldResources, opList).
|
return evaluator.getOperatorList(stream, task,
|
||||||
|
this.fieldResources, opList).
|
||||||
then(function () {
|
then(function () {
|
||||||
return opList;
|
return opList;
|
||||||
});
|
});
|
||||||
|
@ -161,7 +161,7 @@ var Page = (function PageClosure() {
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
getOperatorList: function Page_getOperatorList(handler, intent) {
|
getOperatorList: function Page_getOperatorList(handler, task, intent) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var pdfManager = this.pdfManager;
|
var pdfManager = this.pdfManager;
|
||||||
@ -194,8 +194,8 @@ var Page = (function PageClosure() {
|
|||||||
pageIndex: self.pageIndex,
|
pageIndex: self.pageIndex,
|
||||||
intent: intent
|
intent: intent
|
||||||
});
|
});
|
||||||
return partialEvaluator.getOperatorList(contentStream, self.resources,
|
return partialEvaluator.getOperatorList(contentStream, task,
|
||||||
opList).then(function () {
|
self.resources, opList).then(function () {
|
||||||
return opList;
|
return opList;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -212,7 +212,7 @@ var Page = (function PageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var annotationsReadyPromise = Annotation.appendToOperatorList(
|
var annotationsReadyPromise = Annotation.appendToOperatorList(
|
||||||
annotations, pageOpList, pdfManager, partialEvaluator, intent);
|
annotations, pageOpList, pdfManager, partialEvaluator, task, intent);
|
||||||
return annotationsReadyPromise.then(function () {
|
return annotationsReadyPromise.then(function () {
|
||||||
pageOpList.flush(true);
|
pageOpList.flush(true);
|
||||||
return pageOpList;
|
return pageOpList;
|
||||||
@ -220,7 +220,7 @@ var Page = (function PageClosure() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
extractTextContent: function Page_extractTextContent() {
|
extractTextContent: function Page_extractTextContent(task) {
|
||||||
var handler = {
|
var handler = {
|
||||||
on: function nullHandlerOn() {},
|
on: function nullHandlerOn() {},
|
||||||
send: function nullHandlerSend() {}
|
send: function nullHandlerSend() {}
|
||||||
@ -249,6 +249,7 @@ var Page = (function PageClosure() {
|
|||||||
self.fontCache);
|
self.fontCache);
|
||||||
|
|
||||||
return partialEvaluator.getTextContent(contentStream,
|
return partialEvaluator.getTextContent(contentStream,
|
||||||
|
task,
|
||||||
self.resources);
|
self.resources);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -125,6 +125,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
|
buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
|
||||||
xobj, smask,
|
xobj, smask,
|
||||||
operatorList,
|
operatorList,
|
||||||
|
task,
|
||||||
initialState) {
|
initialState) {
|
||||||
var matrix = xobj.dict.getArray('Matrix');
|
var matrix = xobj.dict.getArray('Matrix');
|
||||||
var bbox = xobj.dict.getArray('BBox');
|
var bbox = xobj.dict.getArray('BBox');
|
||||||
@ -157,7 +158,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
|
|
||||||
operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]);
|
operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]);
|
||||||
|
|
||||||
return this.getOperatorList(xobj,
|
return this.getOperatorList(xobj, task,
|
||||||
(xobj.dict.get('Resources') || resources), operatorList, initialState).
|
(xobj.dict.get('Resources') || resources), operatorList, initialState).
|
||||||
then(function () {
|
then(function () {
|
||||||
operatorList.addOp(OPS.paintFormXObjectEnd, []);
|
operatorList.addOp(OPS.paintFormXObjectEnd, []);
|
||||||
@ -269,7 +270,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleSMask: function PartialEvaluator_handleSmask(smask, resources,
|
handleSMask: function PartialEvaluator_handleSmask(smask, resources,
|
||||||
operatorList,
|
operatorList, task,
|
||||||
stateManager) {
|
stateManager) {
|
||||||
var smaskContent = smask.get('G');
|
var smaskContent = smask.get('G');
|
||||||
var smaskOptions = {
|
var smaskOptions = {
|
||||||
@ -277,13 +278,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
backdrop: smask.get('BC')
|
backdrop: smask.get('BC')
|
||||||
};
|
};
|
||||||
return this.buildFormXObject(resources, smaskContent, smaskOptions,
|
return this.buildFormXObject(resources, smaskContent, smaskOptions,
|
||||||
operatorList, stateManager.state.clone());
|
operatorList, task, stateManager.state.clone());
|
||||||
},
|
},
|
||||||
|
|
||||||
handleTilingType:
|
handleTilingType:
|
||||||
function PartialEvaluator_handleTilingType(fn, args, resources,
|
function PartialEvaluator_handleTilingType(fn, args, resources,
|
||||||
pattern, patternDict,
|
pattern, patternDict,
|
||||||
operatorList) {
|
operatorList, task) {
|
||||||
// Create an IR of the pattern code.
|
// Create an IR of the pattern code.
|
||||||
var tilingOpList = new OperatorList();
|
var tilingOpList = new OperatorList();
|
||||||
// Merge the available resources, to prevent issues when the patternDict
|
// Merge the available resources, to prevent issues when the patternDict
|
||||||
@ -291,8 +292,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
var resourcesArray = [patternDict.get('Resources'), resources];
|
var resourcesArray = [patternDict.get('Resources'), resources];
|
||||||
var patternResources = Dict.merge(this.xref, resourcesArray);
|
var patternResources = Dict.merge(this.xref, resourcesArray);
|
||||||
|
|
||||||
return this.getOperatorList(pattern, patternResources, tilingOpList).then(
|
return this.getOperatorList(pattern, task, patternResources,
|
||||||
function () {
|
tilingOpList).then(function () {
|
||||||
// Add the dependencies to the parent operator list so they are
|
// Add the dependencies to the parent operator list so they are
|
||||||
// resolved before sub operator list is executed synchronously.
|
// resolved before sub operator list is executed synchronously.
|
||||||
operatorList.addDependencies(tilingOpList.dependencies);
|
operatorList.addDependencies(tilingOpList.dependencies);
|
||||||
@ -305,7 +306,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
|
|
||||||
handleSetFont:
|
handleSetFont:
|
||||||
function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef,
|
function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef,
|
||||||
operatorList, state) {
|
operatorList, task, state) {
|
||||||
// TODO(mack): Not needed?
|
// TODO(mack): Not needed?
|
||||||
var fontName;
|
var fontName;
|
||||||
if (fontArgs) {
|
if (fontArgs) {
|
||||||
@ -319,8 +320,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
if (!translated.font.isType3Font) {
|
if (!translated.font.isType3Font) {
|
||||||
return translated;
|
return translated;
|
||||||
}
|
}
|
||||||
return translated.loadType3Data(self, resources, operatorList).then(
|
return translated.loadType3Data(self, resources, operatorList, task).
|
||||||
function () {
|
then(function () {
|
||||||
return translated;
|
return translated;
|
||||||
});
|
});
|
||||||
}).then(function (translated) {
|
}).then(function (translated) {
|
||||||
@ -367,8 +368,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
setGState: function PartialEvaluator_setGState(resources, gState,
|
setGState: function PartialEvaluator_setGState(resources, gState,
|
||||||
operatorList, xref,
|
operatorList, task,
|
||||||
stateManager) {
|
xref, stateManager) {
|
||||||
// This array holds the converted/processed state data.
|
// This array holds the converted/processed state data.
|
||||||
var gStateObj = [];
|
var gStateObj = [];
|
||||||
var gStateMap = gState.map;
|
var gStateMap = gState.map;
|
||||||
@ -392,8 +393,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
break;
|
break;
|
||||||
case 'Font':
|
case 'Font':
|
||||||
promise = promise.then(function () {
|
promise = promise.then(function () {
|
||||||
return self.handleSetFont(resources, null, value[0],
|
return self.handleSetFont(resources, null, value[0], operatorList,
|
||||||
operatorList, stateManager.state).
|
task, stateManager.state).
|
||||||
then(function (loadedName) {
|
then(function (loadedName) {
|
||||||
operatorList.addDependency(loadedName);
|
operatorList.addDependency(loadedName);
|
||||||
gStateObj.push([key, [loadedName, value[1]]]);
|
gStateObj.push([key, [loadedName, value[1]]]);
|
||||||
@ -412,7 +413,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
if (isDict(dict)) {
|
if (isDict(dict)) {
|
||||||
promise = promise.then(function () {
|
promise = promise.then(function () {
|
||||||
return self.handleSMask(dict, resources, operatorList,
|
return self.handleSMask(dict, resources, operatorList,
|
||||||
stateManager);
|
task, stateManager);
|
||||||
});
|
});
|
||||||
gStateObj.push([key, true]);
|
gStateObj.push([key, true]);
|
||||||
} else {
|
} else {
|
||||||
@ -593,7 +594,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args,
|
handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args,
|
||||||
cs, patterns, resources, xref) {
|
cs, patterns, resources, task, xref) {
|
||||||
// compile tiling patterns
|
// compile tiling patterns
|
||||||
var patternName = args[args.length - 1];
|
var patternName = args[args.length - 1];
|
||||||
// SCN/scn applies patterns along with normal colors
|
// SCN/scn applies patterns along with normal colors
|
||||||
@ -606,7 +607,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
if (typeNum === TILING_PATTERN) {
|
if (typeNum === TILING_PATTERN) {
|
||||||
var color = cs.base ? cs.base.getRgb(args, 0) : null;
|
var color = cs.base ? cs.base.getRgb(args, 0) : null;
|
||||||
return this.handleTilingType(fn, color, resources, pattern,
|
return this.handleTilingType(fn, color, resources, pattern,
|
||||||
dict, operatorList);
|
dict, operatorList, task);
|
||||||
} else if (typeNum === SHADING_PATTERN) {
|
} else if (typeNum === SHADING_PATTERN) {
|
||||||
var shading = dict.get('Shading');
|
var shading = dict.get('Shading');
|
||||||
var matrix = dict.get('Matrix');
|
var matrix = dict.get('Matrix');
|
||||||
@ -623,6 +624,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getOperatorList: function PartialEvaluator_getOperatorList(stream,
|
getOperatorList: function PartialEvaluator_getOperatorList(stream,
|
||||||
|
task,
|
||||||
resources,
|
resources,
|
||||||
operatorList,
|
operatorList,
|
||||||
initialState) {
|
initialState) {
|
||||||
@ -641,6 +643,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
var timeSlotManager = new TimeSlotManager();
|
var timeSlotManager = new TimeSlotManager();
|
||||||
|
|
||||||
return new Promise(function next(resolve, reject) {
|
return new Promise(function next(resolve, reject) {
|
||||||
|
task.ensureNotTerminated();
|
||||||
timeSlotManager.reset();
|
timeSlotManager.reset();
|
||||||
var stop, operation = {}, i, ii, cs;
|
var stop, operation = {}, i, ii, cs;
|
||||||
while (!(stop = timeSlotManager.check())) {
|
while (!(stop = timeSlotManager.check())) {
|
||||||
@ -683,7 +686,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
if (type.name === 'Form') {
|
if (type.name === 'Form') {
|
||||||
stateManager.save();
|
stateManager.save();
|
||||||
return self.buildFormXObject(resources, xobj, null,
|
return self.buildFormXObject(resources, xobj, null,
|
||||||
operatorList,
|
operatorList, task,
|
||||||
stateManager.state.clone()).
|
stateManager.state.clone()).
|
||||||
then(function () {
|
then(function () {
|
||||||
stateManager.restore();
|
stateManager.restore();
|
||||||
@ -707,8 +710,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
case OPS.setFont:
|
case OPS.setFont:
|
||||||
var fontSize = args[1];
|
var fontSize = args[1];
|
||||||
// eagerly collect all fonts
|
// eagerly collect all fonts
|
||||||
return self.handleSetFont(resources, args, null,
|
return self.handleSetFont(resources, args, null, operatorList,
|
||||||
operatorList, stateManager.state).
|
task, stateManager.state).
|
||||||
then(function (loadedName) {
|
then(function (loadedName) {
|
||||||
operatorList.addDependency(loadedName);
|
operatorList.addDependency(loadedName);
|
||||||
operatorList.addOp(OPS.setFont, [loadedName, fontSize]);
|
operatorList.addOp(OPS.setFont, [loadedName, fontSize]);
|
||||||
@ -814,7 +817,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
cs = stateManager.state.fillColorSpace;
|
cs = stateManager.state.fillColorSpace;
|
||||||
if (cs.name === 'Pattern') {
|
if (cs.name === 'Pattern') {
|
||||||
return self.handleColorN(operatorList, OPS.setFillColorN,
|
return self.handleColorN(operatorList, OPS.setFillColorN,
|
||||||
args, cs, patterns, resources, xref).then(function() {
|
args, cs, patterns, resources, task, xref).then(function() {
|
||||||
next(resolve, reject);
|
next(resolve, reject);
|
||||||
}, reject);
|
}, reject);
|
||||||
}
|
}
|
||||||
@ -825,7 +828,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
cs = stateManager.state.strokeColorSpace;
|
cs = stateManager.state.strokeColorSpace;
|
||||||
if (cs.name === 'Pattern') {
|
if (cs.name === 'Pattern') {
|
||||||
return self.handleColorN(operatorList, OPS.setStrokeColorN,
|
return self.handleColorN(operatorList, OPS.setStrokeColorN,
|
||||||
args, cs, patterns, resources, xref).then(function() {
|
args, cs, patterns, resources, task, xref).then(function() {
|
||||||
next(resolve, reject);
|
next(resolve, reject);
|
||||||
}, reject);
|
}, reject);
|
||||||
}
|
}
|
||||||
@ -859,8 +862,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var gState = extGState.get(dictName.name);
|
var gState = extGState.get(dictName.name);
|
||||||
return self.setGState(resources, gState, operatorList, xref,
|
return self.setGState(resources, gState, operatorList, task,
|
||||||
stateManager).then(function() {
|
xref, stateManager).then(function() {
|
||||||
next(resolve, reject);
|
next(resolve, reject);
|
||||||
}, reject);
|
}, reject);
|
||||||
case OPS.moveTo:
|
case OPS.moveTo:
|
||||||
@ -898,7 +901,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
if (stop) {
|
if (stop) {
|
||||||
deferred.then(function () {
|
deferred.then(function () {
|
||||||
next(resolve, reject);
|
next(resolve, reject);
|
||||||
});
|
}, reject);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Some PDFs don't close all restores inside object/form.
|
// Some PDFs don't close all restores inside object/form.
|
||||||
@ -910,7 +913,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getTextContent: function PartialEvaluator_getTextContent(stream, resources,
|
getTextContent: function PartialEvaluator_getTextContent(stream, task,
|
||||||
|
resources,
|
||||||
stateManager) {
|
stateManager) {
|
||||||
|
|
||||||
stateManager = (stateManager || new StateManager(new TextState()));
|
stateManager = (stateManager || new StateManager(new TextState()));
|
||||||
@ -1088,6 +1092,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
var timeSlotManager = new TimeSlotManager();
|
var timeSlotManager = new TimeSlotManager();
|
||||||
|
|
||||||
return new Promise(function next(resolve, reject) {
|
return new Promise(function next(resolve, reject) {
|
||||||
|
task.ensureNotTerminated();
|
||||||
timeSlotManager.reset();
|
timeSlotManager.reset();
|
||||||
var stop, operation = {}, args = [];
|
var stop, operation = {}, args = [];
|
||||||
while (!(stop = timeSlotManager.check())) {
|
while (!(stop = timeSlotManager.check())) {
|
||||||
@ -1243,7 +1248,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
stateManager.transform(matrix);
|
stateManager.transform(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.getTextContent(xobj,
|
return self.getTextContent(xobj, task,
|
||||||
xobj.dict.get('Resources') || resources, stateManager).
|
xobj.dict.get('Resources') || resources, stateManager).
|
||||||
then(function (formTextContent) {
|
then(function (formTextContent) {
|
||||||
Util.appendToArray(bidiTexts, formTextContent.items);
|
Util.appendToArray(bidiTexts, formTextContent.items);
|
||||||
@ -1283,7 +1288,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
if (stop) {
|
if (stop) {
|
||||||
deferred.then(function () {
|
deferred.then(function () {
|
||||||
next(resolve, reject);
|
next(resolve, reject);
|
||||||
});
|
}, reject);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resolve(textContent);
|
resolve(textContent);
|
||||||
@ -1848,7 +1853,7 @@ var TranslatedFont = (function TranslatedFontClosure() {
|
|||||||
]);
|
]);
|
||||||
this.sent = true;
|
this.sent = true;
|
||||||
},
|
},
|
||||||
loadType3Data: function (evaluator, resources, parentOperatorList) {
|
loadType3Data: function (evaluator, resources, parentOperatorList, task) {
|
||||||
assert(this.font.isType3Font);
|
assert(this.font.isType3Font);
|
||||||
|
|
||||||
if (this.type3Loaded) {
|
if (this.type3Loaded) {
|
||||||
@ -1865,7 +1870,7 @@ var TranslatedFont = (function TranslatedFontClosure() {
|
|||||||
loadCharProcsPromise = loadCharProcsPromise.then(function (key) {
|
loadCharProcsPromise = loadCharProcsPromise.then(function (key) {
|
||||||
var glyphStream = charProcs[key];
|
var glyphStream = charProcs[key];
|
||||||
var operatorList = new OperatorList();
|
var operatorList = new OperatorList();
|
||||||
return evaluator.getOperatorList(glyphStream, fontResources,
|
return evaluator.getOperatorList(glyphStream, task, fontResources,
|
||||||
operatorList).then(function () {
|
operatorList).then(function () {
|
||||||
charProcOperatorList[key] = operatorList.getIR();
|
charProcOperatorList[key] = operatorList.getIR();
|
||||||
|
|
||||||
|
@ -22,11 +22,42 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var WorkerTask = (function WorkerTaskClosure() {
|
||||||
|
function WorkerTask(name) {
|
||||||
|
this.name = name;
|
||||||
|
this.terminated = false;
|
||||||
|
this._capability = createPromiseCapability();
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerTask.prototype = {
|
||||||
|
get finished() {
|
||||||
|
return this._capability.promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
finish: function () {
|
||||||
|
this._capability.resolve();
|
||||||
|
},
|
||||||
|
|
||||||
|
terminate: function () {
|
||||||
|
this.terminated = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
ensureNotTerminated: function () {
|
||||||
|
if (this.terminated) {
|
||||||
|
throw new Error('Worker task was terminated');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return WorkerTask;
|
||||||
|
})();
|
||||||
|
|
||||||
var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||||
setup: function wphSetup(handler) {
|
setup: function wphSetup(handler) {
|
||||||
var pdfManager;
|
var pdfManager;
|
||||||
var terminated = false;
|
var terminated = false;
|
||||||
var cancelXHRs = null;
|
var cancelXHRs = null;
|
||||||
|
var WorkerTasks = [];
|
||||||
|
|
||||||
function ensureNotTerminated() {
|
function ensureNotTerminated() {
|
||||||
if (terminated) {
|
if (terminated) {
|
||||||
@ -34,6 +65,16 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startWorkerTask(task) {
|
||||||
|
WorkerTasks.push(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishWorkerTask(task) {
|
||||||
|
task.finish();
|
||||||
|
var i = WorkerTasks.indexOf(task);
|
||||||
|
WorkerTasks.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
function loadDocument(recoveryMode) {
|
function loadDocument(recoveryMode) {
|
||||||
var loadDocumentCapability = createPromiseCapability();
|
var loadDocumentCapability = createPromiseCapability();
|
||||||
|
|
||||||
@ -413,17 +454,25 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
|
handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
|
||||||
pdfManager.getPage(data.pageIndex).then(function(page) {
|
var pageIndex = data.pageIndex;
|
||||||
|
pdfManager.getPage(pageIndex).then(function(page) {
|
||||||
|
var task = new WorkerTask('RenderPageRequest: page ' + pageIndex);
|
||||||
|
startWorkerTask(task);
|
||||||
|
|
||||||
var pageNum = data.pageIndex + 1;
|
var pageNum = pageIndex + 1;
|
||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
// Pre compile the pdf page and fetch the fonts/images.
|
// Pre compile the pdf page and fetch the fonts/images.
|
||||||
page.getOperatorList(handler, data.intent).then(function(operatorList) {
|
page.getOperatorList(handler, task, data.intent).then(
|
||||||
|
function(operatorList) {
|
||||||
|
finishWorkerTask(task);
|
||||||
|
|
||||||
info('page=' + pageNum + ' - getOperatorList: time=' +
|
info('page=' + pageNum + ' - getOperatorList: time=' +
|
||||||
(Date.now() - start) + 'ms, len=' + operatorList.fnArray.length);
|
(Date.now() - start) + 'ms, len=' + operatorList.fnArray.length);
|
||||||
|
|
||||||
}, function(e) {
|
}, function(e) {
|
||||||
|
finishWorkerTask(task);
|
||||||
|
if (task.terminated) {
|
||||||
|
return; // ignoring errors from the terminated thread
|
||||||
|
}
|
||||||
|
|
||||||
var minimumStackMessage =
|
var minimumStackMessage =
|
||||||
'worker.js: while trying to getPage() and getOperatorList()';
|
'worker.js: while trying to getPage() and getOperatorList()';
|
||||||
@ -458,13 +507,23 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
|||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
handler.on('GetTextContent', function wphExtractText(data) {
|
handler.on('GetTextContent', function wphExtractText(data) {
|
||||||
return pdfManager.getPage(data.pageIndex).then(function(page) {
|
var pageIndex = data.pageIndex;
|
||||||
var pageNum = data.pageIndex + 1;
|
return pdfManager.getPage(pageIndex).then(function(page) {
|
||||||
|
var task = new WorkerTask('GetTextContent: page ' + pageIndex);
|
||||||
|
startWorkerTask(task);
|
||||||
|
var pageNum = pageIndex + 1;
|
||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
return page.extractTextContent().then(function(textContent) {
|
return page.extractTextContent(task).then(function(textContent) {
|
||||||
|
finishWorkerTask(task);
|
||||||
info('text indexing: page=' + pageNum + ' - time=' +
|
info('text indexing: page=' + pageNum + ' - time=' +
|
||||||
(Date.now() - start) + 'ms');
|
(Date.now() - start) + 'ms');
|
||||||
return textContent;
|
return textContent;
|
||||||
|
}, function (reason) {
|
||||||
|
finishWorkerTask(task);
|
||||||
|
if (task.terminated) {
|
||||||
|
return; // ignoring errors from the terminated thread
|
||||||
|
}
|
||||||
|
throw reason;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -482,6 +541,14 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
|||||||
if (cancelXHRs) {
|
if (cancelXHRs) {
|
||||||
cancelXHRs();
|
cancelXHRs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var waitOn = [];
|
||||||
|
WorkerTasks.forEach(function (task) {
|
||||||
|
waitOn.push(task.finished);
|
||||||
|
task.terminate();
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(waitOn).then(function () {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -883,15 +883,20 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
|||||||
this.destroyed = true;
|
this.destroyed = true;
|
||||||
this.transport.pageCache[this.pageIndex] = null;
|
this.transport.pageCache[this.pageIndex] = null;
|
||||||
|
|
||||||
|
var waitOn = [];
|
||||||
Object.keys(this.intentStates).forEach(function(intent) {
|
Object.keys(this.intentStates).forEach(function(intent) {
|
||||||
var intentState = this.intentStates[intent];
|
var intentState = this.intentStates[intent];
|
||||||
intentState.renderTasks.forEach(function(renderTask) {
|
intentState.renderTasks.forEach(function(renderTask) {
|
||||||
|
var renderCompleted = renderTask.capability.promise.
|
||||||
|
catch(function () {}); // ignoring failures
|
||||||
|
waitOn.push(renderCompleted);
|
||||||
renderTask.cancel();
|
renderTask.cancel();
|
||||||
});
|
});
|
||||||
}, this);
|
}, this);
|
||||||
this.objs.clear();
|
this.objs.clear();
|
||||||
this.annotationsPromise = null;
|
this.annotationsPromise = null;
|
||||||
this.pendingCleanup = false;
|
this.pendingCleanup = false;
|
||||||
|
return Promise.all(waitOn);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1054,15 +1059,21 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||||||
this.destroyed = true;
|
this.destroyed = true;
|
||||||
this.destroyCapability = createPromiseCapability();
|
this.destroyCapability = createPromiseCapability();
|
||||||
|
|
||||||
|
var waitOn = [];
|
||||||
|
// We need to wait for all renderings to be completed, e.g.
|
||||||
|
// timeout/rAF can take a long time.
|
||||||
this.pageCache.forEach(function (page) {
|
this.pageCache.forEach(function (page) {
|
||||||
if (page) {
|
if (page) {
|
||||||
page._destroy();
|
waitOn.push(page._destroy());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.pageCache = [];
|
this.pageCache = [];
|
||||||
this.pagePromises = [];
|
this.pagePromises = [];
|
||||||
var self = this;
|
var self = this;
|
||||||
this.messageHandler.sendWithPromise('Terminate', null).then(function () {
|
// We also need to wait for the worker to finish its long running tasks.
|
||||||
|
var terminated = this.messageHandler.sendWithPromise('Terminate', null);
|
||||||
|
waitOn.push(terminated);
|
||||||
|
Promise.all(waitOn).then(function () {
|
||||||
FontLoader.clear();
|
FontLoader.clear();
|
||||||
if (self.worker) {
|
if (self.worker) {
|
||||||
self.worker.terminate();
|
self.worker.terminate();
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/* -*- 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 expect, it, describe, PartialEvaluator, StringStream, OPS,
|
/* globals expect, it, describe, PartialEvaluator, StringStream, OPS,
|
||||||
OperatorList, waitsFor, runs, Dict, Name, Stream */
|
OperatorList, waitsFor, runs, Dict, Name, Stream, WorkerTask */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe('evaluator', function() {
|
describe('evaluator', function() {
|
||||||
function XrefMock(queue) {
|
function XrefMock(queue) {
|
||||||
this.queue = queue;
|
this.queue = queue || [];
|
||||||
}
|
}
|
||||||
XrefMock.prototype = {
|
XrefMock.prototype = {
|
||||||
fetchIfRef: function() {
|
fetchIfRef: function() {
|
||||||
@ -35,7 +35,9 @@ describe('evaluator', function() {
|
|||||||
var done = false;
|
var done = false;
|
||||||
runs(function () {
|
runs(function () {
|
||||||
var result = new OperatorList();
|
var result = new OperatorList();
|
||||||
evaluator.getOperatorList(stream, resources, result).then(function () {
|
var task = new WorkerTask('OperatorListCheck');
|
||||||
|
evaluator.getOperatorList(stream, task, resources, result).then(
|
||||||
|
function () {
|
||||||
check(result);
|
check(result);
|
||||||
done = true;
|
done = true;
|
||||||
});
|
});
|
||||||
@ -259,4 +261,48 @@ describe('evaluator', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('thread control', function() {
|
||||||
|
it('should abort operator list parsing', function () {
|
||||||
|
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
||||||
|
new XrefMock(), new HandlerMock(),
|
||||||
|
'prefix');
|
||||||
|
var stream = new StringStream('qqQQ');
|
||||||
|
var resources = new ResourcesMock();
|
||||||
|
var done = false;
|
||||||
|
runs(function () {
|
||||||
|
var result = new OperatorList();
|
||||||
|
var task = new WorkerTask('OperatorListAbort');
|
||||||
|
task.terminate();
|
||||||
|
evaluator.getOperatorList(stream, task, resources, result).catch(
|
||||||
|
function () {
|
||||||
|
done = true;
|
||||||
|
expect(!!result.fnArray && !!result.argsArray).toEqual(true);
|
||||||
|
expect(result.fnArray.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
waitsFor(function () {
|
||||||
|
return done;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should abort text parsing parsing', function () {
|
||||||
|
var resources = new ResourcesMock();
|
||||||
|
var evaluator = new PartialEvaluator(new PdfManagerMock(),
|
||||||
|
new XrefMock(), new HandlerMock(),
|
||||||
|
'prefix');
|
||||||
|
var stream = new StringStream('qqQQ');
|
||||||
|
var done = false;
|
||||||
|
runs(function () {
|
||||||
|
var task = new WorkerTask('TextContentAbort');
|
||||||
|
task.terminate();
|
||||||
|
evaluator.getTextContent(stream, task, resources).catch(
|
||||||
|
function () {
|
||||||
|
done = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
waitsFor(function () {
|
||||||
|
return done;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user