added ranges to operators
Some checks failed
CI / Test (20) (push) Has been cancelled
CI / Test (22) (push) Has been cancelled
CI / Test (23) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Lint / Lint (lts/*) (push) Has been cancelled
Types tests / Test (lts/*) (push) Has been cancelled

This commit is contained in:
Kilian Schuettler 2025-03-16 19:08:20 +01:00
parent 88a38b6c5b
commit 2305c6416e
9 changed files with 248 additions and 83 deletions

View File

@ -24,8 +24,9 @@ const loadingTask = getDocument({
try {
const pdfDocument = await loadingTask.promise;
console.log("# PDF document loaded.");
const table = await pdfDocument.getStreamAsString("/Page2/Contents/0/Data");
console.log(table);
const page = await pdfDocument.getPage(1);
const opList = await page.getOperatorList();
console.log(opList);
} catch (e) {
console.error(e);
}

View File

@ -1,9 +1,13 @@
import { EvaluatorPreprocessor } from "../../src/core/evaluator.js";
import {
getImageAsBlob,
getPrim,
getPrimitive,
getPrimTree,
getStreamAsString,
} from "../../src/core/obj_walker.js";
import { Lexer, Parser } from "../../src/core/parser.js";
import { EOF } from "../../src/core/primitives.js";
import fs from "fs";
import { PDFDocument } from "../../src/core/document.js";
import { Stream } from "../../src/core/stream.js";
@ -32,12 +36,58 @@ fs.readFile(filePath, (err, data) => {
}
});
function bytesToString(bytes) {
let string = "";
for (let i = 0; i < bytes.length; i++) {
string += String.fromCharCode(bytes[i]);
}
return string;
}
async function parse(doc) {
const path = "/Page2/Contents/2";
let [stream] = await getPrimitive(path, doc);
const lexer = new Lexer(stream);
const parser = new Parser({ lexer, xref: doc.xref, trackRanges: true });
const objs = [];
let [obj, start, end] = parser.getObjWithRange();
while (obj !== EOF) {
if (obj.cmd) {
objs.push([obj.cmd, start, end]);
} else {
objs.push([obj, start, end]);
}
[obj, start, end] = parser.getObjWithRange();
}
[stream] = await getPrimitive(path, doc);
const bytes = stream.getBytes();
const classes = new Set();
for (const o of objs) {
console.log(o[0].constructor.name);
classes.add(o[0].constructor.name);
const lexemmeBytes = bytes.slice(o[1], o[2]);
console.log(bytesToString(lexemmeBytes));
}
console.log("unique classes", classes);
[stream] = await getPrimitive(path, doc);
const preprocessor = new EvaluatorPreprocessor(stream, doc.xref);
const operation = {};
operation.args = null;
while (preprocessor.read(operation)) {
const args = operation.args;
const fn = operation.fn;
const range = operation.range;
const op = bytesToString(bytes.slice(range[0], range[1]));
console.log(args, fn);
console.log(`${range[0]}------------------------------------`);
console.log(op);
console.log(`${range[1]}------------------------------------`);
}
// console.time("xref");
// let table = await retrieveXref(doc);
// console.timeEnd("xref");
// console.time("get prim");
// const prim = await getPrim("/Page2/Resources/XObject/Im0/Length", doc);
// const prim = await getPrim("/Trailer/Root/Names/Dests/Names/1", doc);
// console.timeEnd("get prim");
// console.log(prim);
// const request = {
@ -55,20 +105,40 @@ async function parse(doc) {
// const tree = await getPrimTree([request], doc);
// console.timeEnd("get tree");
// logTree(tree);
console.time("string");
const string = await getStreamAsString("/Page2/Contents/0/Data", doc);
console.timeEnd("string");
console.log(string);
// const handler = { send: undefined };
// console.time("string");
// const string = await getStreamAsString("/Page2/Contents/0/Data", doc);
// console.timeEnd("string");
// console.log(string);
// console.time("image");
// // const image = await getStreamAsImage("/Page2/Contents/2/Data", doc);
// const image = await getImageAsBlob(
// const blob = await getImageAsBlob(
// "/Page2/Resources/XObject/Im0/Data",
// doc,
// handler
// doc
// );
// console.timeEnd("image");
// console.log(image);
// console.log(blob);
// saveBlobToFile(blob, "image.png");
}
async function saveBlobToFile(blob, imagePath) {
const buffer = await blobToBuffer(blob);
fs.writeFile(imagePath, buffer, err => {
if (err) {
console.error("Error saving file:", err);
} else {
console.log("File saved successfully!");
}
});
}
function blobToBuffer(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(Buffer.from(reader.result));
reader.onerror = reject;
reader.readAsArrayBuffer(blob);
});
}
function logTree(tree) {

View File

@ -177,11 +177,17 @@ function normalizeBlendMode(value, parsingArray = false) {
return "source-over";
}
function addLocallyCachedImageOps(opList, data) {
function addLocallyCachedImageOps(opList, data, range) {
if (data.objId) {
opList.addDependency(data.objId);
}
opList.addImageOps(data.fn, data.args, data.optionalContent, data.hasMask);
opList.addImageOps(
data.fn,
data.args,
range,
data.optionalContent,
data.hasMask
);
if (data.fn === OPS.paintImageMaskXObject && data.args[0]?.count > 0) {
data.args[0].count++;
@ -455,7 +461,8 @@ class PartialEvaluator {
operatorList,
task,
initialState,
localColorSpaceCache
localColorSpaceCache,
range = null
) {
const dict = xobj.dict;
const matrix = lookupMatrix(dict.getArray("Matrix"), null);
@ -469,7 +476,11 @@ class PartialEvaluator {
);
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
operatorList.addOp(
OPS.beginMarkedContentProps,
["OC", optionalContent],
range
);
}
const group = dict.get("Group");
if (group) {
@ -511,14 +522,14 @@ class PartialEvaluator {
smask.backdrop = colorSpace.getRgb(smask.backdrop, 0);
}
operatorList.addOp(OPS.beginGroup, [groupOptions]);
operatorList.addOp(OPS.beginGroup, [groupOptions], range);
}
// If it's a group, a new canvas will be created that is the size of the
// bounding box and translated to the correct position so we don't need to
// apply the bounding box to it.
const args = group ? [matrix, null] : [matrix, bbox];
operatorList.addOp(OPS.paintFormXObjectBegin, args);
operatorList.addOp(OPS.paintFormXObjectBegin, args, range);
await this.getOperatorList({
stream: xobj,
@ -527,14 +538,14 @@ class PartialEvaluator {
operatorList,
initialState,
});
operatorList.addOp(OPS.paintFormXObjectEnd, []);
operatorList.addOp(OPS.paintFormXObjectEnd, [], range);
if (group) {
operatorList.addOp(OPS.endGroup, [groupOptions]);
operatorList.addOp(OPS.endGroup, [groupOptions], range);
}
if (optionalContent !== undefined) {
operatorList.addOp(OPS.endMarkedContent, []);
operatorList.addOp(OPS.endMarkedContent, [], range);
}
}
@ -569,6 +580,7 @@ class PartialEvaluator {
cacheKey,
localImageCache,
localColorSpaceCache,
range,
}) {
const dict = image.dict;
const imageRef = dict.objId;
@ -627,6 +639,7 @@ class PartialEvaluator {
operatorList.addImageOps(
OPS.paintImageMaskXObject,
args,
range,
optionalContent
);
@ -899,7 +912,8 @@ class PartialEvaluator {
operatorList,
task,
stateManager,
localColorSpaceCache
localColorSpaceCache,
range
) {
const smaskContent = smask.get("G");
const smaskOptions = {
@ -929,7 +943,8 @@ class PartialEvaluator {
operatorList,
task,
stateManager.state.clone(),
localColorSpaceCache
localColorSpaceCache,
range
);
}
@ -1013,7 +1028,7 @@ class PartialEvaluator {
// Add the dependencies to the parent operator list so they are
// resolved before the sub operator list is executed synchronously.
operatorList.addDependencies(tilingOpList.dependencies);
operatorList.addOp(fn, tilingPatternIR);
operatorList.addOp(fn, tilingPatternIR, range);
if (patternDict.objId) {
localTilingPatternCache.set(/* name = */ null, patternDict.objId, {
@ -1124,6 +1139,7 @@ class PartialEvaluator {
stateManager,
localGStateCache,
localColorSpaceCache,
range,
}) {
const gStateRef = gState.objId;
let isSimpleGState = true;
@ -1180,7 +1196,8 @@ class PartialEvaluator {
operatorList,
task,
stateManager,
localColorSpaceCache
localColorSpaceCache,
range
)
);
gStateObj.push([key, true]);
@ -1218,7 +1235,7 @@ class PartialEvaluator {
await promise;
if (gStateObj.length > 0) {
operatorList.addOp(OPS.setGState, [gStateObj]);
operatorList.addOp(OPS.setGState, [gStateObj], range);
}
if (isSimpleGState) {
@ -1387,7 +1404,7 @@ class PartialEvaluator {
return promise;
}
buildPath(operatorList, fn, args, parsingText = false) {
buildPath(operatorList, fn, args, parsingText = false, range = null) {
const lastIndex = operatorList.length - 1;
if (!args) {
args = [];
@ -1405,7 +1422,7 @@ class PartialEvaluator {
// *extremely* rare that shouldn't really matter much in practice.
if (parsingText) {
warn(`Encountered path operator "${fn}" inside of a text object.`);
operatorList.addOp(OPS.save, null);
operatorList.addOp(OPS.save, null, range);
}
let minMax;
@ -1428,10 +1445,10 @@ class PartialEvaluator {
minMax = [Infinity, Infinity, -Infinity, -Infinity];
break;
}
operatorList.addOp(OPS.constructPath, [[fn], args, minMax]);
operatorList.addOp(OPS.constructPath, [[fn], args, minMax], range);
if (parsingText) {
operatorList.addOp(OPS.restore, null);
operatorList.addOp(OPS.restore, null, range);
}
} else {
const opArgs = operatorList.argsArray[lastIndex];
@ -1439,6 +1456,9 @@ class PartialEvaluator {
opArgs[1].push(...args);
const minMax = opArgs[2];
const opRange = operatorList.rangeArray[lastIndex];
opRange[1] = range[1];
// Compute min/max in the worker instead of the main thread.
// If the current matrix (when drawing) is a scaling one
// then min/max can be easily computed in using those values.
@ -1543,7 +1563,8 @@ class PartialEvaluator {
task,
localColorSpaceCache,
localTilingPatternCache,
localShadingPatternCache
localShadingPatternCache,
range
) {
// compile tiling patterns
const patternName = args.pop();
@ -1562,7 +1583,7 @@ class PartialEvaluator {
localTilingPattern.dict,
color
);
operatorList.addOp(fn, tilingPatternIR);
operatorList.addOp(fn, tilingPatternIR, range);
return undefined;
} catch {
// Handle any errors during normal TilingPattern parsing.
@ -1596,7 +1617,7 @@ class PartialEvaluator {
});
if (objId) {
const matrix = lookupMatrix(dict.getArray("Matrix"), null);
operatorList.addOp(fn, ["Shading", objId, matrix]);
operatorList.addOp(fn, ["Shading", objId, matrix], range);
}
return undefined;
}
@ -1771,6 +1792,7 @@ class PartialEvaluator {
}
let args = operation.args;
let fn = operation.fn;
const range = operation.range;
switch (fn | 0) {
case OPS.paintXObject:
@ -1781,7 +1803,7 @@ class PartialEvaluator {
if (isValidName) {
const localImage = localImageCache.getByName(name);
if (localImage) {
addLocallyCachedImageOps(operatorList, localImage);
addLocallyCachedImageOps(operatorList, localImage, range);
args = null;
continue;
}
@ -1859,6 +1881,7 @@ class PartialEvaluator {
cacheKey: name,
localImageCache,
localColorSpaceCache,
range,
})
.then(resolveXObject, rejectXObject);
return;
@ -1900,7 +1923,11 @@ class PartialEvaluator {
)
.then(function (loadedName) {
operatorList.addDependency(loadedName);
operatorList.addOp(OPS.setFont, [loadedName, fontSize]);
operatorList.addOp(
OPS.setFont,
[loadedName, fontSize],
range
);
})
);
return;
@ -1929,6 +1956,7 @@ class PartialEvaluator {
cacheKey,
localImageCache,
localColorSpaceCache,
range,
})
);
return;
@ -1961,7 +1989,7 @@ class PartialEvaluator {
self.ensureStateFont(stateManager.state);
continue;
}
operatorList.addOp(OPS.nextLine);
operatorList.addOp(OPS.nextLine, null, range);
args[0] = self.handleText(args[0], stateManager.state);
fn = OPS.showText;
break;
@ -1970,9 +1998,9 @@ class PartialEvaluator {
self.ensureStateFont(stateManager.state);
continue;
}
operatorList.addOp(OPS.nextLine);
operatorList.addOp(OPS.setWordSpacing, [args.shift()]);
operatorList.addOp(OPS.setCharSpacing, [args.shift()]);
operatorList.addOp(OPS.nextLine, null, range);
operatorList.addOp(OPS.setWordSpacing, [args.shift()], range);
operatorList.addOp(OPS.setCharSpacing, [args.shift()], range);
args[0] = self.handleText(args[0], stateManager.state);
fn = OPS.showText;
break;
@ -2092,7 +2120,8 @@ class PartialEvaluator {
task,
localColorSpaceCache,
localTilingPatternCache,
localShadingPatternCache
localShadingPatternCache,
range
)
);
return;
@ -2124,7 +2153,8 @@ class PartialEvaluator {
task,
localColorSpaceCache,
localTilingPatternCache,
localShadingPatternCache
localShadingPatternCache,
range
)
);
return;
@ -2175,7 +2205,7 @@ class PartialEvaluator {
const localGStateObj = localGStateCache.getByName(name);
if (localGStateObj) {
if (localGStateObj.length > 0) {
operatorList.addOp(OPS.setGState, [localGStateObj]);
operatorList.addOp(OPS.setGState, [localGStateObj], range);
}
args = null;
continue;
@ -2211,6 +2241,7 @@ class PartialEvaluator {
stateManager,
localGStateCache,
localColorSpaceCache,
range,
})
.then(resolveGState, rejectGState);
}).catch(function (reason) {
@ -2232,7 +2263,7 @@ class PartialEvaluator {
case OPS.curveTo3:
case OPS.closePath:
case OPS.rectangle:
self.buildPath(operatorList, fn, args, parsingText);
self.buildPath(operatorList, fn, args, parsingText, range);
continue;
case OPS.markPoint:
case OPS.markPointProps:
@ -2248,7 +2279,11 @@ class PartialEvaluator {
case OPS.beginMarkedContentProps:
if (!(args[0] instanceof Name)) {
warn(`Expected name for beginMarkedContentProps arg0=${args[0]}`);
operatorList.addOp(OPS.beginMarkedContentProps, ["OC", null]);
operatorList.addOp(
OPS.beginMarkedContentProps,
["OC", null],
range
);
continue;
}
if (args[0].name === "OC") {
@ -2256,10 +2291,11 @@ class PartialEvaluator {
self
.parseMarkedContentProps(args[1], resources)
.then(data => {
operatorList.addOp(OPS.beginMarkedContentProps, [
"OC",
data,
]);
operatorList.addOp(
OPS.beginMarkedContentProps,
["OC", data],
range
);
})
.catch(reason => {
if (reason instanceof AbortException) {
@ -2269,10 +2305,11 @@ class PartialEvaluator {
warn(
`getOperatorList - ignoring beginMarkedContentProps: "${reason}".`
);
operatorList.addOp(OPS.beginMarkedContentProps, [
"OC",
null,
]);
operatorList.addOp(
OPS.beginMarkedContentProps,
["OC", null],
range
);
return;
}
throw reason;
@ -2305,7 +2342,7 @@ class PartialEvaluator {
}
}
}
operatorList.addOp(fn, args);
operatorList.addOp(fn, args, range);
}
if (stop) {
next(deferred);
@ -5101,6 +5138,7 @@ class EvaluatorPreprocessor {
// avoiding allocations where possible is worthwhile.
//
read(operation) {
const start = this.parser.getPosition();
let args = operation.args;
while (true) {
const obj = this.parser.getObj();
@ -5177,6 +5215,8 @@ class EvaluatorPreprocessor {
operation.fn = fn;
operation.args = args;
const end = this.parser.getPosition();
operation.range = [start, end];
return true;
}
if (obj === EOF) {

View File

@ -47,8 +47,7 @@ async function getImageAsBlob(path, doc) {
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
const imageData = await pdfImage.createImageData(true, false);
return new Blob([imageData.data], { type: "image/png" });
return pdfImage.createImageData(true, false);
}
async function getPrimitive(path, doc) {
@ -254,6 +253,8 @@ function toType(prim) {
return ["String", "-"];
} else if (isRef(prim)) {
return ["Reference", "-"];
} else if (prim === null) {
return ["Null", "-"];
}
throw new Error("Unknown prim");
}
@ -305,6 +306,8 @@ function primToString(prim) {
return prim;
} else if (isRef(prim)) {
return "XRef(" + prim.num + ", " + prim.gen + ")";
} else if (prim === null) {
return "Null";
}
throw new Error("Unknown prim");
}
@ -376,5 +379,6 @@ export {
getPrimTree,
getStreamAsString,
PrimitiveModel,
toType,
TreeViewModel,
};

View File

@ -477,9 +477,10 @@ class NullOptimizer {
_optimize() {}
push(fn, args) {
push(fn, args, range) {
this.queue.fnArray.push(fn);
this.queue.argsArray.push(args);
this.queue.rangeArray.push(range);
this._optimize();
}
@ -589,6 +590,7 @@ class OperatorList {
this._streamSink = streamSink;
this.fnArray = [];
this.argsArray = [];
this.rangeArray = [];
this.optimizer =
streamSink && !(intent & RenderingIntentFlag.OPLIST)
? new QueueOptimizer(this)
@ -620,8 +622,8 @@ class OperatorList {
return this._totalLength + this.length;
}
addOp(fn, args) {
this.optimizer.push(fn, args);
addOp(fn, args, range = null) {
this.optimizer.push(fn, args, range);
this.weight++;
if (this._streamSink) {
if (this.weight >= OperatorList.CHUNK_SIZE) {
@ -636,7 +638,7 @@ class OperatorList {
}
}
addImageOps(fn, args, optionalContent, hasMask = false) {
addImageOps(fn, args, range, optionalContent, hasMask = false) {
if (hasMask) {
this.addOp(OPS.save);
this.addOp(OPS.setGState, [[["SMask", false]]]);
@ -645,7 +647,7 @@ class OperatorList {
this.addOp(OPS.beginMarkedContentProps, ["OC", optionalContent]);
}
this.addOp(fn, args);
this.addOp(fn, args, range);
if (optionalContent !== undefined) {
this.addOp(OPS.endMarkedContent, []);
@ -678,7 +680,7 @@ class OperatorList {
this.dependencies.add(dependency);
}
for (let i = 0, ii = opList.length; i < ii; i++) {
this.addOp(opList.fnArray[i], opList.argsArray[i]);
this.addOp(opList.fnArray[i], opList.argsArray[i], opList.rangeArray[i]);
}
}
@ -686,6 +688,7 @@ class OperatorList {
return {
fnArray: this.fnArray,
argsArray: this.argsArray,
rangeArray: this.rangeArray,
length: this.length,
};
}
@ -717,6 +720,7 @@ class OperatorList {
{
fnArray: this.fnArray,
argsArray: this.argsArray,
rangeArray: this.rangeArray,
lastChunk,
separateAnnots,
length,
@ -728,6 +732,7 @@ class OperatorList {
this.dependencies.clear();
this.fnArray.length = 0;
this.argsArray.length = 0;
this.rangeArray.length = 0;
this.weight = 0;
this.optimizer.reset();
}

View File

@ -59,26 +59,51 @@ function getInlineImageCacheKey(bytes) {
}
class Parser {
constructor({ lexer, xref, allowStreams = false, recoveryMode = false }) {
constructor({
lexer,
xref,
allowStreams = false,
recoveryMode = false,
trackRanges = true,
}) {
this.lexer = lexer;
this.xref = xref;
this.allowStreams = allowStreams;
this.recoveryMode = recoveryMode;
this.withRange = trackRanges;
this.imageCache = Object.create(null);
this._imageId = 0;
this.refill();
}
refill() {
this.buf1 = this.lexer.getObj();
this.buf2 = this.lexer.getObj();
if (this.withRange) {
const [buf1, start1, end1] = this.lexer.getObjWithRange();
const [buf2, start2, end2] = this.lexer.getObjWithRange();
this.buf1 = buf1;
this.range1 = [start1, end1];
this.buf2 = buf2;
this.range2 = [start2, end2];
} else {
this.buf1 = this.lexer.getObj();
this.buf2 = this.lexer.getObj();
}
}
shift() {
if (this.buf2 instanceof Cmd && this.buf2.cmd === "ID") {
this.buf1 = this.buf2;
this.buf2 = null;
if (this.withRange) {
this.range1 = this.range2;
this.range2 = null;
}
} else if (this.withRange) {
this.buf1 = this.buf2;
this.range1 = this.range2;
const [buf2, start2, end2] = this.lexer.getObjWithRange();
this.buf2 = buf2;
this.range2 = [start2, end2];
} else {
this.buf1 = this.buf2;
this.buf2 = this.lexer.getObj();
@ -99,6 +124,17 @@ class Parser {
}
}
getPosition() {
return this.range1 ? this.range1[0] : 0;
}
getObjWithRange(cipherTransform = null) {
const start = this.range1[0];
const obj = this.getObj(cipherTransform);
const end = this.range1[0];
return [obj, start, end];
}
getObj(cipherTransform = null) {
const buf1 = this.buf1;
this.shift();
@ -1204,6 +1240,14 @@ class Lexer {
return strBuf.join("");
}
getObjWithRange() {
// at the start of getObj() the stream has stepped beyond currentChar by one
const start = this.stream.pos - 1;
const obj = this.getObj();
const end = this.stream.pos;
return [obj, start, end];
}
getObj() {
// Skip whitespace and comments.
let comment = false;

View File

@ -1,8 +1,8 @@
import {Dict, Ref} from "./primitives.js";
import {BaseStream} from "./base_stream.js";
import { Ref } from "./primitives.js";
import { toType } from "./obj_walker.js";
async function retrieveXref(doc) {
let result = new XRefTable(doc.xref.entries.length);
const result = new XRefTable(doc.xref.entries.length);
for (let i = 0; i < doc.xref.entries.length; i++) {
result.entries.push(to_model(i, doc.xref.entries[i], doc.xref));
}
@ -13,13 +13,8 @@ function to_model(i, entry, xref) {
if (entry.free) {
return new XRefEntry("Free", i, entry.gen, entry.offset);
}
const fetched = xref.fetch(new Ref(i, entry.gen));
let type = "Unknown";
if (fetched instanceof Dict) {
type = "Dictionary";
} else if (fetched instanceof BaseStream) {
type = "Stream";
}
const fetched = xref.fetch(Ref.get(i, entry.gen));
const [type] = toType(fetched);
return new XRefEntry(type, i, entry.gen, entry.offset);
}
@ -39,4 +34,4 @@ class XRefEntry {
}
}
export { XRefEntry, XRefTable, retrieveXref };
export { retrieveXref, XRefEntry, XRefTable };

View File

@ -503,7 +503,7 @@ class WorkerMessageHandler {
return getPrimTree(request, pdfManager.pdfDocument);
});
handler.on("GetImageAsBlob", function (path) {
handler.on("GetImageData", function (path) {
return getImageAsBlob(path, pdfManager.pdfDocument);
});

View File

@ -1133,11 +1133,11 @@ class PDFDocumentProxy {
}
/**
* @returns {Promise<Blob>} A promise that is resolved to a blob representing
* the image as png.
* @returns {Promise<ImageData>} A promise that is resolved to ImageData.
* Throws an Error if the path does not lead to an image!
*/
getImageByPath(path) {
return this._transport.getImageAsBlob(path);
getImageDataByPath(path) {
return this._transport.getImageDataByPath(path);
}
/**
@ -1705,6 +1705,7 @@ class PDFPageProxy {
intentState.operatorList = {
fnArray: [],
argsArray: [],
rangeArray: [],
lastChunk: false,
separateAnnots: null,
};
@ -1882,6 +1883,11 @@ class PDFPageProxy {
for (let i = 0, ii = operatorListChunk.length; i < ii; i++) {
intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
if (intentState.operatorList.rangeArray) {
intentState.operatorList.rangeArray.push(
operatorListChunk.rangeArray[i]
);
}
}
intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots;
@ -2956,8 +2962,8 @@ class WorkerTransport {
return this.messageHandler.sendWithPromise("GetPrimTree", request);
}
getImageAsBlob(path) {
return this.messageHandler.sendWithPromise("GetImageAsBlob", path);
getImageDataByPath(path) {
return this.messageHandler.sendWithPromise("GetImageData", path);
}
getStreamAsString(path) {