PDInterpOutputExpandImpl.mesa
Copyright (C) 1985, Xerox Corporation. All rights reserved.
Implements a Cedar PD output device that creates a new, fully instantiatied PD file.
Michael Plass, December 23, 1985 5:26:11 pm PST
Last Edited by: Gasbarro, June 23, 1986 12:18:34 pm PDT
Pier, July 2, 1985 6:11:52 pm PDT
DIRECTORY Basics, SampleMapOps, PDFileFormat, PDInterpBitmap, PDInterpOutput, PDQueue, IO, FS, Rope, PupName, Convert;
PDInterpOutputExpandImpl: PROGRAM
IMPORTS SampleMapOps, PDQueue, IO, FS, Rope, PupName, Convert
EXPORTS PDInterpOutput = BEGIN
ROPE: TYPE ~ Rope.ROPE;
bandMap: SampleMapOps.SampleMap ← NIL;
bandMapOrigin: SampleMapOps.CVEC ← [0, 0];
currentStartImage: PDFileFormat.StartImage;
currentHerald: PDFileFormat.Herald;
bandNumber: NAT ← 0;
pdFileStream: IO.STREAMNIL;
requestTime: ROPENIL;
pdFileName: ROPENIL;
workingDirectory: ROPENIL;
pageNumber: INT ← 0;
msgStart: ROPENIL;
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 ← SampleMapOps.Create[sSize: herald.bandSSize, fSize: startImage.fSizePage, bitsPerSample: 1];
currentStartImage ← startImage;
currentHerald ← herald;
bandNumber ← 0;
bandMapOrigin ← [s: startImage.passBands*herald.bandSSize, f: startImage.fMinPage];
SampleMapOps.Clear[bandMap];
RETURN [[
sOrigin: bandMapOrigin.s,
fOrigin: bandMapOrigin.f,
sMin: 0,
fMin: 0,
sSize: bandMap.sSize,
fSize: bandMap.fSize,
pointer: bandMap.base.word,
rast: (bandMap.bitsPerLine+Basics.bitsPerWord-1)/Basics.bitsPerWord,
lines: bandMap.sSize
]]
};
EndBand: PUBLIC PROC RETURNS [PDInterpBitmap.BitmapDesc] = {
trimmedBand: SampleMapOps.SubMap ← SampleMapOps.Trim[[bandMap]];
endBandCommand: PDFileFormat.Command ← [control[endBand]];
IF trimmedBand.size.s > 0 THEN {
scratch: SampleMapOps.SampleMap ~ SampleMapOps.ObtainScratch[sSize: trimmedBand.size.s, fSize: trimmedBand.size.f, bitsPerSample: 1];
colorCommand: PDFileFormat.Command ← [imaging[colorSamples]];
args: PDFileFormat.ColorSamples ← [
sMin: bandMapOrigin.s+trimmedBand.start.s,
fMin: bandMapOrigin.f+trimmedBand.start.f
];
sampleArray: PDFileFormat.SampleArray ← [
sSize: trimmedBand.size.s,
fSize: trimmedBand.size.f
];
SampleMapOps.Clear[scratch];
SampleMapOps.Transfer[dest: scratch, source: trimmedBand];
WriteBlock[pdFileStream, @colorCommand, SIZE[PDFileFormat.Command]];
WriteBlock[pdFileStream, @args, SIZE[PDFileFormat.ColorSamples]];
WriteBlock[pdFileStream, @sampleArray, SIZE[PDFileFormat.SampleArray]];
WriteBlock[pdFileStream, scratch.base.word, SampleMapOps.ComputeWords[sSize: scratch.sSize, fSize: scratch.fSize, bitsPerSample: 1]];
SampleMapOps.ReleaseScratch[scratch];
};
WriteBlock[pdFileStream, @endBandCommand, SIZE[PDFileFormat.Command]];
bandNumber ← bandNumber + 1;
bandMapOrigin.s ← bandMapOrigin.s + currentHerald.bandSSize;
SampleMapOps.Clear[bandMap];
IF bandNumber > currentStartImage.nBands THEN ERROR;
RETURN [[
sOrigin: bandMapOrigin.s,
fOrigin: bandMapOrigin.f,
sMin: 0,
fMin: 0,
sSize: bandMap.sSize,
fSize: bandMap.fSize,
pointer: bandMap.base.word,
rast: (bandMap.bitsPerLine+Basics.bitsPerWord-1)/Basics.bitsPerWord,
lines: bandMap.sSize
]]
};
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 ← 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[PupName.MyName[]]];
};
Init[];
END.