-- ColorVersatecInterpOutputImpl.mesa
-- Copyright (C) 1984, Xerox Corporation. All rights reserved.
-- Michael Plass, October 31, 1984 12:56:16 pm PST
DIRECTORY Environment, PDFileFormat, PDInterpBasic, PDInterpOutput, PDInterpBitmap, PDDeviceDriver, PDQueue, PDInterpSysCalls, Process, ProcessorFace, PDTextBitmap, PDRemoteStream;
ColorVersatecInterpOutputImpl: PROGRAM
IMPORTS PDInterpBitmap, PDDeviceDriver, PDInterpSysCalls, PDQueue, PDTextBitmap, PDRemoteStream
EXPORTS PDInterpOutput
= BEGIN
bitsPerWord: NAT = Environment.bitsPerWord;
currentHerald: PDFileFormat.Herald;
currentStartImage: PDFileFormat.StartImage;
currentBandNumber: NAT ← 0;
bandWords: INT ← 0;
band: PDInterpBitmap.BitmapDesc ← [sOrigin: 0, fOrigin: 0, sMin: 0, fMin: 0, sSize: 0, fSize: 0, pointer: NIL, rast: 0, lines: 0];
bandWordsAllocated: INT ← 0;
extraBands: NAT ← 12;
fontFileName: LONG STRING ← "[Indigo]<Peach>Fonts>TimesRoman36B.ks";
leadingTitleBlockBands: NAT ← 4;
CurrentBandDesc: PROC RETURNS [PDInterpBitmap.BitmapDesc] = {
band.sOrigin ← currentHerald.bandSSize*(currentBandNumber+currentStartImage.passBands);
PDInterpBitmap.Clear[band];
RETURN [band]
};
StartImage: PUBLIC PROC [herald: PDFileFormat.Herald, startImage: PDFileFormat.StartImage, request: PDQueue.Request]
RETURNS [PDInterpBitmap.BitmapDesc] = {
rast: NAT = (--startImage.fSizePage-- 8000 +bitsPerWord-1)/bitsPerWord;
lines: INT = herald.bandSSize;
words: INT = rast*lines;
color: PDDeviceDriver.Color ← SELECT startImage.toner FROM
black => Black,
cyan => Cyan,
magenta => Magenta,
yellow => Yellow,
ENDCASE => ERROR;
currentHerald ← herald;
currentStartImage ← startImage;
currentBandNumber ← 0;
IF words > bandWordsAllocated THEN {
IF band.pointer # NIL THEN PDInterpSysCalls.FreeSpace[band.pointer];
band.pointer ← PDInterpSysCalls.AllocateSpace[words];
bandWordsAllocated ← words;
};
band.sOrigin ← 0;
band.fOrigin ← 0; -- startImage.fMinPage;
band.sMin ← 0;
band.fMin ← 0;
band.sSize ← herald.bandSSize;
band.fSize ← rast*bitsPerWord;
band.rast ← rast;
band.lines ← herald.bandSSize;
bandWords ← words;
IF currentStartImage.feed THEN {
passBands ← ALL[LAST[NAT]];
nBands ← ALL[0];
};
passBands[color] ← currentStartImage.passBands;
nBands[color] ← currentStartImage.nBands;
RETURN [CurrentBandDesc[]]
};
EndBand: PUBLIC PROC RETURNS [PDInterpBitmap.BitmapDesc] = {
PDDeviceDriver.StoreBand[
sourcePtr: band.pointer,
destOffset: bandWords*currentBandNumber,
wordCount: bandWords,
color: SELECT currentStartImage.toner FROM
black => Black,
cyan => Cyan,
magenta => Magenta,
yellow => Yellow,
ENDCASE => ERROR
];
currentBandNumber ← currentBandNumber + 1;
RETURN [CurrentBandDesc[]]
};
passBands: ARRAY PDDeviceDriver.Color OF NAT;
nBands: ARRAY PDDeviceDriver.Color OF NAT;
TryToLoadFont: PROC [request: PDQueue.Request] = {
IF PDTextBitmap.FontAscent[] = 0 THEN {
ok: BOOL ← FALSE;
accessError: BOOL ← FALSE;
ok ← PDTextBitmap.SetFont[fontFileName, request.requestor, request.requestorPassword ! PDRemoteStream.Error => {accessError ← TRUE; CONTINUE}];
IF NOT ok THEN {
IF accessError THEN
PDQueue.LogMessage["Could not access font file for title block:",,request.requestor]
ELSE
PDQueue.LogMessage["Invalid font file for title block:",,request.requestor];
PDQueue.LogMessage[fontFileName];
RETURN
};
};
};
DoTitleBlock: PROC [request: PDQueue.Request] = {
ascent: INTEGER ← PDTextBitmap.FontAscent[];
descent: INTEGER ← PDTextBitmap.FontDescent[];
topMargin: INTEGER ← (band.sSize-ascent+descent)/2;
titleBand: PDInterpBitmap.BitmapDesc ← PDInterpBitmap.Reshape[band.pointer, bandWordsAllocated, [-topMargin-ascent, 0, band.sSize, band.fSize]];
empty: LONG STRING ← [0];
margin: INTEGER ← ascent;
tabw: CARDINAL ← MAX[ascent+descent, 1] * 10;
centeredString: LONG STRING ← IF request.separator.length = 0 THEN request.fileName ELSE request.separator;
penultimateString: LONG STRING ← IF request.separator.length = 0 THEN request.separator ELSE request.fileName;
string: ARRAY [0..5) OF LONG STRING ← [request.requestor, request.requestTime, centeredString, penultimateString, request.requestor];
pos: ARRAY [0..5) OF INTEGER ← ALL[0];
TryLayout: PROC RETURNS [ok: BOOLEAN] = {
spaceLeft: INTEGER ← titleBand.fSize;
wid: ARRAY [0..5) OF INTEGER;
glue: ARRAY [0..5) OF INTEGER;
FOR i: NAT IN [0..5) DO
wid[i] ← PDTextBitmap.TextWidth[string[i]];
ENDLOOP;
FOR i: NAT IN [0..5) DO
glue[i] ← IF wid[i] = 0 THEN 0 ELSE PDTextBitmap.TextWidth[" "];
ENDLOOP;
glue[4] ← margin;
glue[0] ← MAX[glue[0]+wid[0], tabw]-wid[0];
glue[3] ← IF glue[3]+wid[4] = 0 THEN 0 ELSE MAX[glue[3]+wid[4], tabw]-wid[4];
spaceLeft ← spaceLeft - margin;
FOR i: NAT IN [0..5) DO
spaceLeft ← spaceLeft - wid[i] - glue[i];
ENDLOOP;
IF spaceLeft < 0 THEN RETURN [FALSE];
glue[1] ← glue[1] + spaceLeft/2;
glue[2] ← glue[2] + (spaceLeft-spaceLeft/2);
pos[0] ← margin;
FOR i: NAT IN [0..4) DO
pos[i+1] ← pos[i]+wid[i]+glue[i];
ENDLOOP;
RETURN [TRUE];
};
DoLayout: PROC = {
IF TryLayout[].ok THEN RETURN;
string[4] ← empty;
IF TryLayout[].ok THEN RETURN;
string[3] ← empty;
IF TryLayout[].ok THEN RETURN;
string[1] ← empty;
IF TryLayout[].ok THEN RETURN;
string[2] ← empty;
pos[0] ← margin;
};
totalBands: NAT ← 0;
FOR c: PDDeviceDriver.Color IN PDDeviceDriver.Color DO
IF passBands[c] # NAT.LAST THEN
totalBands ← MAX[totalBands, passBands[c] + nBands[c]];
ENDLOOP;
currentBandNumber ← nBands[Black];
DoLayout[];
PDInterpBitmap.Clear[titleBand];
WHILE passBands[Black] + currentBandNumber < totalBands + extraBands DO
PDDeviceDriver.StoreBand[
sourcePtr: titleBand.pointer,
destOffset: bandWords*currentBandNumber,
wordCount: bandWords,
color: Black
];
currentBandNumber ← currentBandNumber + 1;
ENDLOOP;
PDInterpBitmap.Fill[titleBand, titleBand.Window, 1];
FOR i: NAT IN [0..5) DO
PDTextBitmap.TextToBitmap[dest: titleBand.ShiftMap[0, -pos[i]], string: string[i], function: [and, complement]];
ENDLOOP;
PDDeviceDriver.StoreBand[
sourcePtr: titleBand.pointer,
destOffset: bandWords*currentBandNumber,
wordCount: bandWords,
color: Black,
isSeparatorBand: TRUE
];
currentBandNumber ← currentBandNumber + 1;
nBands[Black] ← currentBandNumber;
};
EndImage: PUBLIC PROC [request: PDQueue.Request] = {
IF currentStartImage.strip THEN {
minPass: NAT ← LAST[NAT];
FOR c: PDDeviceDriver.Color IN PDDeviceDriver.Color DO
minPass ← MIN[passBands[c], minPass];
ENDLOOP;
FOR c: PDDeviceDriver.Color IN PDDeviceDriver.Color DO
IF passBands[c] # NAT.LAST THEN passBands[c] ← passBands[c] - minPass + leadingTitleBlockBands;
ENDLOOP;
TryToLoadFont[request];
IF PDTextBitmap.FontAscent[] # 0 THEN DoTitleBlock[request];
PrintPage[];
};
};
PrintPage: PROC = {
successCode: PDDeviceDriver.SuccessCode;
scanLineLength: CARDINAL ← band.fSize;
FOR copyNum: CARDINAL IN [0..currentHerald.copies) DO
DO
s: PDDeviceDriver.PrinterStatus;
successCode ← PDDeviceDriver.PrintPage[
passBands: passBands,
nBands: nBands,
fourColor: currentStartImage.toner#black
];
IF PDQueue.ReprintCancelled[] THEN RETURN;
SELECT successCode FROM
warning => EXIT;
error => {
WHILE (s←PDDeviceDriver.GetStatus[])#standBy DO
PDDeviceDriver.DisplayBadStatusInMP[s];
SELECT s FROM
registrationJam => PDQueue.LogMessage[" - Registration jam"];
fuserJam => PDQueue.LogMessage[" - Fuser jam"];
warming => PDQueue.LogMessage[" - Warming up"];
feederFault => PDQueue.LogMessage[" - Out of paper"];
interlockOpen => PDQueue.LogMessage[" - Door open"];
fuserCold => PDQueue.LogMessage[" - Fuser cold"];
parityError => PDQueue.LogMessage[" - Parity Error"];
offLine => PDQueue.LogMessage[" - Offline"];
ENDCASE => PDQueue.LogMessage[" - Can't feed page"];
ENDLOOP
};
ENDCASE => EXIT; -- ok
ENDLOOP;
ENDLOOP;
};
ReprintLastPage: PUBLIC PROC [copies: CARDINAL] = {
IF currentHerald.password # PDFileFormat.passwordValue THEN RETURN;
IF PDQueue.ReprintCancelled[] THEN RETURN;
currentHerald.copies ← copies;
PrintPage[];
};
END.