PDInterpReaderImpl.mesa
Michael Plass, November 11, 1983 2:11 pm
DIRECTORY
Environment, Inline, PDInterpBasic, PDFileFormat, PDInterpBitmap, PDInterpReader, Space, Mopcodes, UnsafeStorage, PDInterpInput;
PDInterpReaderImpl: PROGRAM
IMPORTS Inline, PDInterpBitmap, Space, UnsafeStorage, PDInterpInput
EXPORTS PDInterpReader
~ BEGIN OPEN PDInterpReader;
bitsPerWord: NAT ~ Environment.bitsPerWord;
wordsPerPage: NAT ~ Environment.wordsPerPage;
scratchWords: INT ← 32000;
bufferSize: NAT = 256;
ColorTileFromLoad: PUBLIC PROC [handle: Handle, colorTileLoadAddress: INT, scratchPointer: LONG POINTER, scratchWords: INT] RETURNS [PDInterpBitmap.Tile] ~ {
private: Private ~ handle.private;
tile: LONG POINTER TO PDFileFormat.Tile ~ private.loadPointer + colorTileLoadAddress;
words: INT ~ Inline.LongMult[tile.sSize, (tile.fSize+(bitsPerWord-1))/bitsPerWord];
bitmap: PDInterpBitmap.BitmapDesc← PDInterpBitmap.Reshape[
tile + SIZE[PDFileFormat.Tile],
words,
[tile.sMin, tile.fMin, tile.sSize, tile.fSize]
];
RETURN [PDInterpBitmap.CreateTile[
rectangle: [tile.sMin, tile.fMin, tile.sSize, tile.fSize],
phase: tile.phase,
rasterPointer: tile + SIZE[PDFileFormat.Tile],
scratchPointer: scratchPointer,
scratchWords: scratchWords
]];
};
BlockTransfer: PROC [source: LONG POINTER, count: CARDINAL, dest: LONG POINTER]
~ MACHINE CODE {Mopcodes.zBLTL};
LongBlockTransfer: PROC [source: LONG POINTER, count: INT, dest: LONG POINTER] ~ {
WHILE count > LAST[CARDINAL] DO
BlockTransfer[source, LAST[CARDINAL], dest];
source ← source + LAST[CARDINAL];
dest ← dest + LAST[CARDINAL];
count ← count - LAST[CARDINAL];
ENDLOOP;
BlockTransfer[source, count, dest];
};
Private: TYPE ~ LONG POINTER TO PrivateRep;
PrivateRep: PUBLIC TYPE ~ RECORD [
loadSpace: Space.Handle ← Space.nullHandle,
loadPointer: LONG POINTER ← NIL,
loadWordsAllocated: INT ← 0,
bufferOriginPointer: LONG POINTER ← NIL,
bufferWordsAllocated: INT ← 0,
bufferWordPointer: LONG POINTER ← NIL,
bufferWordCount: INT ← 0
The buffer variables satisfy the invariants
(bufferWordPointer + i)^ = InputFileWord[handle.index+i], i IN [0..bufferWordCount)
handle.index+bufferWordCount <= inputFileSizeInWords
bufferWordPointer-bufferOriginPointer >= 0
bufferWordCount + (bufferWordPointer-bufferOriginPointer) <= bufferWordsAllocated
where InputFileWord[k] stands for the kth word of the input file.
];
zone: UNCOUNTED ZONE = UnsafeStorage.GetSystemUZone[];
Words: TYPE ~ RECORD [
SEQUENCE COMPUTED CARDINAL OF CARDINAL
];
Open: PUBLIC PROC [input: PDInterpInput.Handle] RETURNS [handle: Handle] ~ {
private: Private ← zone.NEW[PrivateRep];
handle ← zone.NEW[Rep ← [
herald: [0,0,invalid,0,0,0,0,0,0,0],
image: [0,FALSE,FALSE,FALSE,black,0,0,0,0],
bandNumber: 0,
sMinBand: 0,
sSizeBand: 0,
colorType: none,
colorTileLoadAddress: -1,
priority: 0,
loadPointer: NIL,
loadWords: 0,
private: private,
input: input,
index: 0,
page: 0,
pass: 0,
warningCount: 0
]];
{ENABLE
UNWIND => {
zone.FREE[@(handle.private)];
zone.FREE[@(handle)];
};
ReadHerald[handle];
AllocateSpace[handle];
};
};
AllocateSpace: PROC [handle: Handle] ~ {
private: Private ← handle.private;
loadPages: INT ← (handle.herald.maxLoadWord + (wordsPerPage-1))/wordsPerPage;
bufferWords: INT ← (Inline.LongMult[handle.herald.bandSSize, (handle.herald.imageFSize+bitsPerWord-1)/bitsPerWord]+100)*2;
bufferPages: INT ← (bufferWords + (wordsPerPage-1))/wordsPerPage;
private.loadSpace ← Space.Create[size: loadPages+bufferPages, parent: Space.virtualMemory];
Space.Map[private.loadSpace];
Space.CreateUniformSwapUnits[16, private.loadSpace];
private.loadPointer ← Space.LongPointer[private.loadSpace];
private.loadWordsAllocated ← loadPages*wordsPerPage;
private.bufferWordPointer ← private.bufferOriginPointer ← private.loadPointer + private.loadWordsAllocated;
private.bufferWordsAllocated ← bufferPages*wordsPerPage;
private.bufferWordCount ← 0;
};
FillBuffer: PROC [handle: Handle] RETURNS [wordsRemovedFromFront: INT]~ {
private: Private ← handle.private;
wordsRemovedFromFront ← (private.bufferWordPointer-private.bufferOriginPointer);
LongBlockTransfer[source: private.bufferWordPointer, count: private.bufferWordCount, dest: private.bufferOriginPointer];
private.bufferWordPointer ← private.bufferOriginPointer;
private.bufferWordCount ← private.bufferWordCount +
PDInterpInput.GetBlock[
handle.input,
private.bufferWordPointer + private.bufferWordCount,
handle.index + private.bufferWordCount,
private.bufferWordsAllocated - private.bufferWordCount
];
};
BlockDescription: TYPE ~ RECORD [pointer: LONG POINTER, words: CARDINAL];
ReadLocate: PROC [handle: Handle, words: INT]
RETURNS [blockDescription: BlockDescription] ~ {
The buffer storage may get re-used with the next ReadLocate or ReadBlock;
private: Private ← handle.private;
IF private.bufferWordCount < words THEN [] ← FillBuffer[handle];
blockDescription.pointer ← private.bufferWordPointer;
blockDescription.words ← MIN[private.bufferWordCount, words];
private.bufferWordPointer ← private.bufferWordPointer + blockDescription.words;
private.bufferWordCount ← private.bufferWordCount - blockDescription.words;
handle.index ← handle.index + blockDescription.words;
};
ReadBlock: PROC [handle: Handle, dest: LONG POINTER, words: CARDINAL] ~ {
private: Private ← handle.private;
IF private.bufferWordCount < words THEN [] ← FillBuffer[handle];
IF private.bufferWordCount < words THEN RaisePDError[handle, unexpectedEOF, 0];
BlockTransfer[source: private.bufferWordPointer, count: words, dest: dest];
private.bufferWordPointer ← private.bufferWordPointer + words;
private.bufferWordCount ← private.bufferWordCount - words;
handle.index ← handle.index + words;
};
ReadLongBlock: PROC [handle: Handle, dest: LONG POINTER, words: INT] ~ {
private: Private ← handle.private;
inBuffer: INTMIN[private.bufferWordCount, words];
LongBlockTransfer[source: private.bufferWordPointer, count: inBuffer, dest: dest];
private.bufferWordPointer ← private.bufferWordPointer + inBuffer;
private.bufferWordCount ← private.bufferWordCount - inBuffer;
handle.index ← handle.index + inBuffer;
dest ← dest + inBuffer;
words ← words - inBuffer;
IF words > 0 THEN {
IF private.bufferWordCount # 0 THEN ERROR;
IF words # PDInterpInput.GetBlock[handle.input, dest, handle.index, words] THEN {
RaisePDError[handle, unexpectedEOF, 0];
};
handle.index ← handle.index + words;
};
};
Close: PUBLIC PROC [handle: Handle] RETURNS [Handle ← NIL] ~ {
private: Private ← handle.private;
private.loadPointer ← NIL;
private.loadWordsAllocated ← 0;
IF private.loadSpace # Space.nullHandle THEN Space.Delete[private.loadSpace];
zone.FREE[@(handle.private)];
zone.FREE[@(handle)];
};
ReadHerald: PROC [handle: Handle] ~ {
herald: PDFileFormat.Herald;
IF PDInterpInput.GetBlock[handle.input, @herald, 0, SIZE[PDFileFormat.Herald]] # SIZE[PDFileFormat.Herald] THEN RaisePDError[handle, unexpectedEOF, 0]
ELSE handle.index ← SIZE[PDFileFormat.Herald];
IF herald.password # PDFileFormat.passwordValue THEN {
RaisePDError[handle, invalidPassword, SIZE[PDFileFormat.Herald]];
};
IF herald.version # PDFileFormat.versionValue THEN {
RaisePDWarning[handle, wrongFormatVersion, SIZE[PDFileFormat.Herald]];
};
IF NOT (herald.sResolution IN [10..10000])
OR NOT (herald.fResolution IN [10..10000]) THEN {
RaisePDWarning[handle, unreasonableResolution, SIZE[PDFileFormat.Herald]];
};
IF NOT (herald.bandSSize IN [8..32767]) THEN {
RaisePDWarning[handle, unreasonableBandSSize, SIZE[PDFileFormat.Herald]];
};
IF NOT (herald.imageSSize IN [80..32767])
OR NOT (herald.imageFSize IN [80..32767]) THEN {
RaisePDWarning[handle, unreasonableImageSize, SIZE[PDFileFormat.Herald]];
};
IF herald.maxLoadWord > 60000 THEN {
RaisePDWarning[handle, unreasonableLoadSize, SIZE[PDFileFormat.Herald]];
};
IF NOT (herald.copies IN [1..200]) THEN {
RaisePDWarning[handle, unreasonableNumberOfCopies, SIZE[PDFileFormat.Herald]];
};
handle.herald ← herald;
handle.sSizeBand ← herald.bandSSize;
};
CheckBB: PROC [handle: Handle, sMin, fMin, sSize, fSize: CARDINAL, errorWordCount: INT] ~ {
IF LONG[sMin] + sSize > handle.herald.imageSSize
OR LONG[fMin] + fSize > handle.herald.imageFSize
OR fMin < handle.image.fMinPage
OR fMin + fSize > handle.image.fMinPage + handle.image.fSizePage
THEN RaisePDError[handle, objectOutOfBounds, errorWordCount];
IF sMin + sSize <= handle.sMinBand
OR sMin >= handle.sMinBand+handle.sSizeBand THEN {
RaisePDWarning[handle, objectOutOfBand, errorWordCount];
};
};
Get: PUBLIC PROC [handle: Handle] RETURNS [CommandBuffer] ~ {
private: Private ← handle.private;
command: PDFileFormat.Command;
BadLoadReference: PROC [dataWords: INT] ~ {
RaisePDError[handle, badLoadReference, SIZE[PDFileFormat.Command]+dataWords];
};
ReadBlock[handle, @command, SIZE[PDFileFormat.Command]];
WITH command SELECT FROM
imagingCommand: PDFileFormat.Command.imaging => {
IF handle.colorType = none THEN {
RaisePDError[handle, missingStartImage, SIZE[PDFileFormat.Command]];
ERROR
};
SELECT imagingCommand.com FROM
maskSamplesRef => {
ans: CommandBuffer.maskSamples;
maskSamplesRef: PDFileFormat.MaskSamplesRef;
loadAddress: Environment.LongNumber;
samples: LONG POINTER TO PDFileFormat.SampleArray;
words: INT;
ReadBlock[handle, @maskSamplesRef, SIZE[PDFileFormat.MaskSamplesRef]];
loadAddress.highbits ← imagingCommand.addrHighBits;
loadAddress.lowbits ← maskSamplesRef.addrLowBits;
ans.loadAddress ← loadAddress.li;
IF ans.loadAddress < 0 OR ans.loadAddress + SIZE[PDFileFormat.SampleArray] > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskSamplesRef]];
samples ← private.loadPointer + loadAddress.li;
words ← Inline.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord];
IF ans.loadAddress + SIZE[PDFileFormat.SampleArray] + words > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskSamplesRef]];
CheckBB[handle, maskSamplesRef.sMin, maskSamplesRef.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamplesRef]];
ans.samples ← [sOrigin: maskSamplesRef.sMin, fOrigin: maskSamplesRef.fMin, sMin: 0, fMin: 0, sSize: samples.sSize, fSize: samples.fSize, pointer: samples+SIZE[PDFileFormat.SampleArray], rast: (samples.fSize+(bitsPerWord-1))/bitsPerWord, lines: samples.sSize];
RETURN [ans]
};
maskRunGroupRef => {
ans: CommandBuffer.maskRunGroup;
maskRunGroupRef: PDFileFormat.MaskRunGroupRef;
loadAddress: Environment.LongNumber;
runGroup: LONG POINTER TO PDFileFormat.RunGroup;
run: LONG POINTER TO PDFileFormat.Run;
s: CARDINAL ← 0;
runCount: CARDINAL ← 0;
words: INT ← 0;
maxRunCount: CARDINAL;
fSize: CARDINAL ← 0;
ReadBlock[handle, @maskRunGroupRef, SIZE[PDFileFormat.MaskRunGroupRef]];
loadAddress.highbits ← imagingCommand.addrHighBits;
loadAddress.lowbits ← maskRunGroupRef.addrLowBits;
ans.loadAddress ← loadAddress.li;
IF ans.loadAddress < 0 OR ans.loadAddress + SIZE[PDFileFormat.RunGroup] > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskRunGroupRef]];
runGroup ← private.loadPointer + loadAddress.li;
ans.pointer ← run ← private.loadPointer + loadAddress.li + SIZE[PDFileFormat.RunGroup];
maxRunCount ← MAX[(handle.loadWords-loadAddress.li-SIZE[PDFileFormat.RunGroup])/2-1, 0];
WHILE s < runGroup.sSize DO
IF run.fSize > fSize THEN fSize ← run.fSize;
IF run.lastRun THEN s ← s + 1;
run ← run + SIZE[PDFileFormat.Run];
IF (runCount ← runCount + 1) >= maxRunCount THEN BadLoadReference[SIZE[PDFileFormat.MaskRunGroupRef]];
ENDLOOP;
ans.runCount ← runCount;
CheckBB[handle, maskRunGroupRef.sMin, maskRunGroupRef.fMin, runGroup.sSize, fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRunGroupRef]];
ans.sMin ← maskRunGroupRef.sMin;
ans.fMin ← ans.fOffset ← maskRunGroupRef.fMin;
ans.sSize ← runGroup.sSize;
ans.fSize ← fSize;
RETURN [ans]
};
maskRectangle => {
ans: CommandBuffer.maskRectangle;
maskRectangle: PDFileFormat.MaskRectangle;
ReadBlock[handle, @maskRectangle, SIZE[PDFileFormat.MaskRectangle]];
CheckBB[handle, maskRectangle.sMin, maskRectangle.fMin, maskRectangle.sSize, maskRectangle.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRectangle]];
ans.sMin ← maskRectangle.sMin;
ans.fMin ← maskRectangle.fMin;
ans.sSize ← maskRectangle.sSize;
ans.fSize ← maskRectangle.fSize;
RETURN [ans]
};
maskTrapezoid => {
ans: CommandBuffer.maskTrapezoid;
maskTrapezoid: PDFileFormat.MaskTrapezoid;
fMin, fMax: INT;
ReadBlock[handle, @maskTrapezoid, SIZE[PDFileFormat.MaskTrapezoid]];
fMin ← MIN[maskTrapezoid.fMin, maskTrapezoid.fMinLast];
fMax ← MAX[LONG[maskTrapezoid.fMin] + maskTrapezoid.fSize, LONG[maskTrapezoid.fMinLast] + maskTrapezoid.fSizeLast];
CheckBB[handle, maskTrapezoid.sMin, fMin, maskTrapezoid.sSize, fMax-fMin, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskTrapezoid]];
ans.sMin ← maskTrapezoid.sMin;
ans.fMin ← maskTrapezoid.fMin;
ans.fMinLast ← maskTrapezoid.fMinLast;
ans.sSize ← maskTrapezoid.sSize;
ans.fSize ← maskTrapezoid.fSize;
ans.fSizeLast ← maskTrapezoid.fSizeLast;
RETURN [ans]
};
maskRunGroup => {
ans: CommandBuffer.maskRunGroup;
maskRunGroup: PDFileFormat.MaskRunGroup;
runGroup: PDFileFormat.RunGroup;
s: CARDINAL ← 0;
runCount: INT ← 0;
words: INT ← 0;
fMin: CARDINALLAST[CARDINAL];
fMax: CARDINALFIRST[CARDINAL];
run: LONG POINTER TO PDFileFormat.Run;
ReadBlock[handle, @maskRunGroup, SIZE[PDFileFormat.MaskRunGroup]];
ReadBlock[handle, @runGroup, SIZE[PDFileFormat.RunGroup]];
run ← private.bufferWordPointer;
WHILE s < runGroup.sSize DO
IF (runCount+1)*SIZE[PDFileFormat.Run] > private.bufferWordCount THEN {
run ← run - FillBuffer[handle];
IF (runCount+1)*SIZE[PDFileFormat.Run] > private.bufferWordCount THEN RaisePDError[handle, runGroupTooLong, SIZE[PDFileFormat.MaskRunGroup] + SIZE[PDFileFormat.RunGroup]];
};
IF run.fMin < fMin THEN fMin ← run.fMin;
IF LONG[run.fMin] + run.fSize > fMax THEN fMax ← LONG[run.fMin] + run.fSize;
IF run.lastRun THEN s ← s + 1;
runCount ← runCount + 1;
run ← run + SIZE[PDFileFormat.Run];
ENDLOOP;
ans.runCount ← runCount;
ans.loadAddress ← -1;
IF runCount = 0 THEN {
ans.pointer ← NIL;
RaisePDWarning[handle, emptyRunGroup, SIZE[PDFileFormat.MaskRunGroup]+SIZE[PDFileFormat.RunGroup]];
fMin ← fMax;
}
ELSE {
[[ans.pointer, ----]] ← ReadLocate[handle, runCount*SIZE[PDFileFormat.Run]];
CheckBB[handle, maskRunGroup.sMin, fMin, runGroup.sSize, fMax-fMin, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRunGroupRef]]
};
ans.sMin ← maskRunGroup.sMin;
ans.fMin ← fMin;
ans.fOffset ← 0;
ans.sSize ← runGroup.sSize;
ans.fSize ← fMax;
RETURN [ans];
};
maskSamples => {
ans: CommandBuffer.maskSamples;
maskSamples: PDFileFormat.MaskSamples;
samples: PDFileFormat.SampleArray;
ReadBlock[handle, @maskSamples, SIZE[PDFileFormat.MaskSamples]];
ReadBlock[handle, @samples, SIZE[PDFileFormat.SampleArray]];
CheckBB[handle, maskSamples.sMin, maskSamples.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamples]+SIZE[PDFileFormat.SampleArray]];
ans.loadAddress ← -1;
{raster: BlockDescription
← ReadLocate[
handle,
Inline.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord]
];
ans.samples ← PDInterpBitmap.Reshape[
raster.pointer,
raster.words,
[maskSamples.sMin, maskSamples.fMin, samples.sSize, samples.fSize]
! PDInterpBitmap.InsufficientSpace => {
RaisePDError[handle, bitmapTooBig, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamples]+SIZE[PDFileFormat.SampleArray]];
ERROR
}
];
};
RETURN [ans];
};
colorSamples => {
ans: CommandBuffer.colorSamples;
colorSamples: PDFileFormat.ColorSamples;
samples: PDFileFormat.SampleArray;
ReadBlock[handle, @colorSamples, SIZE[PDFileFormat.ColorSamples]];
ReadBlock[handle, @samples, SIZE[PDFileFormat.SampleArray]];
CheckBB[handle, colorSamples.sMin, colorSamples.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.ColorSamples]+SIZE[PDFileFormat.SampleArray]];
{raster: BlockDescription
← ReadLocate[
handle,
Inline.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord]
];
ans.samples ← PDInterpBitmap.Reshape[
raster.pointer,
raster.words,
[colorSamples.sMin, colorSamples.fMin, samples.sSize, samples.fSize]
! PDInterpBitmap.InsufficientSpace => {
RaisePDError[handle, bitmapTooBig, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamples]+SIZE[PDFileFormat.SampleArray]];
ERROR
}
];
};
RETURN [ans];
};
ENDCASE => {
RaisePDError[handle, unrecognisedImagingCommand, SIZE[PDFileFormat.Command]]; ERROR};
};
controlCommand: PDFileFormat.Command.control => {
ans: CommandBuffer.stateChange;
ans.loadChangeStart ← ans.loadChangeLength ← 0;
IF handle.colorType = none THEN SELECT controlCommand.com FROM
startImage, deviceCommand, storeLoad, endDocument => NULL;
ENDCASE => {
RaisePDError[handle, missingStartImage, SIZE[PDFileFormat.Command]];
ERROR
};
SELECT controlCommand.com FROM
startImage => {
startImage: PDFileFormat.StartImage;
ReadBlock[handle, @startImage, SIZE[PDFileFormat.StartImage]];
IF startImage.filler # 0 THEN {
RaisePDWarning[handle, nonZeroFill, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]];
};
IF (LONG[startImage.passBands]+startImage.nBands)*handle.sSizeBand >= handle.herald.imageSSize+handle.sSizeBand
OR LONG[startImage.fMinPage]+startImage.fSizePage > handle.herald.imageFSize THEN {
RaisePDWarning[handle, imageBoundsExceedPageBounds, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]];
};
IF handle.colorType # none AND handle.bandNumber < handle.image.nBands THEN
RaisePDWarning[handle, tooFewBands, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]];
handle.image ← startImage;
ans.whatChanged ← imageStart;
handle.priority ← 0;
handle.colorType ← ink;
handle.bandNumber ← 0;
handle.sMinBand ← startImage.passBands*handle.sSizeBand;
IF NOT startImage.strip THEN {handle.pass ← handle.pass + 1};
IF startImage.feed THEN {handle.page ← handle.page + 1; handle.pass ← 1};
RETURN [ans]
};
setPriority => {
priorityLow: PDFileFormat.Priority;
priority: Environment.LongNumber;
ReadBlock[handle, @priorityLow, SIZE[PDFileFormat.Priority]];
priority.highbits ← controlCommand.rest;
priority.lowbits ← priorityLow;
handle.priority ← priority.li;
ans.whatChanged ← priorityChange;
RETURN [ans]
};
setColorInk => {
handle.colorType ← ink;
ans.whatChanged ← colorChange;
RETURN [ans]
};
setColorClear => {
handle.colorType ← clear;
ans.whatChanged ← colorChange;
RETURN [ans]
};
setColorTile => {
setColorTile: PDFileFormat.SetColorTile;
ReadBlock[handle, @setColorTile, SIZE[PDFileFormat.SetColorTile]];
handle.colorTileLoadAddress ← setColorTile.addr;
SELECT controlCommand.rest FROM
0 => handle.colorType ← opaqueTile;
1 => handle.colorType ← transparentTile;
ENDCASE => {
handle.colorType ← opaqueTile;
RaisePDWarning[handle, unknownColorTileFlag, SIZE[PDFileFormat.Command]];
};
ans.whatChanged ← colorChange;
RETURN [ans];
};
endBand => {
handle.sMinBand ← handle.sMinBand + handle.sSizeBand;
handle.bandNumber ← handle.bandNumber + 1;
ans.whatChanged ← bandChange;
IF handle.bandNumber = handle.image.nBands THEN {
ans.whatChanged ← imageEnd;
handle.colorType ← none;
};
RETURN [ans];
};
endDocument => {
ans.whatChanged ← documentEnd;
RETURN [ans];
};
storeLoad => {
storeLoad: PDFileFormat.StoreLoad;
loadWordsAllocated: LONG CARDINAL ← private.loadWordsAllocated;
ReadBlock[handle, @storeLoad, SIZE[PDFileFormat.StoreLoad]];
IF storeLoad.firstAddress > loadWordsAllocated
OR storeLoad.firstAddress + storeLoad.wordCount > loadWordsAllocated
OR storeLoad.firstAddress + storeLoad.wordCount > handle.herald.maxLoadWord THEN
{RaisePDError[handle, loadOutOfBounds, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StoreLoad]]; ERROR};
ReadLongBlock[handle, private.loadPointer+storeLoad.firstAddress, storeLoad.wordCount];
ans.whatChanged ← loadChange;
ans.loadChangeStart ← storeLoad.firstAddress;
ans.loadChangeLength ← storeLoad.wordCount;
handle.loadWords ← MAX[handle.loadWords, ans.loadChangeStart + ans.loadChangeLength];
handle.colorTileLoadAddress ← -1;
RETURN [ans];
};
deviceCommand => {
deviceCommand: CommandBuffer.deviceCommand;
wordCount: CARDINAL;
block: BlockDescription;
ReadBlock[handle, @wordCount, SIZE[CARDINAL]];
block ← ReadLocate[handle, wordCount];
IF block.words < wordCount THEN RaisePDError[handle, unexpectedEOF, block.words+SIZE[CARDINAL]];
deviceCommand.deviceCommandPointer ← block.pointer;
deviceCommand.deviceCommandWords ← block.words;
RETURN [deviceCommand];
};
ENDCASE => {RaisePDError[handle, unrecognisedControlCommand, SIZE[PDFileFormat.Command]]; ERROR};
};
ENDCASE => {RaisePDError[handle, unrecognisedCommandType, SIZE[PDFileFormat.Command]]; ERROR};
};
Error: PUBLIC ERROR [handle: Handle, code: PDInterpBasic.PDErrorCode, wordIndex, wordCount: INT] ~ CODE;
Warning: PUBLIC SIGNAL [handle: Handle, code: PDInterpBasic.PDWarningCode, wordIndex, wordCount: INT] ~ CODE;
RaisePDError: PROC [handle: Handle, code: PDInterpBasic.PDErrorCode, words: INT] ~ {
ERROR Error[handle, code, handle.index-words, words];
};
RaisePDWarning: PROC [handle: Handle, code: PDInterpBasic.PDWarningCode, words: INT] ~ {
handle.warningCount ← handle.warningCount + 1;
SIGNAL Warning[handle, code, handle.index-words, words];
};
END.