-- 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.