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. †PDFileWriterImpl.mesa Michael Plass, May 3, 1983 10:08 am We will come back and overwrite this when the file is closed. Reserve a word in the load for fMax. Will come back to fill in sSize. In case the client decides it didn't really want this page after all. Writes out any additions to the font load Writes out the bands, resetting them along the way. Reverse the list of buffers. ÊݘJšœ™J™#šÏk ˜ J˜ J˜J˜Jšœ ˜ Jšœ ˜ J˜J˜—šœœ˜Jšœ ˜Jšœ ˜Jšœ˜Jšœœ˜2Jšœ œ˜0Jšœœœ˜Jšœœœœ˜$JšÏnœœ$˜=Jšžœœ˜3Jšžœœ'˜CJšžœœ$˜=Jšœœ˜!Jšœœ˜!Jšœ œ ˜Jš œ œœœœ˜/Jšœœœ ˜šœ œœ˜Jšœœ œœ˜%Jšœ˜—šœœœ˜Jšœ œ˜ Jšœ˜Jšœ˜—Jšœœ˜Jšœ œœ˜%šœœœ˜Jšœ˜Jšœœ˜Jšœœœ˜'Jšœ˜—š œœœ œœ˜2Jšœ œÏc%˜7Jšœœ˜Jšœ?˜?Jšœ'˜'Jšœ˜—Jšœ œœœ ˜&šœ œœœ˜"Jšœ œ˜Jšœ˜Jšœœœ˜0Jšœœœ˜Jšœ˜Jšœ˜Jšœœœ˜Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœœœ˜'Jšœœœ˜%Jšœœ œ˜Jšœœ˜Jšœ˜Jšœ˜—šžœœœ œYœ œœœœœœœœ˜§Jšœœ˜ Jšœ œ˜Jšœ˜Jšœ'˜'Jšœ)˜)Jšœ)˜)Jšœ:˜:Jšœ:˜:Jšœ%˜%Jšœ˜Jšœ˜Jšœ$˜$Jšœ.˜.Jšœ(˜(šœœ ˜(J˜Jšœ ˜ Jšœœ˜—šœœ ˜'J˜ Jšœ˜Jšœœ˜—JšœY˜Yšœ œ)˜:Jšœœ˜*Jšœ˜—Jšœ2˜2šœ˜J™=—Jšœ˜—šž œœœ%˜=JšœT˜TJšœ(œ˜CJšœ@˜@Jšœ˜—šž œœœ%˜?JšœT˜TJšœ(œ˜CJšœB˜BJšœ˜—šž œœœJœ˜lJšœ œ.˜:Jšœœœœ˜`šœ"˜"Jšœ˜Jšœœœ˜EJšœ'˜'Jšœ˜Jšœ˜—Jšœ˜—šžœœœœ ˜Ešœœ)˜>Jšœ ˜ Jšœ˜—Jšœ˜—š ž œœœœœ˜LJšœ!˜!Jšœ!˜!Jšœ˜—š ž œœœ œœœ˜gJš œœœœœ˜GJšœ œ˜/Jšœ<˜Jšœœœ ˜DJšœ!˜!Jšœ!œ˜=Jšœ"œ˜Dšœœ œ˜>Jšœ˜Jšœ!œ˜=Jšœ"œ˜DJšœ˜—Jšœ˜—Jšœ˜—šž œœœ!œœœœ˜†Jš œœœœœ˜GJšœ œ˜/Jšœ<˜Jšœœœ ˜DJšœ!˜!Jšœ!œ˜=Jšœ"œ˜Dšœœ œ˜>Jšœ˜Jšœ!œ˜=Jšœ"œ˜DJšœ˜—Jšœ˜—Jšœ˜—š žœœœ5œœœ˜uJšœ6˜6JšœCœ ˜Ošœ%˜%Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜—Jšœœœ˜0Jšœœœœ ˜?Jš œœœœœ˜WJšœ œ˜/Jšœ˜JšœN˜Nšœœ)˜>Jšœœœ ˜DJšœ!˜!Jšœ!œ˜=Jšœœ˜Ašœœ œ˜>Jšœ˜Jšœ!œ˜=Jšœœ˜AJšœ˜—Jšœ˜—Jšœ˜—šž œœœœœ œ œ)œ˜žJšœ:˜:Jšœ œ˜/Jšœœ'˜8Jšœ˜Jšœ.˜.šœœ)˜>Jšœœ˜Jšœœ˜Jšœœ˜š œœœœœ˜Bšœœ˜šœ"˜"Jšœ˜Jšœ ˜ Jšœ˜—Jšœœœœ˜Hšœ)˜)Jšœ-˜-Jšœ ˜ Jšœ˜—Jšœ˜Jšœ!œ˜=Jšœœ˜>Jšœ%œ˜EJšœ˜—Jšœ:˜:Jšœ(˜(J˜ Jšœ˜—Jšœ˜Jšœœœ˜#Jšœ œœ˜Jšœ˜—Jšœ˜—š žœœœ6œœœ˜wJšœ7˜7JšœDœ ˜Pšœ&˜&Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜—Jšœœ˜,Jšœœ˜.Jš œœœœœ˜GJšœ œ˜/Jšœ˜Jšœ.˜.šœœ)˜>Jšœœœ ˜DJšœ!˜!Jšœ!œ˜=Jšœœ ˜Bšœœ œ˜>Jšœ˜Jšœ!œ˜=Jšœœ ˜BJšœ˜—Jšœ˜—Jšœ˜—šž œœœ9˜RJšœ œ˜$Jšœ œ˜/šœœ œœ˜"Jšœ8˜8Jšœœ˜Jšœœ˜Jšœœœ œ˜+J˜—Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ˜šž œœœ˜šœ œ˜šœœœ˜+Jšœ ˜ Jšœ œ˜%Jšœ˜—Jšœ/˜/Jš œ œœœœœ œ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜—Jšœ˜—šž œœœ˜%Jšœ$˜$Jšœ˜Jšœœ˜0Jšœ˜—šž œœœ˜+Jšœœ ˜$Jšœ8œ˜?Jšœ˜Jšœ˜—šžœœ˜Jšœ ˜ Jšœ œ˜%Jšœ$˜$Jšœ˜—šž œœœ˜2Jšœ œ˜"Jšœœœœœ%œœ!˜„Jšœœ ˜)Jšœœœ˜$Jšœœ œ œœœœ œœ ˜UJšœ˜šœ œœœ˜Jšœœœ˜Jš œœœœœ˜3Jšœ˜—Jšœ˜Jšœ*˜*Jšœ˜—šœœ)˜>Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜—Jšœ˜—šž œœœ&œœœ7œ˜§Jšœœœœ˜`JšœC˜CJšœ œ˜/Jšœœ'˜8Jšœœ˜Jšœœ˜Jšœœ˜š žœœœœœ˜Ešœœ˜šœ"˜"Jšœ˜Jšœ ˜ Jšœ˜—Jšœœœœ ˜Fšœ)˜)Jšœ-˜-Jšœ ˜ Jšœ˜—Jšœ˜Jšœ&œ˜BJšœœ˜>Jšœ%œ˜EJšœ˜—Jšœ:˜:Jšœ(˜(J˜ Jšœ˜—Jšœ˜Jšœ.˜.Jšœ˜Jšœœœ˜#Jšœ œœ˜Jšœ˜—š žœœœœ œ˜JJšœœ,˜7Jšœ˜—šžœœœ5˜QJšœ˜JšœH˜HJšœ˜—š ž œœœ6œ"œ˜Jš œ œœœœ˜,Jšœœ˜Jšœœ˜,Jšœœ˜!Jšœœ˜Jšœœœ˜šž œœœœ˜:JšœœœŸ.˜Qšœ˜Jšœœ4˜IJšœ'˜+Jšœ"˜"Jšœœ˜Jšœ˜—Jšœœ˜Jšœœ œ œœœœ œœ ˜Ušœ œœœ˜Jšœ œœ˜7Jš œœœœœ˜3Jšœ˜—Jšœ3˜3Jšœœ˜Jšœ˜—Jšœœœœ ˜6šœ˜Jšœ$™$—˜J™ —Jšœ˜JšœœœJ˜cJšœ˜Jšœ%˜%Jšœ"˜"Jšœœ"˜BJšœ˜—š žœœœ"œ'œ"œ˜Ÿš žœœœœœ˜EJš œœœœœ˜3Jšœ œ˜šœœœ˜"Jšœ˜Jšœ˜—Jšœ˜Jšœ˜—Jšœœ˜!Jšœœ'˜8Jšœœœ˜1Jšœœœœ˜>Jšœœœœ ˜6Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ1œœ˜YJšœ"˜"Jšœœ"˜BJšœ˜—šžœœœ"œ œœœ"œ˜›Jš œœœœœ ˜'Jšœœ˜!Jšœœ'˜8Jšœœœ˜1Jšœœœœ ˜6Jšœ˜Jšœ˜Jšœ˜šœœœ˜(Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜—Jšœ"˜"Jšœœ"˜BJšœ˜—šž œœœœœœ'œ"œ˜Äš žœœœœœ˜EJš œœœœœ˜3Jšœ œ˜šœœœ˜"Jšœ˜Jšœ˜—Jšœ˜Jšœ˜—Jšœœ˜!Jšœœ'˜8Jšœœœ˜1Jšœœœœ˜>Jšœœœœ ˜6Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ*œœ˜RJšœ"˜"Jšœœ"˜BJšœ˜—šžœœœœœœ œœœ"œ˜ÀJš œœœœœ ˜'Jšœœ˜!Jšœœ'˜8Jšœœœ˜1Jšœœœœ ˜6Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜šœœœ˜(Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜—Jšœ"˜"Jšœœ"˜BJšœ˜—šžœœœ˜+Jšœ œ-˜;Jšœ œJ˜VJšœœœœ˜1Jšœ œœœ(˜EJšœ œ˜!Jšœœ˜+Jšœ˜šœ œ)˜:Jšœ ˜ šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ.˜.Jšœ˜—Jšœ-˜-Jšœ-˜-Jšœ(˜(Jšœ˜—šž œœœ˜-J™EJšœ œ-˜;Jšœ œJ˜VJšœœœœ˜1Jšœ œœœ(˜Ešœ œ)˜:Jšœ ˜ šœœœ˜.Jšœ%œ˜*Jš˜—Jšœ˜—Jšœ-˜-Jšœ-˜-Jšœ(˜(Jšœ˜—šžœœœ˜)Jšœ*˜*Jšœ˜Jšœ˜Jšœ˜Jšœ˜—šžœœœœ˜?Jšœœ˜,Jšœœ˜,Jšœœ˜,Jšœœ˜,Jšœ˜—šžœœœœ˜TJšœ œ!˜-Jšœ$˜$Jšœœœœ˜YJšœ˜Jšœ"˜"Jšœ˜—šž œœœœ˜MJšœ œ*˜6Jšœ5˜5Jšœ3˜3Jšœœ˜1JšœQ˜QJšœ œ!˜-Jšœ$˜$Jšœœœœ˜YJšœ˜Jšœ"˜"šœ!œ˜*Jšœ!˜!šœœ˜#Jšœ)œ˜EJšœ)œœ˜9J˜—Jšœi˜iJšœ˜—Jšœ˜—š ž œœœœ œœ˜ZJš œœœœœ ˜(JšœU˜UJšœœ˜!šœ˜šœœ˜!Jšœœ˜%Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ J˜—Jšœ#˜#Jšœ˜Jšœ˜Jšœ˜Jš˜—Jšœ˜JšœI˜IJšœ˜—šžœœœ˜7J™)šœ9˜@Jšœœ9˜OJš œœœœœ˜7Jšœ œ˜ŽJšœ(˜(Jšœ6˜6Jšœ&˜&Jšœ+˜+JšœF˜FJšœ˜—Jšœ˜—š žœœœœœ˜IJš œ œ<œœœ˜mJšœ+˜+Jšœ˜—šž œœœœ˜?Jšœ œ;œœ˜gJšœ+˜+Jšœ˜—šž œœœ˜0Jšœ œHœ$˜Jšœ+˜+Jšœ˜—šžœœ;œ˜]Jšœ6˜6Jšœ œAœ%˜yJšœ+˜+Jšœ˜—šžœœ˜Jšœ˜Jšœœ˜Jšœœ˜Jšœ ˜ Jšœ œ˜Jšœœ˜ Jšœ œ˜Jšœ ˜Jšœœ˜ š œœœ œœ˜0Jšœ˜Jšœ˜Jšœ˜—šœ ˜ Jšœ$˜$Jšœ¢˜¢Jšœ˜—Jšœ œGœ˜xJšœ+˜+Jšœ˜—šž œœ5œœ˜UJ™3šœ œœ˜4Jšœ5˜5Jšœœ˜Jšœœ˜J™šœœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜—šœ œ˜Jšœ œKœ˜|Jšœ˜Jšœ+˜+Jšœ˜JšœœŸ˜Jšœ˜—Jšœ&˜&Jšœ˜—Jšœ˜—Jšœ˜——…—eHƒ«