PDFileWriterImpl.mesa
Michael Plass, May 3, 1983 10:08 am
DIRECTORY
Environment,
FileIO,
IO,
PDFileFormat,
PDFileWriter,
Rope
;
PDFileWriterImpl: CEDAR PROGRAM
IMPORTS FileIO, IO
EXPORTS PDFileWriter
= BEGIN
bytesPerWord: CARDINAL = Environment.bytesPerWord;
bitsPerWord: CARDINAL = Environment.bitsPerWord;
ROPE: TYPE = Rope.ROPE;
LoadReference: TYPE = LONG CARDINAL;
DeliverRunGroupProc: TYPE = PDFileWriter.DeliverRunGroupProc;
CaptureRunProc: TYPE = PDFileWriter.CaptureRunProc;
DeliverSampleArrayProc: TYPE = PDFileWriter.DeliverSampleArrayProc;
CaptureScanLineProc: TYPE = PDFileWriter.CaptureScanLineProc;
TFlag: TYPE = PDFileWriter.TFlag;
Toner: TYPE = PDFileFormat.Toner;
maxLoadSize: CARDINAL = 16000;
LoadRec: TYPE = ARRAY [0..maxLoadSize) OF WORD;
Bands: TYPE = REF BandsRec;
BandsRec: TYPE = RECORD [
bands: SEQUENCE maxBands: NAT OF Band
];
Band: TYPE = RECORD [
colorId: INT,
bandBuffers: BandBuffer
];
bandBufferSize: NAT = 1000;
BandBuffer: TYPE = REF BandBufferRec;
BandBufferRec: TYPE = RECORD [
link: BandBuffer,
length: NAT ← 0,
word: ARRAY [0..bandBufferSize) OF WORD
];
ColorDescriptor: TYPE = MACHINE DEPENDENT RECORD [
colorId: INT ← 0, -- bumped whenever the color changes.
length: CARDINAL ← 1,
command: PDFileFormat.Command.control ← [control[setColorInk]],
setColorTile: PDFileFormat.SetColorTile
];
PDState: PUBLIC TYPE = REF PDStateRec;
PDStateRec: PUBLIC TYPE = RECORD [
fileName: ROPE,
herald: PDFileFormat.Herald,
colorDescriptor: ARRAY Toner OF ColorDescriptor,
stream: IO.STREAM,
firstToner: Toner,
lastToner: Toner,
bands: ARRAY Toner OF Bands,
selectedBands: Bands ← NIL,
selectedBandNum: NAT ← 0,
sMinPage: CARDINAL,
sMaxPage: CARDINAL,
fMinPage: CARDINAL,
fMaxPage: CARDINAL,
currentLoadLocation: LONG CARDINAL ← 0,
loadWrittenLength: LONG CARDINAL ← 0,
load: REF LoadRec ← NIL,
leftOverMode: BOOLEAN,
priorityImportant: BOOLEAN
];
Create: PUBLIC PROC [fileName: ROPE, deviceCode: PDFileFormat.DeviceCode, sResolution, fResolution, imageSSize, imageFSize: CARDINAL, nColors: NAT ← 1, bandSSize: CARDINAL ← 16, copies: CARDINAL ← 1, leftOverMode: BOOLEANTRUE, priorityImportant: BOOLEANTRUE] RETURNS [pdState: PDState] = {
nBands: NAT;
pdState ← NEW [PDStateRec];
pdState.fileName ← fileName;
pdState.herald.deviceCode ← deviceCode;
pdState.herald.sResolution ← sResolution;
pdState.herald.fResolution ← fResolution;
pdState.herald.imageSSize ← pdState.sMinPage ← imageSSize;
pdState.herald.imageFSize ← pdState.fMinPage ← imageFSize;
pdState.herald.bandSSize ← bandSSize;
pdState.herald.maxLoadWord ← 0;
pdState.herald.copies ← copies;
pdState.leftOverMode ← leftOverMode;
pdState.priorityImportant ← priorityImportant;
pdState.sMaxPage ← pdState.fMaxPage ← 0;
pdState.firstToner ← SELECT nColors FROM
1, 4 => black,
3 => cyan,
ENDCASE => ERROR;
pdState.lastToner ← SELECT nColors FROM
1 => black,
3, 4 => yellow,
ENDCASE => ERROR;
nBands ← (pdState.herald.imageSSize+pdState.herald.bandSSize-1)/pdState.herald.bandSSize;
FOR t: Toner IN [pdState.firstToner..pdState.lastToner] DO
pdState.bands[t] ← NEW [BandsRec[nBands]];
ENDLOOP;
pdState.stream ← FileIO.Open[fileName, overwrite];
WriteHerald[pdState];
We will come back and overwrite this when the file is closed.
};
SetColorInk: PUBLIC PROC [pdState: PDState, toner: Toner] = {
pdState.colorDescriptor[toner].colorId ← pdState.colorDescriptor[toner].colorId + 1;
pdState.colorDescriptor[toner].length ← SIZE[PDFileFormat.Command];
pdState.colorDescriptor[toner].command ← [control[setColorInk]];
};
SetColorClear: PUBLIC PROC [pdState: PDState, toner: Toner] = {
pdState.colorDescriptor[toner].colorId ← pdState.colorDescriptor[toner].colorId + 1;
pdState.colorDescriptor[toner].length ← SIZE[PDFileFormat.Command];
pdState.colorDescriptor[toner].command ← [control[setColorClear]];
};
SetColorTile: PUBLIC PROC [pdState: PDState, toner: Toner, tileRef: LoadReference, tFlag: TFlag] = TRUSTED {
colorId: INT ← pdState.colorDescriptor[toner].colorId + 1;
tBit: [0..1] = IF tFlag = opaque THEN PDFileFormat.opaqueFlag ELSE PDFileFormat.transparentFlag;
pdState.colorDescriptor[toner] ← [
colorId: colorId,
length: SIZE[PDFileFormat.Command] + SIZE[PDFileFormat.SetColorTile],
command: [control[setColorTile, tBit]],
setColorTile: [addr: tileRef]
];
};
DoForEachToner: PUBLIC PROC [pdState: PDState, proc: PROC[Toner]] = {
FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO
proc[toner];
ENDLOOP;
};
GetBounds: PUBLIC PROC [pdState: PDState] RETURNS [sMax, fMax: CARDINAL] = {
sMax ← pdState.herald.imageSSize;
fMax ← pdState.herald.imageFSize;
};
MaskRectangle: PUBLIC PROC [pdState: PDState, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL] = TRUSTED {
sEnd: CARDINALIF pdState.leftOverMode THEN sMin+1 ELSE sMin + sSize;
bandSSize: CARDINAL ← pdState.herald.bandSSize;
command: PDFileFormat.Command ← [imaging[maskRectangle, 0]];
maskArgs: PDFileFormat.MaskRectangle ← [sMin:sMin, sSize:sSize, fMin:fMin, fSize:fSize];
ExtendBB[pdState, sMin, fMin];
ExtendBB[pdState, sMin + sSize, fMin + fSize];
FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO
nextBandStart: CARDINAL ← sMin + (bandSSize - (sMin MOD bandSSize));
SelectBand[pdState, sMin, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @maskArgs, SIZE[PDFileFormat.MaskRectangle]];
FOR s: CARDINAL ← nextBandStart, s + bandSSize WHILE s<sEnd DO
SelectBand[pdState, s, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @maskArgs, SIZE[PDFileFormat.MaskRectangle]];
ENDLOOP;
ENDLOOP;
};
MaskTrapezoid: PUBLIC PROC [pdState: PDState, sMin, sSize: CARDINAL, fMin, fSize: CARDINAL, fMinLast, fSizeLast: CARDINAL] = TRUSTED {
sEnd: CARDINALIF pdState.leftOverMode THEN sMin+1 ELSE sMin + sSize;
bandSSize: CARDINAL ← pdState.herald.bandSSize;
command: PDFileFormat.Command ← [imaging[maskTrapezoid, 0]];
maskArgs: PDFileFormat.MaskTrapezoid ← [sMin:sMin, sSize:sSize, fMin:fMin, fSize:fSize, fMinLast:fMinLast, fSizeLast:fSizeLast];
ExtendBB[pdState, sMin, MIN[fMin, fMinLast]];
ExtendBB[pdState, sMin + sSize, MAX[fMin + fSize, fMinLast + fSizeLast]];
FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO
nextBandStart: CARDINAL ← sMin + (bandSSize - (sMin MOD bandSSize));
SelectBand[pdState, sMin, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @maskArgs, SIZE[PDFileFormat.MaskTrapezoid]];
FOR s: CARDINAL ← nextBandStart, s + bandSSize WHILE s<sEnd DO
SelectBand[pdState, s, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @maskArgs, SIZE[PDFileFormat.MaskTrapezoid]];
ENDLOOP;
ENDLOOP;
};
MaskSamplesRef: PUBLIC PROC [pdState: PDState, samplesRef: LoadReference, sMin: CARDINAL, fMin: CARDINAL] = TRUSTED {
longNumber: Environment.LongNumber ← [lc[samplesRef]];
command: PDFileFormat.Command ← [imaging[maskSamplesRef, longNumber.highbits]];
args: PDFileFormat.MaskSamplesRef ← [
addrLowBits: longNumber.lowbits,
sMin: sMin,
fMin: fMin
];
ptr: LONG POINTER ← @(pdState.load[samplesRef]);
sampleArrayPtr: LONG POINTER TO PDFileFormat.SampleArray ← ptr;
sEnd: CARDINALIF pdState.leftOverMode THEN sMin+1 ELSE sMin + sampleArrayPtr^.sSize;
bandSSize: CARDINAL ← pdState.herald.bandSSize;
ExtendBB[pdState, sMin, fMin];
ExtendBB[pdState, sMin + sampleArrayPtr^.sSize, fMin + sampleArrayPtr^.fSize];
FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO
nextBandStart: CARDINAL ← sMin + (bandSSize - (sMin MOD bandSSize));
SelectBand[pdState, sMin, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @args, SIZE[PDFileFormat.MaskSamplesRef]];
FOR s: CARDINAL ← nextBandStart, s + bandSSize WHILE s<sEnd DO
SelectBand[pdState, s, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @args, SIZE[PDFileFormat.MaskSamplesRef]];
ENDLOOP;
ENDLOOP;
};
MaskSamples: PUBLIC PROC [pdState: PDState, sMin: CARDINAL, fMin: CARDINAL, sSize: CARDINAL, fSize: CARDINAL, deliverProc: DeliverSampleArrayProc] = TRUSTED {
command: PDFileFormat.Command ← [imaging[maskSamples, 0]];
bandSSize: CARDINAL = pdState.herald.bandSSize;
wordsPerLine: NAT ← (fSize+(bitsPerWord-1))/bitsPerWord;
ExtendBB[pdState, sMin, fMin];
ExtendBB[pdState, sMin + sSize, fMin + fSize];
FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO
s: CARDINAL ← sMin;
sEnd: CARDINAL ← sMin + sSize;
residualThisBand: NAT ← 0;
scanLineProc: PROC [scanLineDataPointer: LONG POINTER] = TRUSTED {
IF residualThisBand = 0 THEN {
args: PDFileFormat.MaskSamples ← [
sMin: s,
fMin: fMin
];
truncatedEnd: CARDINALMIN[sEnd, s + (bandSSize - (s MOD bandSSize))];
sampleArray: PDFileFormat.SampleArray ← [
sSize: (residualThisBand ← truncatedEnd - s),
fSize: fSize
];
SelectBand[pdState, s, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @args, SIZE[PDFileFormat.MaskSamples]];
EnterBandData[pdState, @sampleArray, SIZE[PDFileFormat.SampleArray]];
};
EnterBandData[pdState, scanLineDataPointer, wordsPerLine];
residualThisBand ← residualThisBand - 1;
s ← s + 1;
};
deliverProc[scanLineProc];
IF residualThisBand # 0 THEN ERROR;
IF s # sEnd THEN ERROR;
ENDLOOP;
};
MaskRunGroupRef: PUBLIC PROC [pdState: PDState, runGroupRef: LoadReference, sMin: CARDINAL, fMin: CARDINAL] = TRUSTED {
longNumber: Environment.LongNumber ← [lc[runGroupRef]];
command: PDFileFormat.Command ← [imaging[maskRunGroupRef, longNumber.highbits]];
args: PDFileFormat.MaskRunGroupRef ← [
addrLowBits: longNumber.lowbits,
sMin: sMin,
fMin: fMin
];
sSize: CARDINAL ← pdState.load[runGroupRef];
fSize: CARDINAL ← pdState.load[runGroupRef-1];
sEnd: CARDINALIF pdState.leftOverMode THEN sMin+1 ELSE sMin + sSize;
bandSSize: CARDINAL ← pdState.herald.bandSSize;
ExtendBB[pdState, sMin, fMin];
ExtendBB[pdState, sMin + sSize, fMin + fSize];
FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO
nextBandStart: CARDINAL ← sMin + (bandSSize - (sMin MOD bandSSize));
SelectBand[pdState, sMin, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @args, SIZE[PDFileFormat.MaskRunGroupRef]];
FOR s: CARDINAL ← nextBandStart, s + bandSSize WHILE s<sEnd DO
SelectBand[pdState, s, toner];
EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @args, SIZE[PDFileFormat.MaskRunGroupRef]];
ENDLOOP;
ENDLOOP;
};
MaskRunGroup: PUBLIC PROC [pdState: PDState, deliverProc: DeliverRunGroupProc] = {
maxRuns: NAT = bandBufferSize/2 - 3;
bandSSize: CARDINAL = pdState.herald.bandSSize;
buffer: MACHINE DEPENDENT RECORD [
command: PDFileFormat.Command ← [imaging[maskRunGroup]],
sMin: CARDINAL,
sSize: CARDINAL,
run: ARRAY [0..maxRuns) OF PDFileFormat.Run
];
nRuns: NAT ← 0;
scanLineNumber: CARDINAL;
bandEnd: CARDINAL;
currentToner: Toner;
PutBuffer: PROC = TRUSTED {
IF nRuns > 0 THEN {
IF NOT buffer.run[nRuns - 1].lastRun THEN {
buffer.sSize ← buffer.sSize + 1;
buffer.run[nRuns - 1].lastRun ← TRUE;
};
SelectBand[pdState, buffer.sMin, currentToner];
EnterBandData[pdState, @buffer, SIZE[PDFileFormat.Command] + SIZE[CARDINAL] + SIZE[CARDINAL] + nRuns * SIZE[PDFileFormat.Run]];
nRuns ← 0;
buffer.sMin ← scanLineNumber;
buffer.sSize ← 0;
};
};
InitBuffer: PROC [sMin: CARDINAL] = {
buffer.sMin ← scanLineNumber ← sMin;
buffer.sSize ← 0;
bandEnd ← sMin - sMin MOD bandSSize + bandSSize;
};
BufferRun: PROC [fMin, fSize: CARDINAL] = {
IF nRuns = maxRuns THEN PutBuffer[];
buffer.run[nRuns] ← [fMin: fMin, fSize: fSize, lastRun: FALSE];
nRuns ← nRuns + 1;
};
NextLine: PROC = {
buffer.sSize ← buffer.sSize + 1;
buffer.run[nRuns - 1].lastRun ← TRUE;
scanLineNumber ← scanLineNumber + 1;
};
CaptureRun: PROC [sMin, fMin, fSize: CARDINAL] = {
IF nRuns = 0 THEN InitBuffer[sMin]
ELSE IF sMin >= bandEnd OR NOT (sMin IN [scanLineNumber..scanLineNumber+1]) OR nRuns = maxRuns THEN {PutBuffer[]; InitBuffer[sMin]};
IF sMin > scanLineNumber THEN NextLine[];
IF sMin # scanLineNumber THEN ERROR;
IF INT[fMin] + INT[fSize] > INT[LAST[CARDINAL]] THEN {fSize ← LAST[CARDINAL] - fMin};
ExtendBB[pdState, sMin, fMin];
IF fSize > LAST[NAT] THEN {
BufferRun[fMin, LAST[NAT]];
fMin ← fMin + LAST[NAT]; fSize ← fSize - LAST[NAT];
};
BufferRun[fMin, fSize];
ExtendBB[pdState, sMin + 1, fMin + fSize];
};
FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO
currentToner ← toner;
deliverProc[CaptureRun];
PutBuffer[];
ENDLOOP;
};
ColorSamples: PUBLIC PROC [pdState: PDState, toner: Toner, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL, deliverProc: DeliverSampleArrayProc, tFlag: TFlag] = TRUSTED {
tBit: [0..1] = IF tFlag = opaque THEN PDFileFormat.opaqueFlag ELSE PDFileFormat.transparentFlag;
colorCommand: PDFileFormat.Command ← [imaging[colorSamples, tBit]];
bandSSize: CARDINAL = pdState.herald.bandSSize;
wordsPerLine: NAT ← (fSize+(bitsPerWord-1))/bitsPerWord;
s: CARDINAL ← sMin;
sEnd: CARDINAL ← sMin + sSize;
residualThisBand: NAT ← 0;
CaptureScanLine: PROC [scanLineDataPointer: LONG POINTER] = TRUSTED {
IF residualThisBand = 0 THEN {
args: PDFileFormat.MaskSamples ← [
sMin: s,
fMin: fMin
];
truncatedEnd: CARDINALMIN[sEnd, s + bandSSize - (s MOD bandSSize)];
sampleArray: PDFileFormat.SampleArray ← [
sSize: (residualThisBand ← truncatedEnd - s),
fSize: fSize
];
SelectBand[pdState, s, toner];
EnterBandData[pdState, @colorCommand, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @args, SIZE[PDFileFormat.MaskSamples]];
EnterBandData[pdState, @sampleArray, SIZE[PDFileFormat.SampleArray]];
};
EnterBandData[pdState, scanLineDataPointer, wordsPerLine];
residualThisBand ← residualThisBand - 1;
s ← s + 1;
};
ExtendBB[pdState, sMin, fMin];
ExtendBB[pdState, sMin + sSize, fMin + fSize];
deliverProc[CaptureScanLine];
IF residualThisBand # 0 THEN ERROR;
IF s # sEnd THEN ERROR;
};
RemainingLoadSize: PUBLIC PROC [pdState: PDState] RETURNS [words: INT] = {
words ← INT[maxLoadSize] - pdState.currentLoadLocation;
};
SetLoadLocation: PUBLIC PROC [pdState: PDState, loadReference: LoadReference] = {
WriteLoadAdditions[pdState];
pdState.currentLoadLocation ← pdState.loadWrittenLength ← loadReference;
};
LoadRunGroup: PUBLIC PROC [pdState: PDState, deliverProc: DeliverRunGroupProc] RETURNS [loadReference: LoadReference] = TRUSTED {
highBit: CARDINAL = CARDINAL[LAST[NAT]] + 1;
scanLineNumber: CARDINAL ← 0;
loc: CARDINAL ← pdState.currentLoadLocation;
load: REF LoadRec ← pdState.load;
fMax: CARDINAL ← 0;
scanLineEmpty: BOOLEANTRUE;
CaptureRun: PROC [sMin, fMin, fSize: CARDINAL] = TRUSTED {
IF sMin<scanLineNumber THEN ERROR; -- scan lines must come in increasing s order.
WHILE sMin#scanLineNumber DO
IF scanLineEmpty THEN {load[loc] ← 0; load[loc+1] ← highBit; loc ← loc+2}
ELSE {load[loc-1] ← load[loc-1] + highBit};
scanLineNumber ← scanLineNumber+1;
scanLineEmpty ← TRUE;
ENDLOOP;
scanLineEmpty ← FALSE;
IF INT[fMin] + INT[fSize] > INT[LAST[CARDINAL]] THEN {fSize ← LAST[CARDINAL] - fMin};
IF fSize > LAST[NAT] THEN {
load[loc] ← fMin; load[loc+1] ← LAST[NAT]; loc ← loc+2;
fMin ← fMin + LAST[NAT]; fSize ← fSize - LAST[NAT];
};
load[loc] ← fMin; load[loc+1] ← fSize; loc ← loc+2;
fMax ← MAX[fMax, fMin+fSize];
};
IF load = NIL THEN pdState.load ← load ← NEW[LoadRec];
loadReference ← loc+1;
Reserve a word in the load for fMax.
loc ← loc + 2;
Will come back to fill in sSize.
deliverProc[CaptureRun];
IF NOT scanLineEmpty THEN {load[loc-1] ← load[loc-1] + highBit; scanLineNumber ← scanLineNumber+1};
load[loadReference-1] ← fMax;
load[loadReference] ← scanLineNumber;
pdState.currentLoadLocation ← loc;
pdState.herald.maxLoadWord ← MAX[pdState.herald.maxLoadWord, loc];
};
LoadSampleArray: PUBLIC PROC [pdState: PDState, sSize, fSize: CARDINAL, deliverProc: DeliverSampleArrayProc] RETURNS [loadReference: LoadReference] = TRUSTED {
CaptureScanLine: PROC [scanLineDataPointer: LONG POINTER] = TRUSTED {
source: LONG POINTER TO WORD ← scanLineDataPointer;
startLoc: CARDINAL ← loc;
FOR i: NAT IN [0..wordsPerLine) DO
load[startLoc+i] ← (source+i)^;
ENDLOOP;
loc ← loc + wordsPerLine;
};
load: REF LoadRec ← pdState.load;
wordsPerLine: NAT ← (fSize+(bitsPerWord-1))/bitsPerWord;
loc: LONG CARDINAL ← pdState.currentLoadLocation;
numberOfWordsOfData: LONG CARDINALLONG[sSize]*wordsPerLine;
IF load = NIL THEN pdState.load ← load ← NEW[LoadRec];
loadReference ← loc;
load[loc] ← sSize; loc ← loc+1;
load[loc] ← fSize; loc ← loc+1;
deliverProc[CaptureScanLine];
IF loc # loadReference + SIZE[PDFileFormat.SampleArray] + numberOfWordsOfData THEN ERROR;
pdState.currentLoadLocation ← loc;
pdState.herald.maxLoadWord ← MAX[pdState.herald.maxLoadWord, loc];
};
LoadContiguousSampleArray: PUBLIC PROC [pdState: PDState, sSize, fSize: CARDINAL, bitsPtr: LONG POINTER] RETURNS [loadReference: LoadReference] = TRUSTED {
source: LONG POINTER TO WORD ← bitsPtr;
load: REF LoadRec ← pdState.load;
wordsPerLine: INT ← (fSize+(bitsPerWord-1))/bitsPerWord;
loc: LONG CARDINAL ← pdState.currentLoadLocation;
IF load = NIL THEN pdState.load ← load ← NEW[LoadRec];
loadReference ← loc;
load[loc] ← sSize; loc ← loc+1;
load[loc] ← fSize; loc ← loc+1;
FOR i: INT IN [0..sSize*wordsPerLine) DO
load[loc] ← source^;
loc ← loc+1;
source ← source+1;
ENDLOOP;
pdState.currentLoadLocation ← loc;
pdState.herald.maxLoadWord ← MAX[pdState.herald.maxLoadWord, loc];
};
LoadColorTile: PUBLIC PROC [pdState: PDState, phase: CARDINAL, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL, deliverProc: DeliverSampleArrayProc] RETURNS [loadReference: LoadReference] = TRUSTED {
CaptureScanLine: PROC [scanLineDataPointer: LONG POINTER] = TRUSTED {
source: LONG POINTER TO WORD ← scanLineDataPointer;
startLoc: CARDINAL ← loc;
FOR i: NAT IN [0..wordsPerLine) DO
load[startLoc+i] ← (source+i)^;
ENDLOOP;
loc ← loc + wordsPerLine;
};
load: REF LoadRec ← pdState.load;
wordsPerLine: NAT ← (fSize+(bitsPerWord-1))/bitsPerWord;
loc: LONG CARDINAL ← pdState.currentLoadLocation;
numberOfWordsOfData: LONG CARDINALLONG[sSize]*wordsPerLine;
IF load = NIL THEN pdState.load ← load ← NEW[LoadRec];
loadReference ← loc;
load[loc] ← phase; loc ← loc+1;
load[loc] ← sMin; loc ← loc+1;
load[loc] ← fMin; loc ← loc+1;
load[loc] ← sSize; loc ← loc+1;
load[loc] ← fSize; loc ← loc+1;
deliverProc[CaptureScanLine];
IF loc # loadReference + SIZE[PDFileFormat.Tile] + numberOfWordsOfData THEN ERROR;
pdState.currentLoadLocation ← loc;
pdState.herald.maxLoadWord ← MAX[pdState.herald.maxLoadWord, loc];
};
LoadContiguousColorTile: PUBLIC PROC [pdState: PDState, phase: CARDINAL, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL, bitsPtr: LONG POINTER] RETURNS [loadReference: LoadReference] = TRUSTED {
source: LONG POINTER TO WORD ← bitsPtr;
load: REF LoadRec ← pdState.load;
wordsPerLine: INT ← (fSize+(bitsPerWord-1))/bitsPerWord;
loc: LONG CARDINAL ← pdState.currentLoadLocation;
IF load = NIL THEN pdState.load ← load ← NEW[LoadRec];
loadReference ← loc;
load[loc] ← phase; loc ← loc+1;
load[loc] ← sMin; loc ← loc+1;
load[loc] ← fMin; loc ← loc+1;
load[loc] ← sSize; loc ← loc+1;
load[loc] ← fSize; loc ← loc+1;
FOR i: INT IN [0..sSize*wordsPerLine) DO
load[loc] ← source^;
loc ← loc+1;
source ← source+1;
ENDLOOP;
pdState.currentLoadLocation ← loc;
pdState.herald.maxLoadWord ← MAX[pdState.herald.maxLoadWord, loc];
};
EndPage: PUBLIC PROC [pdState: PDState] = {
startBand: NAT ← pdState.sMinPage/pdState.herald.bandSSize;
endBand: NAT ← (pdState.sMaxPage+pdState.herald.bandSSize-1)/pdState.herald.bandSSize;
nBands: NATMAX[0, INTEGER[endBand]-startBand];
fSizePage: CARDINALMAX[INT[pdState.fMaxPage]-pdState.fMinPage, 0];
IF nBands = 0 THEN startBand ← 0;
IF fSizePage = 0 THEN pdState.fMinPage ← 0;
WriteLoadAdditions[pdState];
FOR t: Toner IN [pdState.firstToner..pdState.lastToner] DO
bands: Bands ← pdState.bands[t];
WriteStartImage[
pdState: pdState,
feed: t = pdState.firstToner,
strip: t = pdState.lastToner,
toner: t,
passBands: startBand,
nBands: nBands,
fMinPage: pdState.fMinPage,
fSizePage: fSizePage
];
WriteBands[pdState, bands, startBand, nBands];
ENDLOOP;
pdState.sMinPage ← pdState.herald.imageSSize;
pdState.fMinPage ← pdState.herald.imageFSize;
pdState.sMaxPage ← pdState.fMaxPage ← 0;
};
FlushPage: PUBLIC PROC [pdState: PDState] = {
In case the client decides it didn't really want this page after all.
startBand: NAT ← pdState.sMinPage/pdState.herald.bandSSize;
endBand: NAT ← (pdState.sMaxPage+pdState.herald.bandSSize-1)/pdState.herald.bandSSize;
nBands: NATMAX[0, INTEGER[endBand]-startBand];
fSizePage: CARDINALMAX[INT[pdState.fMaxPage]-pdState.fMinPage, 0];
FOR t: Toner IN [pdState.firstToner..pdState.lastToner] DO
bands: Bands ← pdState.bands[t];
FOR i: NAT IN [startBand..startBand+nBands) DO
bands[i] ← [colorId: 0, bandBuffers: NIL];
ENDLOOP
ENDLOOP;
pdState.sMinPage ← pdState.herald.imageSSize;
pdState.fMinPage ← pdState.herald.imageFSize;
pdState.sMaxPage ← pdState.fMaxPage ← 0;
};
Close: PUBLIC PROC [pdState: PDState] = {
WriteControlCommand[pdState, endDocument];
pdState.stream.SetIndex[0];
WriteHerald[pdState];
pdState.stream.Close[];
};
ExtendBB: PROC [pdState: PDState, s: CARDINAL, f: CARDINAL] = {
pdState.sMinPage ← MIN[s, pdState.sMinPage];
pdState.sMaxPage ← MAX[s, pdState.sMaxPage];
pdState.fMinPage ← MIN[f, pdState.fMinPage];
pdState.fMaxPage ← MAX[f, pdState.fMaxPage];
};
SelectBandNoColor: PROC [pdState: PDState, sMin: CARDINAL, toner: Toner] = TRUSTED {
bandNum: NAT ← sMin/pdState.herald.bandSSize;
bands: Bands ← pdState.bands[toner];
IF bands[bandNum].bandBuffers = NIL THEN bands[bandNum].bandBuffers ← NEW[BandBufferRec];
pdState.selectedBands ← bands;
pdState.selectedBandNum ← bandNum;
};
SelectBand: PROC [pdState: PDState, sMin: CARDINAL, toner: Toner] = TRUSTED {
colorId: INT ← pdState.colorDescriptor[toner].colorId;
longPriority: Environment.LongNumber ← [lc[colorId]];
priorityHighbits: [0..256) ← longPriority.highbits;
priorityLowbits: CARDINAL ← longPriority.lowbits;
priorityCommand: PDFileFormat.Command ← [control[setPriority, priorityHighbits]];
bandNum: NAT ← sMin/pdState.herald.bandSSize;
bands: Bands ← pdState.bands[toner];
IF bands[bandNum].bandBuffers = NIL THEN bands[bandNum].bandBuffers ← NEW[BandBufferRec];
pdState.selectedBands ← bands;
pdState.selectedBandNum ← bandNum;
IF colorId # bands[bandNum].colorId THEN {
bands[bandNum].colorId ← colorId;
IF pdState.priorityImportant THEN {
EnterBandData[pdState, @priorityCommand, SIZE[PDFileFormat.Command]];
EnterBandData[pdState, @priorityLowbits, SIZE[CARDINAL]];
};
EnterBandData[pdState, @(pdState.colorDescriptor[toner].command), pdState.colorDescriptor[toner].length];
};
};
EnterBandData: PROC [pdState: PDState, startPtr: LONG POINTER, wordCount: NAT] = TRUSTED {
source: LONG POINTER TO WORD ← startPtr;
bandBuffers: BandBuffer ← pdState.selectedBands[pdState.selectedBandNum].bandBuffers;
length: NAT ← bandBuffers.length;
WHILE wordCount > 0 DO
IF length = bandBufferSize THEN {
new: BandBuffer ← NEW[BandBufferRec];
bandBuffers.length ← length;
new.link ← bandBuffers;
bandBuffers ← new;
length ← 0;
};
bandBuffers.word[length] ← source^;
length ← length + 1;
wordCount ← wordCount - 1;
source ← source + 1;
ENDLOOP;
bandBuffers.length ← length;
pdState.selectedBands[pdState.selectedBandNum].bandBuffers ← bandBuffers;
};
WriteLoadAdditions: PROC [pdState: PDState] = TRUSTED {
Writes out any additions to the font load
WHILE pdState.loadWrittenLength < pdState.currentLoadLocation DO
lengthOfAdditions: INT ← pdState.currentLoadLocation-pdState.loadWrittenLength;
lengthOfChunk: INTMIN[lengthOfAdditions, LAST[NAT]];
unsafeBlock: IO.UnsafeBlock = [base: @(pdState.load[pdState.loadWrittenLength]), startIndex: 0, stopIndexPlusOne: lengthOfChunk*bytesPerWord];
WriteControlCommand[pdState, storeLoad];
WriteLongCardinal[pdState, pdState.loadWrittenLength];
WriteCardinal[pdState, lengthOfChunk];
pdState.stream.UnsafePutBlock[unsafeBlock];
pdState.loadWrittenLength ← pdState.loadWrittenLength + lengthOfChunk;
ENDLOOP;
};
WriteLongCardinal: PROC [pdState: PDState, lc: LONG CARDINAL] = TRUSTED {
unsafeBlock: IO.UnsafeBlock = [base: @lc, startIndex: 0, stopIndexPlusOne: SIZE[LONG CARDINAL]*bytesPerWord];
pdState.stream.UnsafePutBlock[unsafeBlock];
};
WriteCardinal: PROC [pdState: PDState, c: CARDINAL] = TRUSTED {
unsafeBlock: IO.UnsafeBlock = [base: @c, startIndex: 0, stopIndexPlusOne: SIZE[CARDINAL]*bytesPerWord];
pdState.stream.UnsafePutBlock[unsafeBlock];
};
WriteHerald: PROC [pdState: PDState] = TRUSTED {
unsafeBlock: IO.UnsafeBlock = [base: @pdState.herald, startIndex: 0, stopIndexPlusOne: SIZE[PDFileFormat.Herald]*bytesPerWord];
pdState.stream.UnsafePutBlock[unsafeBlock];
};
WriteControlCommand: PROC [pdState: PDState, controlCom: PDFileFormat.ControlCom] = TRUSTED {
command: PDFileFormat.Command ← [control[controlCom]];
unsafeBlock: IO.UnsafeBlock = [base: @command, startIndex: 0, stopIndexPlusOne: SIZE[PDFileFormat.Command]*bytesPerWord];
pdState.stream.UnsafePutBlock[unsafeBlock];
};
WriteStartImage: PROC [
pdState: PDState,
feed: BOOLEAN,
strip: BOOLEAN,
toner: Toner,
passBands: NAT,
nBands: NAT,
fMinPage: CARDINAL,
fSizePage: CARDINAL
] = TRUSTED {
StartImageBuf: TYPE = MACHINE DEPENDENT RECORD [
command: PDFileFormat.Command,
args: PDFileFormat.StartImage
];
startImageBuf: StartImageBuf ← [
command: [control[com: startImage]],
args: [leftOverMode: pdState.leftOverMode, feed: feed, strip: strip, toner: toner, passBands: passBands, nBands: nBands, fMinPage: fMinPage, fSizePage: fSizePage]
];
unsafeBlock: IO.UnsafeBlock = [base: @startImageBuf, startIndex: 0, stopIndexPlusOne: SIZE[StartImageBuf]*bytesPerWord];
pdState.stream.UnsafePutBlock[unsafeBlock];
};
WriteBands: PROC [pdState: PDState, bands: Bands, startBand, nBands: NAT] = TRUSTED {
Writes out the bands, resetting them along the way.
FOR bandNum: NAT IN [startBand..startBand+nBands) DO
bandBuffers: BandBuffer ← bands[bandNum].bandBuffers;
bufList: BandBuffer ← NIL;
bands[bandNum] ← [0, NIL];
Reverse the list of buffers.
WHILE bandBuffers # NIL DO
t: BandBuffer ← bandBuffers;
bandBuffers ← bandBuffers.link;
t.link ← bufList;
bufList ← t;
ENDLOOP;
WHILE bufList # NIL DO
unsafeBlock: IO.UnsafeBlock = [base: @(bufList.word[0]), startIndex: 0, stopIndexPlusOne: INT[bufList.length]*bytesPerWord];
t: BandBuffer ← bufList;
pdState.stream.UnsafePutBlock[unsafeBlock];
bufList ← bufList.link;
t ← NIL; -- Free goes here
ENDLOOP;
WriteControlCommand[pdState, endBand];
ENDLOOP;
};
END.