PDInterpPageImpl.mesa
Copyright (C) 1984, Xerox Corporation. All rights reserved.
Michael Plass, October 31, 1984 10:35:36 am PST
Last Edited by: Pier, November 30, 1983 6:37 pm
DIRECTORY Environment, Inline, PDFileFormat, PDInterpReader, PDInterpOutput, PDInterpPage, PDInterpBitmap, PDInterpSysCalls, Heap, PDQueue, Process;
PDInterpPageImpl: PROGRAM
IMPORTS Inline, PDInterpReader, PDInterpOutput, PDInterpBitmap, PDInterpSysCalls, Heap, Process, PDQueue
EXPORTS PDInterpPage
= BEGIN
CommandBuffer: TYPE = PDInterpReader.CommandBuffer;
bitsPerWord: NAT = Environment.bitsPerWord;
heapZone: UNCOUNTED ZONE=Heap.systemZone;
totalAllocates, totalFrees: INT ← 0;
availCount: NAT; --count of the number of leftover records on the free list
Leftover list types
LeftoverRef: TYPE = LONG POINTER TO Leftover;
Leftover: TYPE = RECORD [
link: LeftoverRef ← NIL,
commandBuffer: CommandBuffer,
colorType: PDInterpReader.ColorType,
colorTileLoadAddress: INT ← -1,
priority: INT
];
InterpretPage: PUBLIC PROC [handle: PDInterpReader.Handle, request: PDQueue.Request, abort: LONG POINTER TO BOOLEAN] RETURNS [ok: BOOLEAN] = {
readHead, writeHead, availHead, writeTail: LeftoverRef ← NIL; --heads and tail of leftover lists
currentColorType: PDInterpReader.ColorType;
currentColorTileLoadAddress: INT ← -1;
currentPriority: INT ← -1;
leftovers: BOOLEAN; --can't be filled in until StartImage has happened
commandBuffer: CommandBuffer;
band: PDInterpBitmap.BitmapDesc;
bandMaxS: INT;
cachedColorTile: PDInterpBitmap.Tile;
cachedColorReference: INT ← -1;
GetColorTile: PROC = {
IF currentColorTileLoadAddress # cachedColorReference THEN {
cachedColorTile ← PDInterpReader.ColorTileFromLoad[handle, cachedColorReference ← currentColorTileLoadAddress, scratchPointer, scratchWords];
};
};
TransferRectangle: PROC [rectangle: PDInterpBitmap.Rectangle] = {
SELECT currentColorType FROM
none => ERROR;
clear => PDInterpBitmap.Fill[band, rectangle, 0];
ink => PDInterpBitmap.Fill[band, rectangle, 1];
opaqueTile => {
GetColorTile[];
PDInterpBitmap.TransferTile[band.Clip[rectangle], cachedColorTile];
};
transparentTile => {
GetColorTile[];
PDInterpBitmap.TransferTile[band.Clip[rectangle], cachedColorTile, [or, null]];
};
ENDCASE => ERROR;
};
DoLine: PROCEDURE [sMin,fMin,fSize: CARDINAL] = {
SELECT currentColorType FROM
none => ERROR;
clear => PDInterpBitmap.Fill[band, [sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize], 0];
opaqueTile, ink => PDInterpBitmap.Fill[band, [sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize], 1];
transparentTile =>
PDInterpBitmap.TransferTile[band.Clip[[sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize]], cachedColorTile, [or, null]];
ENDCASE => ERROR;
};
TempColor: PROC [rectangle: PDInterpBitmap.Rectangle] = {
SELECT currentColorType FROM
none => ERROR;
clear => NULL;
ink => NULL;
opaqueTile => {
GetColorTile[];
PDInterpBitmap.TransferTile[band.Clip[rectangle], cachedColorTile, [xor, complement]];
};
transparentTile => GetColorTile[];
ENDCASE => ERROR;
};
AddLeftover: PROC = {
IF availCount=0 THEN {
totalAllocates←totalAllocates+1;
IF writeHead=NIL THEN writeHead←writeTail←heapZone.NEW[Leftover ←[link: NIL, commandBuffer: commandBuffer, colorType: currentColorType, colorTileLoadAddress: currentColorTileLoadAddress, priority: currentPriority]]
ELSE {
writeTail.link←heapZone.NEW[Leftover ←[link: NIL, commandBuffer: commandBuffer, colorType: currentColorType, colorTileLoadAddress: currentColorTileLoadAddress, priority: currentPriority]];
writeTail←writeTail.link;
};
}
ELSE {
availCount𡤊vailCount-1; --move a node from availList to writeList
IF writeHead=NIL THEN {writeHead←writeTail𡤊vailHead; availHead𡤊vailHead.link;}
ELSE {
writeTail.link𡤊vailHead; writeTail𡤊vailHead; availHead𡤊vailHead.link;
};
writeTail^←[link: NIL, commandBuffer: commandBuffer, colorType: currentColorType, colorTileLoadAddress: currentColorTileLoadAddress, priority: currentPriority];
};
};
FreeList: PROC[head: LeftoverRef] = { --this proc out here so the UNWIND can call it
tempHead: LeftoverRef;
UNTIL head=NIL DO
tempHead←head^.link;
heapZone.FREE[@head];
totalFrees←totalFrees+1;
head←tempHead;
ENDLOOP;
};
CheckAbort: PROC = {IF abort^ THEN ERROR ABORTED};
availCount𡤀
Process.SetPriority[Process.priorityBackground];
DO
ENABLE UNWIND => {
FreeList[readHead];
FreeList[writeHead];
FreeList[availHead];
availCount𡤀
Process.SetPriority[Process.priorityNormal];
};
IF readHead#NIL AND readHead.priority<handle.priority THEN {
tempHead: LeftoverRef ← readHead;
commandBuffer ← readHead.commandBuffer;
currentColorTileLoadAddress←readHead.colorTileLoadAddress;
currentColorType←readHead.colorType;
currentPriority←readHead.priority;
now move this record from readList to availList
readHead←readHead.link;
tempHead.link𡤊vailHead;
availHead←tempHead;
availCount𡤊vailCount+1;
}
ELSE {
commandBuffer ← PDInterpReader.Get[handle];
currentColorTileLoadAddress←handle.colorTileLoadAddress;
currentColorType←handle.colorType;
currentPriority←handle.priority;
};
WITH commandBuffer SELECT FROM
stateChange: CommandBuffer.stateChange => {
SELECT stateChange.whatChanged FROM
imageStart => {
band ← PDInterpOutput.StartImage[handle.herald, handle.image, request];
bandMaxS ← band.sOrigin+band.sMin+band.sSize;
leftovers ← handle.image.leftOverMode;
IF handle.image.nBands = 0 THEN {PDInterpOutput.EndImage[request]};
};
imageEnd => {
[] ← PDInterpOutput.EndBand[];
IF readHead#NIL THEN ERROR; --DEBUGGING CHECK !!
readHead←writeHead;
writeHead←NIL;
FreeList[readHead]; --from this image
FreeList[writeHead]; --from this image
FreeList[availHead];
availCount𡤀
Process.SetPriority[Process.priorityForeground];
PDQueue.DeferSaving[];
PDInterpOutput.EndImage[request];
Process.SetPriority[Process.priorityNormal];
PDQueue.DoDeferredSave[];
RETURN [TRUE];
};
priorityChange => NULL;
colorChange => NULL;
bandChange => {
CheckAbort[];
band ← PDInterpOutput.EndBand[];
bandMaxS�nd.sOrigin+band.sMin+band.sSize;
IF readHead#NIL THEN ERROR; --DEBUGGING CHECK !!
readHead←writeHead;
writeHead←NIL;
};
loadChange => NULL;
documentEnd => {Process.SetPriority[Process.priorityNormal]; RETURN [FALSE]};
ENDCASE => ERROR;
};
maskRectangle: CommandBuffer.maskRectangle => {
TransferRectangle[[maskRectangle.sMin, maskRectangle.fMin, maskRectangle.sSize, maskRectangle.fSize]];
IF leftovers AND maskRectangle.sMin+maskRectangle.sSize>bandMaxS THEN AddLeftover[];
};
maskTrapezoid: CommandBuffer.maskTrapezoid => {
EdgeBlock: TYPE = RECORD [fPos, fIncr: Environment.LongNumber];
MakeEdge: PROC[fMinLast, fMin, sSize: CARDINAL] RETURNS [edge: EdgeBlock] = {
edge.fPos.highbits ← fMin;
edge.fPos.lowbits ← 0;
edge.fIncr.highbits ← fMinLast - fMin;
edge.fIncr.lowbits ← 0;
IF sSize > 1 THEN edge.fIncr.li ← edge.fIncr.li/sSize;
};
fMinBox: CARDINALMIN[maskTrapezoid.fMin, maskTrapezoid.fMinLast];
fMaxBox: CARDINALMAX[maskTrapezoid.fMin+maskTrapezoid.fSize, maskTrapezoid.fMinLast+maskTrapezoid.fSizeLast];
fSizeBox: CARDINAL𡤏MaxBox-fMinBox;
trapMaxS: CARDINAL ← maskTrapezoid.sMin+maskTrapezoid.sSize;
s: CARDINAL ← maskTrapezoid.sMin;
sMinBand: CARDINALMIN[band.sOrigin+band.sMin, maskTrapezoid.sMin+maskTrapezoid.sSize];
sMaxBand: CARDINALMIN[bandMaxS, trapMaxS];
calculate initial edges:
minEdge: EdgeBlock ← MakeEdge[fMinLast: maskTrapezoid.fMinLast, fMin: maskTrapezoid.fMin, sSize: maskTrapezoid.sSize];
maxEdge: EdgeBlock ← MakeEdge[fMinLast: maskTrapezoid.fMinLast+maskTrapezoid.fSizeLast, fMin: maskTrapezoid.fMin+maskTrapezoid.fSize, sSize: maskTrapezoid.sSize];
TempColor[[sMin: maskTrapezoid.sMin, fMin: fMinBox, sSize: maskTrapezoid.sSize, fSize: fSizeBox]];
WHILE s < sMinBand DO
minEdge.fPos.lc ← minEdge.fPos.lc + minEdge.fIncr.li;
maxEdge.fPos.lc ← maxEdge.fPos.lc + maxEdge.fIncr.li;
s ← s + 1;
ENDLOOP;
WHILE s < sMaxBand DO
DoLine[sMin: s, fMin: minEdge.fPos.highbits, fSize: maxEdge.fPos.highbits-minEdge.fPos.highbits];
minEdge.fPos.lc ← minEdge.fPos.lc + minEdge.fIncr.li;
maxEdge.fPos.lc ← maxEdge.fPos.lc + maxEdge.fIncr.li;
s ← s + 1;
ENDLOOP;
TempColor[[sMin: maskTrapezoid.sMin, fMin: fMinBox, sSize: maskTrapezoid.sSize, fSize: fSizeBox]];
IF leftovers AND trapMaxS>bandMaxS THEN AddLeftover[];
};
maskRunGroup: CommandBuffer.maskRunGroup => {
s: CARDINAL ← maskRunGroup.sMin;
sMinBand: CARDINALMIN[band.sOrigin+band.sMin, maskRunGroup.sMin+maskRunGroup.sSize];
sMaxBand: CARDINALMIN[band.sOrigin+band.sMin+band.sSize, maskRunGroup.sMin+maskRunGroup.sSize];
run: LONG POINTER TO PDFileFormat.Run ← maskRunGroup.pointer;
TempColor[[maskRunGroup.sMin, maskRunGroup.fMin, maskRunGroup.sSize, maskRunGroup.fSize]];
WHILE s < sMinBand DO
IF run.lastRun THEN s ← s + 1;
run ← run + SIZE[PDFileFormat.Run];
ENDLOOP;
WHILE s < sMaxBand DO
IF run.fMin+run.fSize > maskRunGroup.fSize THEN ERROR;
DoLine[sMin: s, fMin: run.fMin+maskRunGroup.fOffset, fSize: run.fSize];
IF run.lastRun THEN s ← s + 1;
run ← run + SIZE[PDFileFormat.Run];
ENDLOOP;
TempColor[[maskRunGroup.sMin, maskRunGroup.fMin, maskRunGroup.sSize, maskRunGroup.fSize]];
IF leftovers AND maskRunGroup.loadAddress>=0 AND maskRunGroup.sMin+maskRunGroup.sSize>bandMaxS THEN {
maskRunGroup.sSize←maskRunGroup.sSize-(s-maskRunGroup.sMin);
maskRunGroup.sMin←s;
maskRunGroup.runCount ← -1; --unused, eventually eliminate from DEF
maskRunGroup.pointer←run;
AddLeftover[];
};
};
maskSamples: CommandBuffer.maskSamples => {
rectangle: PDInterpBitmap.Rectangle ← PDInterpBitmap.Window[maskSamples.samples];
TempColor[rectangle];
SELECT currentColorType FROM
none => ERROR;
clear => PDInterpBitmap.Transfer[band, maskSamples.samples, [and, complement]];
opaqueTile, ink => PDInterpBitmap.Transfer[band, maskSamples.samples, [or, null]];
transparentTile => {
bounds: PDInterpBitmap.Rectangle ← PDInterpBitmap.Intersect[rectangle, PDInterpBitmap.Window[band]];
scratchWords: INT ← Inline.LongMult[bounds.sSize, (bounds.fSize+bitsPerWord-1)/bitsPerWord];
buffer: LONG POINTER ←PDInterpSysCalls.AllocateSpace[scratchWords];
destDesc:PDInterpBitmap.BitmapDesc←PDInterpBitmap.Reshape[pointer: buffer, words: scratchWords, bounds: bounds];
GetColorTile[];
PDInterpBitmap.TransferTile[dest: destDesc, tile: cachedColorTile];
PDInterpBitmap.Transfer[destDesc, maskSamples.samples, [and, null]];
PDInterpBitmap.Transfer[band, destDesc, [or, null]];
PDInterpSysCalls.FreeSpace[buffer];
};
ENDCASE => ERROR;
TempColor[rectangle];
IF leftovers AND maskSamples.loadAddress>=0 AND maskSamples.samples.sOrigin+maskSamples.samples.sMin+maskSamples.samples.sSize > bandMaxS THEN AddLeftover[];
};
colorSamples: CommandBuffer.colorSamples => {
PDInterpBitmap.Transfer[band, colorSamples.samples];
};
deviceCommand: CommandBuffer.deviceCommand => {
};
ENDCASE => NULL;
ENDLOOP;
};
scratchPages: INT = 4;
scratchWords: INT ← scratchPages*Environment.wordsPerPage;
scratchPointer: LONG POINTER ← PDInterpSysCalls.AllocateSpace[scratchWords];
END.