DIRECTORY Basics, PrincOpsUtils, MessageWindow, TapeOps, PDFileFormat, PDInterpSysCalls, PDInterpBitmap, PDInterpOutput, PDQueue, Rope ; PDInterpOutputTapeImpl: CEDAR PROGRAM IMPORTS PrincOpsUtils, MessageWindow, PDInterpBitmap, PDInterpSysCalls, TapeOps EXPORTS PDInterpOutput = BEGIN bpi: CARDINAL _ 200; pageWidthInches: CARDINAL _ 40; white: CARDINAL = 0; bitsPerWord: NAT = Basics.bitsPerWord; bytesPerWord: NAT = Basics.bytesPerWord; wordsPerScan: CARDINAL = ((bpi * pageWidthInches) + bitsPerWord - 1) / bitsPerWord; scansPerBand: CARDINAL _ 64; wordsPerBand: LONG CARDINAL = LONG[wordsPerScan] * LONG[scansPerBand]; currentHerald: PDFileFormat.Herald; currentStartImage: PDFileFormat.StartImage; currentBandNumber: NAT _ 0; bandWords: NAT _ 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; tapeHandle: TapeOps.TapeHandle _ NIL; preamble: REF ColorPreamble; ColorPreamble: TYPE = MACHINE DEPENDENT RECORD [ escape: [0..256) _ 9BH, -- escape header: CHARACTER, byteCountHigh: [0..256) _ 0, byteCountLow: [0..256) _ 4, lengthHigh: [0..256) _ 0, lengthLow: [0..256) _ 0, modeAndColor: ModeAndColor, reserved: [0..256) _ 0, padding: Bytepad --tape wants first record padded to 32 bytes ]; Bytepad: TYPE = ARRAY [0..12) OF CARDINAL; pad: Bytepad = ALL[0]; Color: TYPE = MACHINE DEPENDENT {Black(0), Cyan(1), Magenta(2), Yellow(3)}; ColorMode: TYPE = MACHINE DEPENDENT { SinglePassOfColor(0), FirstPassOfColor(1), IntermediatePassOfColor(2), (3)}; ModeAndColor: TYPE = MACHINE DEPENDENT RECORD [ padding: [0..16) _ 0, --4 bits of padding mode: ColorMode, --2 bit field color: Color _ Black ]; --2 bit field CurrentBandDesc: PROC RETURNS [PDInterpBitmap.BitmapDesc] = TRUSTED { 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] = { IF taping THEN { rast: NAT = (--startImage.fSizePage-- (bpi*pageWidthInches)+bitsPerWord-1)/bitsPerWord; lines: INT = herald.bandSSize; words: INT = rast*lines; mode: ColorMode _ IF NOT startImage.feed THEN IntermediatePassOfColor ELSE IF startImage.strip THEN SinglePassOfColor ELSE FirstPassOfColor; color: 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 TRUSTED { 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 bandWords MOD bufferWords # 0 THEN ERROR; IF currentStartImage.feed THEN { --start of new page tapeHandle _ InitializeTape[]; }; preamble _ MakeColorPreamble[inches: IF color=Black THEN LongestColor[]+2 ELSE 0, mode: mode, color: color]; TRUSTED {PutBlock[source: LOOPHOLE[preamble], words: SIZE[ColorPreamble]];}; IF passBands[color]#0 THEN SendWhiteSpace[bands: passBands[color]] } ELSE { --first pass to find images sizes and white space rast: NAT = (--startImage.fSizePage-- (bpi*pageWidthInches)+bitsPerWord-1)/bitsPerWord; lines: INT = herald.bandSSize; words: INT = rast*lines; color: 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 TRUSTED { 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 bandWords MOD bufferWords # 0 THEN ERROR; buffersPerBand _ bandWords/bufferWords; --THIS MUST HAVE ZERO REMAINDER IF currentStartImage.feed THEN { --start of new page, so initialize separation arrays passBands _ ALL[LAST[NAT]]; nBands _ ALL[0]; }; passBands[color] _ currentStartImage.passBands; nBands[color] _ currentStartImage.nBands; }; RETURN [CurrentBandDesc[]]; }; MakeColorPreamble: PROC [inches: CARDINAL, mode: ColorMode, color: Color _ Black] RETURNS [preamble: REF ColorPreamble] = { preamble _ NEW[ColorPreamble _ [ header: 'P, -- color header preamble lengthLow: inches, -- length in inches modeAndColor: [mode: mode, color: color], padding: pad ]]; }; PutBlock: PROC [source: LONG POINTER, words: NAT] = TRUSTED { tapeStatus: TapeOps.TapeStatus; loopCount: NAT _ words/bufferWords; --whole number of full buffers lastBuffer: NAT _ words MOD bufferWords; --words in final, unfilled buffer IF words > bandWordsAllocated THEN ERROR; FOR count: NAT IN [0..loopCount) DO MoveWordsToBuffer[from: source+LONG[bufferWords]*LONG[count], words: bufferWords]; tapeStatus _ TapeOps.WriteRecord[tapeHandle: tapeHandle, writeData: textBuffer]; IF tapeStatus[EOT] THEN ERROR; ENDLOOP; IF lastBuffer#0 THEN { MoveWordsToBuffer[from: source+LONG[bufferWords]*LONG[loopCount], words: lastBuffer]; tapeStatus _ TapeOps.WriteRecord[tapeHandle: tapeHandle, writeData: textBuffer]; IF tapeStatus[EOT] THEN ERROR; }; }; MoveWordsToBuffer: PROC [from: LONG POINTER, words: NAT] = TRUSTED { IF words > textBuffer.maxLength/2 THEN ERROR; textBuffer.length _ words*2; PrincOpsUtils.LongCopy[from: from, to: bufferData, nwords: words]; }; EndBand: PUBLIC PROC RETURNS [PDInterpBitmap.BitmapDesc] = TRUSTED { IF taping THEN PutBlock[source: band.pointer, words: bandWords]; currentBandNumber _ currentBandNumber + 1; RETURN [CurrentBandDesc[]] }; EndImage: PUBLIC PROC [request: PDQueue.Request] = { IF currentStartImage.strip THEN { -- all images completed for this page minPass: NAT _ LAST[NAT]; FOR c: Color IN Color DO minPass _ MIN[passBands[c], minPass]; ENDLOOP; FOR c: Color IN Color DO IF passBands[c] # NAT.LAST THEN passBands[c] _ passBands[c] - minPass; ENDLOOP; IF taping THEN FinalizeTape[tapeHandle]; taping _ NOT taping; } ELSE IF taping THEN { tapeStatus: TapeOps.TapeStatus; tapeStatus _ TapeOps.WriteFileMark[tapeHandle]; --file mark between separations IF tapeStatus[EOT] THEN ERROR; }; }; LongestColor: PROC [] RETURNS [inches: CARDINAL] = { inches _ 0; FOR c: Color IN Color DO inches _ MAX[inches, ((passBands[c] + nBands[c]) * scansPerBand) / bpi]; ENDLOOP; }; SendWhiteSpace: PROC [bands: CARDINAL] = TRUSTED { PrincOpsUtils.LongZero[where: bufferData, nwords: bufferWords]; FOR i: CARDINAL IN [0..bands) DO FOR j: CARDINAL IN [0..buffersPerBand) DO PutBlock[source: bufferData, words: bufferWords]; ENDLOOP; ENDLOOP; }; InitializeTape: PROC RETURNS [tapeHandle: TapeOps.TapeHandle] = { ENABLE TapeOps.TapeOpsError => { IF tapeHandle#NIL THEN TapeOps.CloseDrive[tapeHandle]; ERROR}; tapeStatus: TapeOps.TapeStatus; tapeHandle _ TapeOps.OpenDrive[serverName: serverName, driveNumber: driveNumber, density: density]; tapeStatus _ TapeOps.GetStatus[tapeHandle]; UNTIL tapeStatus[RDY] DO MessageWindow.Append[message: "Tape Drive Not Ready", clearFirst: TRUE]; MessageWindow.Blink[]; tapeStatus _ TapeOps.GetStatus[tapeHandle]; ENDLOOP; }; FinalizeTape: PROC [tapeHandle: TapeOps.TapeHandle] = { ENABLE TapeOps.TapeOpsError => {TapeOps.CloseDrive[tapeHandle]; ERROR}; tapeStatus: TapeOps.TapeStatus; tapeStatus _ TapeOps.WriteFileMark[tapeHandle]; IF tapeStatus[EOT] THEN ERROR; tapeStatus _ TapeOps.WriteFileMark[tapeHandle]; --need two file marks IF tapeStatus[EOT] THEN ERROR; tapeStatus _ TapeOps.Rewind[tapeHandle]; IF tapeStatus[EOT] THEN ERROR; TapeOps.CloseDrive[tapeHandle]; }; SetTapeServer: PROC [serverNameL: Rope.ROPE _ "Maggie", driveNumberL: NAT _ 0, densityL: TapeOps.Density _ PE1600] = { serverName _ serverNameL; driveNumber _ driveNumberL; density _ densityL; }; serverName: Rope.ROPE _ "Maggie"; driveNumber: NAT _ 0; density: TapeOps.Density _ PE1600; taping: BOOLEAN _ FALSE; --true if second pass and writing tapes passBands: ARRAY Color OF NAT; nBands: ARRAY Color OF NAT; bufferData: LONG POINTER; bufferBytes: NAT = 16000; --16 scanline buffer bufferWords: NAT = bufferBytes/bytesPerWord; bufferPad: NAT = 10; --just for debugging textBuffer: REF TEXT _ NEW[TEXT[bufferBytes+bufferPad]]; buffersPerBand: NAT _ 0; --MUST BE AN INTEGRAL NUMBER OF BUFFERS PER BAND textBuffer.length _ bufferBytes; TRUSTED {bufferData _ LOOPHOLE[textBuffer, LONG POINTER]+SIZE[TEXT[0]];}; END. PDInterpOutputTapeImpl.mesa Last edited by Ken Pier, May 9, 1986 2:01:48 pm PDT Plotter constants PrincOpsUtils.LongZero[where: bufferData, nwords: bufferWords]; look at ColorVersatecInterpOutputImpl which deals with XDE stuff band by band look at PDInterpOutputViewerImpl to see how to get along in the Cedar world with ImagerPixelMaps. Combine the two, and then put in the tape file streams and control commands. Think about naming and size of files. Write a test tape BY HAND with four solid rectangles and send to Versatec. Ê  ˜Icodešœ™K™3K˜šÏk ˜ Kšœ}˜}K˜—K˜šÏnœœ˜%KšœH˜OKšœ˜K˜Kšœ™Kšœœ˜Kšœœ˜Kšœœ˜Kšœ œ˜&Kšœœ˜(Kšœœ=˜SKšœœ˜Kš œœœœœ˜FK˜#K˜+Kšœœ˜Kšœ œ˜Kšœjœ˜‚Kšœœ˜Kšœ!œ˜%K˜Kšœ œ˜Kšœœœ œœÏc œ œ¼Ÿ-œ˜ÒKš œ œœ œœ˜*Kšœœ˜K˜Kšœœœ œ,˜KK˜Kšœ œœ œP˜sK˜Kšœœœ œœŸœŸœŸ ˜¦K˜šžœœœœ˜EK˜WK˜Kšœ˜ K˜K˜—K˜šž œœœ^œ ˜œšœœ˜KšœœŸœ2˜WKšœœ˜Kšœœ˜Kšœœœœœœœœ˜Œšœœ˜+K˜K˜ K˜K˜Kšœœ˜—K˜K˜K˜šœœœ˜,Kšœœœ*˜DK˜5K˜K˜—K˜KšœŸ˜)K˜K˜K˜K˜K˜K˜K˜Kšœ œœœ˜,šœœŸ˜4K˜K˜—Kšœ%œ œœ˜lKšœœœ˜LKšœœ(˜BKšœ˜—šœŸ1˜8KšœœŸœ2˜WKšœœ˜Kšœœ˜šœœ˜+K˜K˜ K˜K˜Kšœœ˜—K˜K˜K˜šœœœ˜,Kšœœœ*˜DK˜5K˜K˜—K˜KšœŸ˜)K˜K˜K˜K˜K˜K˜K˜Kšœ œœœ˜,Kšœ)Ÿ˜HšœœŸ4˜UKšœ œœœ˜Kšœ œ˜K˜—K˜/K˜)Kšœ˜—Kšœ˜K˜K˜—K˜š žœœ œ)œ œ˜{Kšœ œ ŸœŸœ:˜©Kšœ˜—K˜š žœœ œœ œœ˜>Kšœ˜Kšœ œŸ˜BKšœ œ œŸ!˜JKšœœœ˜)šœœœ˜#Kšœœœ˜RKšœP˜PKšœ œœœ˜Kšœ˜—šœœ˜Kšœ?™?Kšœœœ ˜UKšœP˜PKšœ œœœ˜K˜—K˜—K˜š žœœœœ œœ˜EKšœ!œœ˜.Kšœ˜KšœB˜BK˜—K˜š žœœœœœ˜DKšœœ2˜@K˜*Kšœ˜K˜K˜—K˜šžœœœ˜4šœœŸ%˜GKšœ œœœ˜šœ œ˜Kšœ œ˜%Kšœ˜—šœ œ˜Kšœœœœ'˜FKšœ˜—Kšœœ˜(Kšœ œ˜K˜—šœœœ˜Kšœ˜Kšœ0Ÿ˜OKšœ œœœ˜K˜—K˜—K˜šž œœœ œ˜4Kšœ ˜ Kšœ œ˜Kšœ œ<˜HKšœ˜K˜—K˜šžœœ œœ˜2Kšœ?˜?šœœœ ˜ šœœœ˜)Kšœ1˜1Kšœ˜—Kšœ˜—K˜—K˜šžœœœ%˜Ašœ˜ Kšœ œœ!œ˜>K˜—Kšœ˜Kšœd˜dKšœ+˜+šœ œœ˜KšœBœ˜HKšœ˜Kšœ+˜+Kšœ˜—K˜—K˜šž œœ%˜7Kšœ:œ˜GKšœ˜Kšœ/˜/Kšœ œœœ˜Kšœ0Ÿ˜EKšœ œœœ˜Kšœ(˜(Kšœ œœœ˜Kšœ˜K˜—K˜šž œœœœ-˜vKšœI˜IK˜—K˜Kšœœ ˜!Kšœ œ˜Kšœ"˜"K˜KšœœœŸ'˜@Kšœ œœœ˜Kšœœœœ˜K˜Kšœ œœ˜Kšœ œ Ÿ˜/Kšœ œ˜,Kšœ œŸ˜*Kš œ œœœœ˜8KšœœŸ0˜IKšœ ˜ Kš œœ œœœœ˜IK˜Kšœ˜—K˜KšœM™MK™ÔK™K™JK™—…—"Ä.|