PDInterpOutputExpandImpl.mesa
Copyright (C) 1985, Xerox Corporation. All rights reserved.
Michael Plass, January 16, 1985 5:09:10 pm PST
Implements a Cedar PD output device that creates a new, fully instantiatied PD file.
Last Edited by: Gasbarro, June 4, 1985 12:11:49 pm PDT
DIRECTORY Basics, ImagerPixelMaps, PDFileFormat, PDInterpBitmap, PDInterpOutput, PDQueue, IO, FS, Rope, PupDefs, Convert;
PDInterpOutputExpandImpl: PROGRAM
IMPORTS Basics, ImagerPixelMaps, PDQueue, IO, FS, Rope, PupDefs, Convert
EXPORTS PDInterpOutput = BEGIN
ROPE: TYPE ~ Rope.ROPE;
bandMap: ImagerPixelMaps.PixelMap ← [0, 0, 0, 0, 0, 0, NIL];
scratchMap: ImagerPixelMaps.PixelMap ← [0, 0, 0, 0, 0, 0, NIL];
currentStartImage: PDFileFormat.StartImage;
currentHerald: PDFileFormat.Herald;
bandNumber: NAT ← 0;
pdFileStream: IO.STREAMNIL;
requestTime: ROPENIL;
pdFileName: ROPENIL;
workingDirectory: ROPENIL;
pageNumber: INT ← 0;
msgStart: ROPE;
RopeFromString: PROC [name: LONG STRING] RETURNS [ROPE] ~ {
i: INTEGER ← -1;
action: SAFE PROC RETURNS [CHAR] ~ TRUSTED {RETURN [name[i←i+1]]};
RETURN [Rope.FromProc[name.length, action]]
};
GetWorkingDirectory: PROC [] RETURNS [ROPE] ~ {
cp: FS.ComponentPositions;
fullFName: Rope.ROPE;
[fullFName, cp] ← FS.ExpandName["*"];
RETURN [Rope.Substr[fullFName, 0, cp.base.start]]
};
GetFileNameRoot: PROC [name: ROPE] RETURNS [ROPE] ~ {
cp: FS.ComponentPositions;
fullFName: Rope.ROPE;
[fullFName, cp] ← FS.ExpandName[name];
RETURN [Rope.Substr[fullFName, cp.base.start, cp.base.length]]
};
GetCurrentRequestNumber: PROC RETURNS [number: INT ← -1] ~ {
action: PROC [requestNumber: CARDINAL, request: PDQueue.Request, status: PDQueue.RequestStatus] RETURNS [continue: BOOLEANTRUE] ~ {
IF status = printing THEN {number ← requestNumber; continue ← FALSE};
};
PDQueue.EnumerateRequests[action];
};
WriteBlock: PROC [stream: IO.STREAM, addr: LONG POINTER, wordCount: INT] ~ {
IO.UnsafePutBlock[stream, [base: addr, startIndex: 0, count: wordCount*Basics.bytesPerWord]];
};
WriteHerald: PROC [pdFileStream: IO.STREAM, herald: PDFileFormat.Herald] ~ {
herald.maxLoadWord ← 0;
WriteBlock[pdFileStream, @herald, SIZE[PDFileFormat.Herald]];
};
WriteStartImage: PROC [pdFileStream: IO.STREAM, startImage: PDFileFormat.StartImage] ~ {
startImageCommand: PDFileFormat.Command ← [control[startImage]];
WriteBlock[pdFileStream, @startImageCommand, SIZE[PDFileFormat.Command]];
WriteBlock[pdFileStream, @startImage, SIZE[PDFileFormat.StartImage]];
};
StartImage: PUBLIC PROC [herald: PDFileFormat.Herald, startImage: PDFileFormat.StartImage, request: PDQueue.Request] RETURNS [PDInterpBitmap.BitmapDesc] = {
inputName: ROPE ← RopeFromString[request.fileName];
time: ROPE ← RopeFromString[request.requestTime];
bytesPerImage: INT ~ INT[herald.imageFSize]*herald.bandSSize*startImage.nBands/8;
IF NOT time.Equal[requestTime] THEN {pageNumber ← 0; requestTime ← time};
IF startImage.feed THEN {
pageNumber ← pageNumber + 1;
pdFileName ← Rope.Cat[
workingDirectory,
GetFileNameRoot[inputName],
"-",
Convert.RopeFromInt[pageNumber],
".pd"
];
pdFileStream ← FS.StreamOpen[pdFileName, $create];
WriteHerald[pdFileStream, herald];
};
WriteStartImage[pdFileStream, startImage];
IO.SetLength[pdFileStream, IO.GetIndex[pdFileStream]+bytesPerImage];
bandMap ← ImagerPixelMaps.Create[0, [startImage.passBands*herald.bandSSize, startImage.fMinPage, herald.bandSSize, startImage.fSizePage]];
currentStartImage ← startImage;
currentHerald ← herald;
bandNumber ← 0;
bandMap.Clear;
RETURN [[
sOrigin: bandMap.sOrigin,
fOrigin: bandMap.fOrigin,
sMin: bandMap.sMin,
fMin: bandMap.fMin,
sSize: bandMap.sSize,
fSize: bandMap.fSize,
pointer: bandMap.refRep.pointer,
rast: bandMap.refRep.rast,
lines: bandMap.refRep.lines
]]
};
Trim: PROC [pixelMap: ImagerPixelMaps.PixelMap, scratch: REF ImagerPixelMaps.PixelMapRep] RETURNS [ImagerPixelMaps.PixelMap] ~ {
temp: ImagerPixelMaps.PixelMap ← pixelMap;
IsAllZero: PROC [pixelMap: ImagerPixelMaps.PixelMap] RETURNS [BOOLEAN] = {
w: ImagerPixelMaps.DeviceRectangle ← pixelMap.Window;
t: ImagerPixelMaps.PixelMap ← scratch.Reshape[0, w];
t.Clear;
t.Transfer[pixelMap];
TRUSTED {
p: LONG POINTER TO WORD ← t.refRep.pointer;
FOR i: LONG CARDINAL IN [0..Basics.LongMult[pixelMap.refRep.lines, pixelMap.refRep.rast]) DO
IF (p+i)^ # 0 THEN RETURN [FALSE];
ENDLOOP;
};
RETURN [TRUE]
};
WHILE pixelMap.sSize > 0 DO
temp.sSize ← 1;
temp.sMin ← pixelMap.sMin+pixelMap.sSize-1;
IF IsAllZero[temp] THEN {pixelMap.sSize ← pixelMap.sSize - 1}
ELSE EXIT;
ENDLOOP;
WHILE pixelMap.sSize > 0 DO
temp.sSize ← 1;
temp.sMin ← pixelMap.sMin;
IF IsAllZero[temp] THEN {pixelMap.sSize ← pixelMap.sSize - 1; pixelMap.sMin ← pixelMap.sMin + 1}
ELSE EXIT;
ENDLOOP;
IF pixelMap.sSize = 0 THEN pixelMap.fSize ← 0;
temp ← pixelMap;
WHILE pixelMap.fSize > 0 DO
temp.fSize ← 1;
temp.fMin ← pixelMap.fMin+pixelMap.fSize-1;
IF IsAllZero[temp] THEN {pixelMap.fSize ← pixelMap.fSize - 1}
ELSE EXIT;
ENDLOOP;
WHILE pixelMap.fSize > 0 DO
temp.fSize ← 1;
temp.fMin ← pixelMap.fMin;
IF IsAllZero[temp] THEN {pixelMap.fSize ← pixelMap.fSize - 1; pixelMap.fMin ← pixelMap.fMin + 1}
ELSE EXIT;
ENDLOOP;
IF pixelMap.fSize = 0 THEN pixelMap.sSize ← 0;
RETURN [pixelMap]
};
EndBand: PUBLIC PROC RETURNS [PDInterpBitmap.BitmapDesc] = {
trimmedBand: ImagerPixelMaps.PixelMap ← Trim[bandMap, scratchMap.refRep];
endBandCommand: PDFileFormat.Command ← [control[endBand]];
IF trimmedBand.sSize > 0 THEN {
w: ImagerPixelMaps.DeviceRectangle ← trimmedBand.Window;
colorCommand: PDFileFormat.Command ← [imaging[colorSamples]];
args: PDFileFormat.ColorSamples ← [
sMin: w.sMin,
fMin: w.fMin
];
sampleArray: PDFileFormat.SampleArray ← [
sSize: w.sSize,
fSize: w.fSize
];
scratchMap ← scratchMap.refRep.Reshape[0, w];
scratchMap.Clear;
scratchMap.Transfer[trimmedBand];
WriteBlock[pdFileStream, @colorCommand, SIZE[PDFileFormat.Command]];
WriteBlock[pdFileStream, @args, SIZE[PDFileFormat.ColorSamples]];
WriteBlock[pdFileStream, @sampleArray, SIZE[PDFileFormat.SampleArray]];
WriteBlock[pdFileStream, scratchMap.refRep.pointer, Basics.LongMult[scratchMap.refRep.rast, w.sSize]];
};
WriteBlock[pdFileStream, @endBandCommand, SIZE[PDFileFormat.Command]];
bandNumber ← bandNumber + 1;
bandMap ← bandMap.ShiftMap[currentHerald.bandSSize, 0];
bandMap.Clear;
IF bandNumber > currentStartImage.nBands THEN ERROR;
RETURN [[
sOrigin: bandMap.sOrigin,
fOrigin: bandMap.fOrigin,
sMin: bandMap.sMin,
fMin: bandMap.fMin,
sSize: bandMap.sSize,
fSize: bandMap.fSize,
pointer: bandMap.refRep.pointer,
rast: bandMap.refRep.rast,
lines: bandMap.refRep.lines
]]
};
EndImage: PUBLIC PROC [request: PDQueue.Request] = {
IF currentStartImage.strip THEN {
endDocumentCommand: PDFileFormat.Command ← [control[endDocument]];
rope: ROPE ~ msgStart.Concat[pdFileName.Substr[4]];
message: LONG STRING = [200];
FOR i: INT IN [0..rope.Length) DO
message[i] ← rope.Fetch[i];
ENDLOOP;
message.length ← rope.Length;
WriteBlock[pdFileStream, @endDocumentCommand, SIZE[PDFileFormat.Command]];
IO.SetLength[pdFileStream, IO.GetIndex[pdFileStream]];
pdFileStream.Close;
pdFileStream ← NIL;
bandMap.refRep ← scratchMap.refRep ← NIL;
PDQueue.LogMessage[message, GetCurrentRequestNumber[], request.requestor];
};
};
ReprintLastPage: PUBLIC PROC [copies: CARDINAL] = {
};
ReadQueue: PROC [address: LONG POINTER, nwords: CARDINAL] = TRUSTED {
stream: IO.STREAM;
stream ← FS.StreamOpen["[]<>PeachExpand.queue", $read, ALL[FALSE] ! FS.Error => CONTINUE];
IF stream#NIL THEN {
[] ← stream.UnsafeGetBlock[[base: address, startIndex: 0, count: nwords*2]];
stream.Close;
};
};
WriteQueue: PROC [address: LONG POINTER, nwords: CARDINAL] = TRUSTED {
stream: IO.STREAMFS.StreamOpen["[]<>PeachExpand.queue", $create];
[] ← stream.UnsafePutBlock[[base: address, startIndex: 0, count: nwords*2]];
stream.Close;
};
RegisterDisk: PROC = {PDQueue.RegisterDisk[ReadQueue, WriteQueue, 16*1024]};
Init: PROC ~ {
RegisterDisk[];
workingDirectory ← GetWorkingDirectory[];
msgStart ← IO.PutFR["Output page: [%g]<Cedar>", IO.rope[PupDefs.GetMyName[]]];
};
Init[];
END.