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
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.STREAM ← NIL;
requestTime: ROPE ← NIL;
pdFileName: ROPE ← NIL;
workingDirectory: ROPE ← NIL;
pageNumber: INT ← 0;
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:
BOOLEAN ←
TRUE] ~ {
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.STREAM ← FS.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[]]];
};
END.