<> <> DIRECTORY Environment, FileIO, IO, PDFileFormat, PDFileWriter, Rope ; PDFileWriterImpl: CEDAR PROGRAM IMPORTS FileIO, IO EXPORTS PDFileWriter = BEGIN bytesPerWord: CARDINAL = Environment.bytesPerWord; bitsPerWord: CARDINAL = Environment.bitsPerWord; ROPE: TYPE = Rope.ROPE; LoadReference: TYPE = LONG CARDINAL; DeliverRunGroupProc: TYPE = PDFileWriter.DeliverRunGroupProc; CaptureRunProc: TYPE = PDFileWriter.CaptureRunProc; DeliverSampleArrayProc: TYPE = PDFileWriter.DeliverSampleArrayProc; CaptureScanLineProc: TYPE = PDFileWriter.CaptureScanLineProc; TFlag: TYPE = PDFileWriter.TFlag; Toner: TYPE = PDFileFormat.Toner; maxLoadSize: CARDINAL = 16000; LoadRec: TYPE = ARRAY [0..maxLoadSize) OF WORD; Bands: TYPE = REF BandsRec; BandsRec: TYPE = RECORD [ bands: SEQUENCE maxBands: NAT OF Band ]; Band: TYPE = RECORD [ colorId: INT, bandBuffers: BandBuffer ]; bandBufferSize: NAT = 1000; BandBuffer: TYPE = REF BandBufferRec; BandBufferRec: TYPE = RECORD [ link: BandBuffer, length: NAT _ 0, word: ARRAY [0..bandBufferSize) OF WORD ]; ColorDescriptor: TYPE = MACHINE DEPENDENT RECORD [ colorId: INT _ 0, -- bumped whenever the color changes. length: CARDINAL _ 1, command: PDFileFormat.Command.control _ [control[setColorInk]], setColorTile: PDFileFormat.SetColorTile ]; PDState: PUBLIC TYPE = REF PDStateRec; PDStateRec: PUBLIC TYPE = RECORD [ fileName: ROPE, herald: PDFileFormat.Herald, colorDescriptor: ARRAY Toner OF ColorDescriptor, stream: IO.STREAM, firstToner: Toner, lastToner: Toner, bands: ARRAY Toner OF Bands, selectedBands: Bands _ NIL, selectedBandNum: NAT _ 0, sMinPage: CARDINAL, sMaxPage: CARDINAL, fMinPage: CARDINAL, fMaxPage: CARDINAL, currentLoadLocation: LONG CARDINAL _ 0, loadWrittenLength: LONG CARDINAL _ 0, load: REF LoadRec _ NIL, leftOverMode: BOOLEAN, priorityImportant: BOOLEAN ]; Create: PUBLIC PROC [fileName: ROPE, deviceCode: PDFileFormat.DeviceCode, sResolution, fResolution, imageSSize, imageFSize: CARDINAL, nColors: NAT _ 1, bandSSize: CARDINAL _ 16, copies: CARDINAL _ 1, leftOverMode: BOOLEAN _ TRUE, priorityImportant: BOOLEAN _ TRUE] RETURNS [pdState: PDState] = { nBands: NAT; pdState _ NEW [PDStateRec]; pdState.fileName _ fileName; pdState.herald.deviceCode _ deviceCode; pdState.herald.sResolution _ sResolution; pdState.herald.fResolution _ fResolution; pdState.herald.imageSSize _ pdState.sMinPage _ imageSSize; pdState.herald.imageFSize _ pdState.fMinPage _ imageFSize; pdState.herald.bandSSize _ bandSSize; pdState.herald.maxLoadWord _ 0; pdState.herald.copies _ copies; pdState.leftOverMode _ leftOverMode; pdState.priorityImportant _ priorityImportant; pdState.sMaxPage _ pdState.fMaxPage _ 0; pdState.firstToner _ SELECT nColors FROM 1, 4 => black, 3 => cyan, ENDCASE => ERROR; pdState.lastToner _ SELECT nColors FROM 1 => black, 3, 4 => yellow, ENDCASE => ERROR; nBands _ (pdState.herald.imageSSize+pdState.herald.bandSSize-1)/pdState.herald.bandSSize; FOR t: Toner IN [pdState.firstToner..pdState.lastToner] DO pdState.bands[t] _ NEW [BandsRec[nBands]]; ENDLOOP; pdState.stream _ FileIO.Open[fileName, overwrite]; WriteHerald[pdState]; <> }; SetColorInk: PUBLIC PROC [pdState: PDState, toner: Toner] = { pdState.colorDescriptor[toner].colorId _ pdState.colorDescriptor[toner].colorId + 1; pdState.colorDescriptor[toner].length _ SIZE[PDFileFormat.Command]; pdState.colorDescriptor[toner].command _ [control[setColorInk]]; }; SetColorClear: PUBLIC PROC [pdState: PDState, toner: Toner] = { pdState.colorDescriptor[toner].colorId _ pdState.colorDescriptor[toner].colorId + 1; pdState.colorDescriptor[toner].length _ SIZE[PDFileFormat.Command]; pdState.colorDescriptor[toner].command _ [control[setColorClear]]; }; SetColorTile: PUBLIC PROC [pdState: PDState, toner: Toner, tileRef: LoadReference, tFlag: TFlag] = TRUSTED { colorId: INT _ pdState.colorDescriptor[toner].colorId + 1; tBit: [0..1] = IF tFlag = opaque THEN PDFileFormat.opaqueFlag ELSE PDFileFormat.transparentFlag; pdState.colorDescriptor[toner] _ [ colorId: colorId, length: SIZE[PDFileFormat.Command] + SIZE[PDFileFormat.SetColorTile], command: [control[setColorTile, tBit]], setColorTile: [addr: tileRef] ]; }; DoForEachToner: PUBLIC PROC [pdState: PDState, proc: PROC[Toner]] = { FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO proc[toner]; ENDLOOP; }; GetBounds: PUBLIC PROC [pdState: PDState] RETURNS [sMax, fMax: CARDINAL] = { sMax _ pdState.herald.imageSSize; fMax _ pdState.herald.imageFSize; }; MaskRectangle: PUBLIC PROC [pdState: PDState, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL] = TRUSTED { sEnd: CARDINAL _ IF pdState.leftOverMode THEN sMin+1 ELSE sMin + sSize; bandSSize: CARDINAL _ pdState.herald.bandSSize; command: PDFileFormat.Command _ [imaging[maskRectangle, 0]]; maskArgs: PDFileFormat.MaskRectangle _ [sMin:sMin, sSize:sSize, fMin:fMin, fSize:fSize]; ExtendBB[pdState, sMin, fMin]; ExtendBB[pdState, sMin + sSize, fMin + fSize]; FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO nextBandStart: CARDINAL _ sMin + (bandSSize - (sMin MOD bandSSize)); SelectBand[pdState, sMin, toner]; EnterBandData[pdState, @command, SIZE[PDFileFormat.Command]]; EnterBandData[pdState, @maskArgs, SIZE[PDFileFormat.MaskRectangle]]; FOR s: CARDINAL _ nextBandStart, s + bandSSize WHILE s 0 THEN { IF NOT buffer.run[nRuns - 1].lastRun THEN { buffer.sSize _ buffer.sSize + 1; buffer.run[nRuns - 1].lastRun _ TRUE; }; SelectBand[pdState, buffer.sMin, currentToner]; EnterBandData[pdState, @buffer, SIZE[PDFileFormat.Command] + SIZE[CARDINAL] + SIZE[CARDINAL] + nRuns * SIZE[PDFileFormat.Run]]; nRuns _ 0; buffer.sMin _ scanLineNumber; buffer.sSize _ 0; }; }; InitBuffer: PROC [sMin: CARDINAL] = { buffer.sMin _ scanLineNumber _ sMin; buffer.sSize _ 0; bandEnd _ sMin - sMin MOD bandSSize + bandSSize; }; BufferRun: PROC [fMin, fSize: CARDINAL] = { IF nRuns = maxRuns THEN PutBuffer[]; buffer.run[nRuns] _ [fMin: fMin, fSize: fSize, lastRun: FALSE]; nRuns _ nRuns + 1; }; NextLine: PROC = { buffer.sSize _ buffer.sSize + 1; buffer.run[nRuns - 1].lastRun _ TRUE; scanLineNumber _ scanLineNumber + 1; }; CaptureRun: PROC [sMin, fMin, fSize: CARDINAL] = { IF nRuns = 0 THEN InitBuffer[sMin] ELSE IF sMin >= bandEnd OR NOT (sMin IN [scanLineNumber..scanLineNumber+1]) OR nRuns = maxRuns THEN {PutBuffer[]; InitBuffer[sMin]}; IF sMin > scanLineNumber THEN NextLine[]; IF sMin # scanLineNumber THEN ERROR; IF INT[fMin] + INT[fSize] > INT[LAST[CARDINAL]] THEN {fSize _ LAST[CARDINAL] - fMin}; ExtendBB[pdState, sMin, fMin]; IF fSize > LAST[NAT] THEN { BufferRun[fMin, LAST[NAT]]; fMin _ fMin + LAST[NAT]; fSize _ fSize - LAST[NAT]; }; BufferRun[fMin, fSize]; ExtendBB[pdState, sMin + 1, fMin + fSize]; }; FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO currentToner _ toner; deliverProc[CaptureRun]; PutBuffer[]; ENDLOOP; }; ColorSamples: PUBLIC PROC [pdState: PDState, toner: Toner, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL, deliverProc: DeliverSampleArrayProc, tFlag: TFlag] = TRUSTED { tBit: [0..1] = IF tFlag = opaque THEN PDFileFormat.opaqueFlag ELSE PDFileFormat.transparentFlag; colorCommand: PDFileFormat.Command _ [imaging[colorSamples, tBit]]; bandSSize: CARDINAL = pdState.herald.bandSSize; wordsPerLine: NAT _ (fSize+(bitsPerWord-1))/bitsPerWord; s: CARDINAL _ sMin; sEnd: CARDINAL _ sMin + sSize; residualThisBand: NAT _ 0; CaptureScanLine: PROC [scanLineDataPointer: LONG POINTER] = TRUSTED { IF residualThisBand = 0 THEN { args: PDFileFormat.MaskSamples _ [ sMin: s, fMin: fMin ]; truncatedEnd: CARDINAL _ MIN[sEnd, s + bandSSize - (s MOD bandSSize)]; sampleArray: PDFileFormat.SampleArray _ [ sSize: (residualThisBand _ truncatedEnd - s), fSize: fSize ]; SelectBand[pdState, s, toner]; EnterBandData[pdState, @colorCommand, SIZE[PDFileFormat.Command]]; EnterBandData[pdState, @args, SIZE[PDFileFormat.MaskSamples]]; EnterBandData[pdState, @sampleArray, SIZE[PDFileFormat.SampleArray]]; }; EnterBandData[pdState, scanLineDataPointer, wordsPerLine]; residualThisBand _ residualThisBand - 1; s _ s + 1; }; ExtendBB[pdState, sMin, fMin]; ExtendBB[pdState, sMin + sSize, fMin + fSize]; deliverProc[CaptureScanLine]; IF residualThisBand # 0 THEN ERROR; IF s # sEnd THEN ERROR; }; RemainingLoadSize: PUBLIC PROC [pdState: PDState] RETURNS [words: INT] = { words _ INT[maxLoadSize] - pdState.currentLoadLocation; }; SetLoadLocation: PUBLIC PROC [pdState: PDState, loadReference: LoadReference] = { WriteLoadAdditions[pdState]; pdState.currentLoadLocation _ pdState.loadWrittenLength _ loadReference; }; LoadRunGroup: PUBLIC PROC [pdState: PDState, deliverProc: DeliverRunGroupProc] RETURNS [loadReference: LoadReference] = TRUSTED { highBit: CARDINAL = CARDINAL[LAST[NAT]] + 1; scanLineNumber: CARDINAL _ 0; loc: CARDINAL _ pdState.currentLoadLocation; load: REF LoadRec _ pdState.load; fMax: CARDINAL _ 0; scanLineEmpty: BOOLEAN _ TRUE; CaptureRun: PROC [sMin, fMin, fSize: CARDINAL] = TRUSTED { IF sMin INT[LAST[CARDINAL]] THEN {fSize _ LAST[CARDINAL] - fMin}; IF fSize > LAST[NAT] THEN { load[loc] _ fMin; load[loc+1] _ LAST[NAT]; loc _ loc+2; fMin _ fMin + LAST[NAT]; fSize _ fSize - LAST[NAT]; }; load[loc] _ fMin; load[loc+1] _ fSize; loc _ loc+2; fMax _ MAX[fMax, fMin+fSize]; }; IF load = NIL THEN pdState.load _ load _ NEW[LoadRec]; loadReference _ loc+1; <> loc _ loc + 2; <> deliverProc[CaptureRun]; IF NOT scanLineEmpty THEN {load[loc-1] _ load[loc-1] + highBit; scanLineNumber _ scanLineNumber+1}; load[loadReference-1] _ fMax; load[loadReference] _ scanLineNumber; pdState.currentLoadLocation _ loc; pdState.herald.maxLoadWord _ MAX[pdState.herald.maxLoadWord, loc]; }; LoadSampleArray: PUBLIC PROC [pdState: PDState, sSize, fSize: CARDINAL, deliverProc: DeliverSampleArrayProc] RETURNS [loadReference: LoadReference] = TRUSTED { CaptureScanLine: PROC [scanLineDataPointer: LONG POINTER] = TRUSTED { source: LONG POINTER TO WORD _ scanLineDataPointer; startLoc: CARDINAL _ loc; FOR i: NAT IN [0..wordsPerLine) DO load[startLoc+i] _ (source+i)^; ENDLOOP; loc _ loc + wordsPerLine; }; load: REF LoadRec _ pdState.load; wordsPerLine: NAT _ (fSize+(bitsPerWord-1))/bitsPerWord; loc: LONG CARDINAL _ pdState.currentLoadLocation; numberOfWordsOfData: LONG CARDINAL _ LONG[sSize]*wordsPerLine; IF load = NIL THEN pdState.load _ load _ NEW[LoadRec]; loadReference _ loc; load[loc] _ sSize; loc _ loc+1; load[loc] _ fSize; loc _ loc+1; deliverProc[CaptureScanLine]; IF loc # loadReference + SIZE[PDFileFormat.SampleArray] + numberOfWordsOfData THEN ERROR; pdState.currentLoadLocation _ loc; pdState.herald.maxLoadWord _ MAX[pdState.herald.maxLoadWord, loc]; }; LoadContiguousSampleArray: PUBLIC PROC [pdState: PDState, sSize, fSize: CARDINAL, bitsPtr: LONG POINTER] RETURNS [loadReference: LoadReference] = TRUSTED { source: LONG POINTER TO WORD _ bitsPtr; load: REF LoadRec _ pdState.load; wordsPerLine: INT _ (fSize+(bitsPerWord-1))/bitsPerWord; loc: LONG CARDINAL _ pdState.currentLoadLocation; IF load = NIL THEN pdState.load _ load _ NEW[LoadRec]; loadReference _ loc; load[loc] _ sSize; loc _ loc+1; load[loc] _ fSize; loc _ loc+1; FOR i: INT IN [0..sSize*wordsPerLine) DO load[loc] _ source^; loc _ loc+1; source _ source+1; ENDLOOP; pdState.currentLoadLocation _ loc; pdState.herald.maxLoadWord _ MAX[pdState.herald.maxLoadWord, loc]; }; LoadColorTile: PUBLIC PROC [pdState: PDState, phase: CARDINAL, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL, deliverProc: DeliverSampleArrayProc] RETURNS [loadReference: LoadReference] = TRUSTED { CaptureScanLine: PROC [scanLineDataPointer: LONG POINTER] = TRUSTED { source: LONG POINTER TO WORD _ scanLineDataPointer; startLoc: CARDINAL _ loc; FOR i: NAT IN [0..wordsPerLine) DO load[startLoc+i] _ (source+i)^; ENDLOOP; loc _ loc + wordsPerLine; }; load: REF LoadRec _ pdState.load; wordsPerLine: NAT _ (fSize+(bitsPerWord-1))/bitsPerWord; loc: LONG CARDINAL _ pdState.currentLoadLocation; numberOfWordsOfData: LONG CARDINAL _ LONG[sSize]*wordsPerLine; IF load = NIL THEN pdState.load _ load _ NEW[LoadRec]; loadReference _ loc; load[loc] _ phase; loc _ loc+1; load[loc] _ sMin; loc _ loc+1; load[loc] _ fMin; loc _ loc+1; load[loc] _ sSize; loc _ loc+1; load[loc] _ fSize; loc _ loc+1; deliverProc[CaptureScanLine]; IF loc # loadReference + SIZE[PDFileFormat.Tile] + numberOfWordsOfData THEN ERROR; pdState.currentLoadLocation _ loc; pdState.herald.maxLoadWord _ MAX[pdState.herald.maxLoadWord, loc]; }; LoadContiguousColorTile: PUBLIC PROC [pdState: PDState, phase: CARDINAL, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL, bitsPtr: LONG POINTER] RETURNS [loadReference: LoadReference] = TRUSTED { source: LONG POINTER TO WORD _ bitsPtr; load: REF LoadRec _ pdState.load; wordsPerLine: INT _ (fSize+(bitsPerWord-1))/bitsPerWord; loc: LONG CARDINAL _ pdState.currentLoadLocation; IF load = NIL THEN pdState.load _ load _ NEW[LoadRec]; loadReference _ loc; load[loc] _ phase; loc _ loc+1; load[loc] _ sMin; loc _ loc+1; load[loc] _ fMin; loc _ loc+1; load[loc] _ sSize; loc _ loc+1; load[loc] _ fSize; loc _ loc+1; FOR i: INT IN [0..sSize*wordsPerLine) DO load[loc] _ source^; loc _ loc+1; source _ source+1; ENDLOOP; pdState.currentLoadLocation _ loc; pdState.herald.maxLoadWord _ MAX[pdState.herald.maxLoadWord, loc]; }; EndPage: PUBLIC PROC [pdState: PDState] = { startBand: NAT _ pdState.sMinPage/pdState.herald.bandSSize; endBand: NAT _ (pdState.sMaxPage+pdState.herald.bandSSize-1)/pdState.herald.bandSSize; nBands: NAT _ MAX[0, INTEGER[endBand]-startBand]; fSizePage: CARDINAL _ MAX[INT[pdState.fMaxPage]-pdState.fMinPage, 0]; IF nBands = 0 THEN startBand _ 0; IF fSizePage = 0 THEN pdState.fMinPage _ 0; WriteLoadAdditions[pdState]; FOR t: Toner IN [pdState.firstToner..pdState.lastToner] DO bands: Bands _ pdState.bands[t]; WriteStartImage[ pdState: pdState, feed: t = pdState.firstToner, strip: t = pdState.lastToner, toner: t, passBands: startBand, nBands: nBands, fMinPage: pdState.fMinPage, fSizePage: fSizePage ]; WriteBands[pdState, bands, startBand, nBands]; ENDLOOP; pdState.sMinPage _ pdState.herald.imageSSize; pdState.fMinPage _ pdState.herald.imageFSize; pdState.sMaxPage _ pdState.fMaxPage _ 0; }; FlushPage: PUBLIC PROC [pdState: PDState] = { <> startBand: NAT _ pdState.sMinPage/pdState.herald.bandSSize; endBand: NAT _ (pdState.sMaxPage+pdState.herald.bandSSize-1)/pdState.herald.bandSSize; nBands: NAT _ MAX[0, INTEGER[endBand]-startBand]; fSizePage: CARDINAL _ MAX[INT[pdState.fMaxPage]-pdState.fMinPage, 0]; FOR t: Toner IN [pdState.firstToner..pdState.lastToner] DO bands: Bands _ pdState.bands[t]; FOR i: NAT IN [startBand..startBand+nBands) DO bands[i] _ [colorId: 0, bandBuffers: NIL]; ENDLOOP ENDLOOP; pdState.sMinPage _ pdState.herald.imageSSize; pdState.fMinPage _ pdState.herald.imageFSize; pdState.sMaxPage _ pdState.fMaxPage _ 0; }; Close: PUBLIC PROC [pdState: PDState] = { WriteControlCommand[pdState, endDocument]; pdState.stream.SetIndex[0]; WriteHerald[pdState]; pdState.stream.Close[]; }; ExtendBB: PROC [pdState: PDState, s: CARDINAL, f: CARDINAL] = { pdState.sMinPage _ MIN[s, pdState.sMinPage]; pdState.sMaxPage _ MAX[s, pdState.sMaxPage]; pdState.fMinPage _ MIN[f, pdState.fMinPage]; pdState.fMaxPage _ MAX[f, pdState.fMaxPage]; }; SelectBandNoColor: PROC [pdState: PDState, sMin: CARDINAL, toner: Toner] = TRUSTED { bandNum: NAT _ sMin/pdState.herald.bandSSize; bands: Bands _ pdState.bands[toner]; IF bands[bandNum].bandBuffers = NIL THEN bands[bandNum].bandBuffers _ NEW[BandBufferRec]; pdState.selectedBands _ bands; pdState.selectedBandNum _ bandNum; }; SelectBand: PROC [pdState: PDState, sMin: CARDINAL, toner: Toner] = TRUSTED { colorId: INT _ pdState.colorDescriptor[toner].colorId; longPriority: Environment.LongNumber _ [lc[colorId]]; priorityHighbits: [0..256) _ longPriority.highbits; priorityLowbits: CARDINAL _ longPriority.lowbits; priorityCommand: PDFileFormat.Command _ [control[setPriority, priorityHighbits]]; bandNum: NAT _ sMin/pdState.herald.bandSSize; bands: Bands _ pdState.bands[toner]; IF bands[bandNum].bandBuffers = NIL THEN bands[bandNum].bandBuffers _ NEW[BandBufferRec]; pdState.selectedBands _ bands; pdState.selectedBandNum _ bandNum; IF colorId # bands[bandNum].colorId THEN { bands[bandNum].colorId _ colorId; IF pdState.priorityImportant THEN { EnterBandData[pdState, @priorityCommand, SIZE[PDFileFormat.Command]]; EnterBandData[pdState, @priorityLowbits, SIZE[CARDINAL]]; }; EnterBandData[pdState, @(pdState.colorDescriptor[toner].command), pdState.colorDescriptor[toner].length]; }; }; EnterBandData: PROC [pdState: PDState, startPtr: LONG POINTER, wordCount: NAT] = TRUSTED { source: LONG POINTER TO WORD _ startPtr; bandBuffers: BandBuffer _ pdState.selectedBands[pdState.selectedBandNum].bandBuffers; length: NAT _ bandBuffers.length; WHILE wordCount > 0 DO IF length = bandBufferSize THEN { new: BandBuffer _ NEW[BandBufferRec]; bandBuffers.length _ length; new.link _ bandBuffers; bandBuffers _ new; length _ 0; }; bandBuffers.word[length] _ source^; length _ length + 1; wordCount _ wordCount - 1; source _ source + 1; ENDLOOP; bandBuffers.length _ length; pdState.selectedBands[pdState.selectedBandNum].bandBuffers _ bandBuffers; }; WriteLoadAdditions: PROC [pdState: PDState] = TRUSTED { <> WHILE pdState.loadWrittenLength < pdState.currentLoadLocation DO lengthOfAdditions: INT _ pdState.currentLoadLocation-pdState.loadWrittenLength; lengthOfChunk: INT _ MIN[lengthOfAdditions, LAST[NAT]]; unsafeBlock: IO.UnsafeBlock = [base: @(pdState.load[pdState.loadWrittenLength]), startIndex: 0, stopIndexPlusOne: lengthOfChunk*bytesPerWord]; WriteControlCommand[pdState, storeLoad]; WriteLongCardinal[pdState, pdState.loadWrittenLength]; WriteCardinal[pdState, lengthOfChunk]; pdState.stream.UnsafePutBlock[unsafeBlock]; pdState.loadWrittenLength _ pdState.loadWrittenLength + lengthOfChunk; ENDLOOP; }; WriteLongCardinal: PROC [pdState: PDState, lc: LONG CARDINAL] = TRUSTED { unsafeBlock: IO.UnsafeBlock = [base: @lc, startIndex: 0, stopIndexPlusOne: SIZE[LONG CARDINAL]*bytesPerWord]; pdState.stream.UnsafePutBlock[unsafeBlock]; }; WriteCardinal: PROC [pdState: PDState, c: CARDINAL] = TRUSTED { unsafeBlock: IO.UnsafeBlock = [base: @c, startIndex: 0, stopIndexPlusOne: SIZE[CARDINAL]*bytesPerWord]; pdState.stream.UnsafePutBlock[unsafeBlock]; }; WriteHerald: PROC [pdState: PDState] = TRUSTED { unsafeBlock: IO.UnsafeBlock = [base: @pdState.herald, startIndex: 0, stopIndexPlusOne: SIZE[PDFileFormat.Herald]*bytesPerWord]; pdState.stream.UnsafePutBlock[unsafeBlock]; }; WriteControlCommand: PROC [pdState: PDState, controlCom: PDFileFormat.ControlCom] = TRUSTED { command: PDFileFormat.Command _ [control[controlCom]]; unsafeBlock: IO.UnsafeBlock = [base: @command, startIndex: 0, stopIndexPlusOne: SIZE[PDFileFormat.Command]*bytesPerWord]; pdState.stream.UnsafePutBlock[unsafeBlock]; }; WriteStartImage: PROC [ pdState: PDState, feed: BOOLEAN, strip: BOOLEAN, toner: Toner, passBands: NAT, nBands: NAT, fMinPage: CARDINAL, fSizePage: CARDINAL ] = TRUSTED { StartImageBuf: TYPE = MACHINE DEPENDENT RECORD [ command: PDFileFormat.Command, args: PDFileFormat.StartImage ]; startImageBuf: StartImageBuf _ [ command: [control[com: startImage]], args: [leftOverMode: pdState.leftOverMode, feed: feed, strip: strip, toner: toner, passBands: passBands, nBands: nBands, fMinPage: fMinPage, fSizePage: fSizePage] ]; unsafeBlock: IO.UnsafeBlock = [base: @startImageBuf, startIndex: 0, stopIndexPlusOne: SIZE[StartImageBuf]*bytesPerWord]; pdState.stream.UnsafePutBlock[unsafeBlock]; }; WriteBands: PROC [pdState: PDState, bands: Bands, startBand, nBands: NAT] = TRUSTED { <> FOR bandNum: NAT IN [startBand..startBand+nBands) DO bandBuffers: BandBuffer _ bands[bandNum].bandBuffers; bufList: BandBuffer _ NIL; bands[bandNum] _ [0, NIL]; <> WHILE bandBuffers # NIL DO t: BandBuffer _ bandBuffers; bandBuffers _ bandBuffers.link; t.link _ bufList; bufList _ t; ENDLOOP; WHILE bufList # NIL DO unsafeBlock: IO.UnsafeBlock = [base: @(bufList.word[0]), startIndex: 0, stopIndexPlusOne: INT[bufList.length]*bytesPerWord]; t: BandBuffer _ bufList; pdState.stream.UnsafePutBlock[unsafeBlock]; bufList _ bufList.link; t _ NIL; -- Free goes here ENDLOOP; WriteControlCommand[pdState, endBand]; ENDLOOP; }; END.