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