DIRECTORY Atom, Environment, FileIO, Inline, IO, PDFileFormat, PDFileWriter, Rope, ImagerPixelMaps, Mopcodes ; PDFileWriterImpl: CEDAR PROGRAM IMPORTS Atom, FileIO, Inline, ImagerPixelMaps, IO, Rope EXPORTS PDFileWriter = BEGIN BlockTransfer: UNSAFE PROC [source: LONG POINTER, count: CARDINAL, dest: LONG POINTER] ~ UNCHECKED MACHINE CODE {Mopcodes.zBLTL}; LongBlockTransfer: UNSAFE PROC [source: LONG POINTER, count: INT, dest: LONG POINTER] ~ UNCHECKED { WHILE count > LAST[CARDINAL] DO BlockTransfer[source: source, count: LAST[CARDINAL], dest: dest]; source _ source + LAST[CARDINAL]; dest _ dest + LAST[CARDINAL]; count _ count - LAST[CARDINAL]; ENDLOOP; BlockTransfer[source: source, count: count, dest: dest]; }; bytesPerWord: CARDINAL = Environment.bytesPerWord; bitsPerWord: CARDINAL = Environment.bitsPerWord; ROPE: TYPE = Rope.ROPE; LoadReference: TYPE = NAT; DeliverRunGroupProc: TYPE = PDFileWriter.DeliverRunGroupProc; CaptureRunProc: TYPE = PDFileWriter.CaptureRunProc; DeliverSampleArrayProc: TYPE = PDFileWriter.DeliverSampleArrayProc; CaptureScanLineProc: TYPE = PDFileWriter.CaptureScanLineProc; TFlag: TYPE = PDFileWriter.TFlag; Toner: TYPE = PDFileFormat.Toner; Bands: TYPE = REF BandsRec; BandsRec: TYPE = RECORD [ bands: SEQUENCE maxBands: NAT OF Band ]; Band: TYPE = RECORD [ colorId: INT, bandBuffer: BandBuffer ]; bandBufferSize: NAT = 200; BandBuffer: TYPE = REF BandBufferRec; BandBufferRec: TYPE = RECORD [ length: NAT _ 0, overflowIndices: LIST OF INT _ NIL, 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 ]; maxLoadItems: CARDINAL _ 2000; LoadDescription: TYPE = REF LoadDescriptionRep; LoadDescriptionRep: TYPE = RECORD [ storageRef: REF, -- to protect against garbage collection pointer: LONG POINTER, words: INT, -- at least as big as loadSizeInWords count: NAT _ 0, entries: SEQUENCE maxCount: NAT OF LoadEntryDescription ]; LoadEntryType: TYPE = {none, samples, runGroup, tile}; LoadEntryDescription: TYPE = RECORD [ loadEntryType: LoadEntryType, offsetHighBits: [0..256), offsetLowBits: CARDINAL, pageOfMostRecentUse: CARDINAL, numberOfPagesUsedIn: CARDINAL ]; 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, currentPage: CARDINAL _ 1, currentLoadLocation: INT _ 0, loadWrittenLength: INT _ 0, loadSizeInWords: INT, leftOverMode: BOOLEAN, priorityImportant: BOOLEAN, loadDescription: LoadDescription, overflowStream: IO.STREAM _ NIL, overflowFileName: ROPE _ NIL ]; Create: PUBLIC PROC [fileName: ROPE, deviceCode: PDFileFormat.DeviceCode, sResolution, fResolution, imageSSize, imageFSize: CARDINAL, nColors: NAT, bandSSize: CARDINAL, copies: CARDINAL, leftOverMode: BOOLEAN, maxLoadWords: INT] 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.loadSizeInWords _ maxLoadWords; pdState.leftOverMode _ leftOverMode; pdState.priorityImportant _ FALSE; 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]; }; SetPriorityImportant: PUBLIC PROC [pdState: PDState, priorityImportant: BOOLEAN] RETURNS [previousValue: BOOLEAN] = { previousValue _ pdState.priorityImportant; pdState.priorityImportant _ priorityImportant; }; 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 { loadEntry: LoadEntryDescription _ pdState.loadDescription[tileRef]; reference: Environment.LongNumber _ [num[lowbits: loadEntry.offsetLowBits, highbits: loadEntry.offsetHighBits]]; colorId: INT _ pdState.colorDescriptor[toner].colorId + 1; tBit: [0..1] = IF tFlag = opaque THEN PDFileFormat.opaqueFlag ELSE PDFileFormat.transparentFlag; IF loadEntry.loadEntryType # tile THEN ERROR; pdState.colorDescriptor[toner] _ [ colorId: colorId, length: SIZE[PDFileFormat.Command] + SIZE[PDFileFormat.SetColorTile], command: [control[setColorTile, tBit]], setColorTile: [addr: reference.lc] ]; }; 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] = INLINE { IF nRuns = maxRuns THEN PutBuffer[]; buffer.run[nRuns] _ [fMin: fMin, fSize: fSize, lastRun: FALSE]; nRuns _ nRuns + 1; }; NextLine: PROC = INLINE { 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 _ pdState.loadSizeInWords - pdState.currentLoadLocation; IF pdState.loadDescription # NIL AND pdState.loadDescription.count = pdState.loadDescription.maxCount THEN words _ 0; }; GetLoadDescription: PROC [pdState: PDState] RETURNS [LoadDescription] = { IF pdState.loadDescription = NIL THEN { loadDescription: LoadDescription _ NEW[LoadDescriptionRep[maxLoadItems]]; rows: NAT _ pdState.loadSizeInWords/200; columns: NAT _ (pdState.loadSizeInWords+rows-1)/rows; temp: ImagerPixelMaps.PixelMap _ ImagerPixelMaps.Create[4, [0,0,rows,columns]]; loadDescription.storageRef _ temp.refRep.ref; loadDescription.pointer _ temp.refRep.pointer; loadDescription.words _ temp.refRep.words; loadDescription.count _ 0; pdState.loadDescription _ loadDescription; }; RETURN [pdState.loadDescription] }; loadBreakOffset: INT _ LAST[INT]; loadBreakCount: INT _ 0; DebugLoad: PROC [loadOffset: INT] ~ { IF loadOffset = loadBreakOffset THEN loadBreakCount _ loadBreakCount + 1; }; LoadRunGroup: PUBLIC PROC [pdState: PDState, deliverProc: DeliverRunGroupProc] RETURNS [loadReference: LoadReference] = TRUSTED { highBit: CARDINAL = CARDINAL[LAST[NAT]] + 1; loadDescription: LoadDescription _ GetLoadDescription[pdState]; scanLineNumber: CARDINAL _ 0; maxLoc: INT _ pdState.loadSizeInWords; loc: INT _ pdState.currentLoadLocation; base: LONG POINTER TO CARDINAL _ loadDescription.pointer; fMax: CARDINAL _ 0; scanLineEmpty: BOOLEAN _ TRUE; CaptureRun: PROC [sMin, fMin, fSize: CARDINAL] = TRUSTED { IF sMin maxLoc THEN ERROR; IF scanLineEmpty THEN {(base+loc)^ _ 0; (base+loc+1)^ _ highBit; loc _ loc+2} ELSE {(base+loc-1)^ _ (base+loc-1)^ + highBit}; scanLineNumber _ scanLineNumber+1; scanLineEmpty _ TRUE; ENDLOOP; scanLineEmpty _ FALSE; IF INT[fMin] + INT[fSize] > INT[LAST[CARDINAL]] THEN {fSize _ LAST[CARDINAL] - fMin}; IF fSize > LAST[NAT] THEN { IF loc+2 > maxLoc THEN ERROR; (base+loc)^ _ fMin; (base+loc+1)^ _ LAST[NAT]; loc _ loc+2; fMin _ fMin + LAST[NAT]; fSize _ fSize - LAST[NAT]; }; IF loc+2 > maxLoc THEN ERROR; (base+loc)^ _ fMin; (base+loc+1)^ _ fSize; loc _ loc+2; fMax _ MAX[fMax, fMin+fSize]; }; origin: INT _ loc+1; loc _ loc + 2; IF loc > maxLoc THEN ERROR; deliverProc[CaptureRun]; IF NOT scanLineEmpty THEN {(base+loc-1)^ _ (base+loc-1)^ + highBit; scanLineNumber _ scanLineNumber+1}; (base+origin-1)^ _ fMax; (base+origin)^ _ scanLineNumber; pdState.currentLoadLocation _ loc; pdState.herald.maxLoadWord _ MAX[pdState.herald.maxLoadWord, loc]; loadReference _ loadDescription.count; loadDescription.count _ loadDescription.count + 1; loadDescription[loadReference] _ [ loadEntryType: runGroup, offsetHighBits: Inline.HighHalf[origin], offsetLowBits: Inline.LowHalf[origin], pageOfMostRecentUse: 0, numberOfPagesUsedIn: 0 ]; DebugLoad[origin]; }; LoadContiguousSampleArray: PUBLIC PROC [pdState: PDState, sSize, fSize: CARDINAL, bitsPtr: LONG POINTER] RETURNS [loadReference: LoadReference] = TRUSTED { loadDescription: LoadDescription _ GetLoadDescription[pdState]; source: LONG POINTER TO WORD _ bitsPtr; wordsPerLine: NAT _ (fSize+(bitsPerWord-1))/bitsPerWord; words: INT _ Inline.LongMult[sSize, wordsPerLine]; startOffset: INT _ pdState.currentLoadLocation; destOffset: INT _ startOffset + SIZE[PDFileFormat.SampleArray]; endOffset: INT _ destOffset + words; sampleArray: LONG POINTER TO PDFileFormat.SampleArray _ loadDescription.pointer + startOffset; destBase: LONG POINTER TO WORD _ loadDescription.pointer + destOffset; IF endOffset > pdState.loadSizeInWords THEN ERROR; sampleArray.sSize _ sSize; sampleArray.fSize _ fSize; LongBlockTransfer[source: source, count: words, dest: destBase]; loadReference _ loadDescription.count; loadDescription.count _ loadDescription.count + 1; loadDescription[loadReference] _ [ loadEntryType: samples, offsetHighBits: Inline.HighHalf[startOffset], offsetLowBits: Inline.LowHalf[startOffset], pageOfMostRecentUse: 0, numberOfPagesUsedIn: 0 ]; pdState.currentLoadLocation _ endOffset; pdState.herald.maxLoadWord _ MAX[pdState.herald.maxLoadWord, endOffset]; DebugLoad[startOffset]; }; LoadContiguousColorTile: PUBLIC PROC [pdState: PDState, phase: CARDINAL, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL, bitsPtr: LONG POINTER] RETURNS [loadReference: LoadReference] = TRUSTED { loadDescription: LoadDescription _ GetLoadDescription[pdState]; source: LONG POINTER TO WORD _ bitsPtr; wordsPerLine: NAT _ (fSize+(bitsPerWord-1))/bitsPerWord; words: INT _ Inline.LongMult[sSize, wordsPerLine]; startOffset: INT _ pdState.currentLoadLocation; destOffset: INT _ startOffset + SIZE[PDFileFormat.Tile]; endOffset: INT _ destOffset + words; tile: LONG POINTER TO PDFileFormat.Tile _ loadDescription.pointer + startOffset; destBase: LONG POINTER TO WORD _ loadDescription.pointer + destOffset; IF endOffset > pdState.loadSizeInWords THEN ERROR; tile.phase _ phase; tile.sMin _ sMin; tile.fMin _ fMin; tile.sSize _ sSize; tile.fSize _ fSize; LongBlockTransfer[source: source, count: words, dest: destBase]; loadReference _ loadDescription.count; loadDescription.count _ loadDescription.count + 1; loadDescription[loadReference] _ [ loadEntryType: tile, offsetHighBits: Inline.HighHalf[startOffset], offsetLowBits: Inline.LowHalf[startOffset], pageOfMostRecentUse: 0, numberOfPagesUsedIn: 0 ]; pdState.currentLoadLocation _ endOffset; pdState.herald.maxLoadWord _ MAX[pdState.herald.maxLoadWord, endOffset]; DebugLoad[startOffset]; }; 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; pdState.currentPage _ pdState.currentPage + 1; IF pdState.overflowStream # NIL THEN pdState.overflowStream.SetIndex[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; bands[i].bandBuffer.length _ 0; bands[i].bandBuffer.overflowIndices _ NIL; ENDLOOP ENDLOOP; IF pdState.overflowStream # NIL THEN { pdState.overflowStream.SetIndex[0]; }; 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]; IO.Close[pdState.stream]; IF pdState.overflowStream # NIL THEN { pdState.overflowStream.SetIndex[0]; pdState.overflowStream.SetLength[0]; pdState.overflowStream.Close[abort: TRUE]; }; }; 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].bandBuffer = NIL THEN bands[bandNum].bandBuffer _ 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].bandBuffer = NIL THEN bands[bandNum].bandBuffer _ 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]; }; }; WriteOverflowBand: PROC [pdState: PDState, bandBuffer: BandBuffer] = TRUSTED { bandDataPtr: LONG POINTER _ @(bandBuffer.word); IF pdState.overflowStream = NIL THEN { pdState.overflowFileName _ Atom.GetPName[Atom.Gensym['A]].Concat["$"]; pdState.overflowStream _ FileIO.Open[pdState.overflowFileName, overwrite]; }; bandBuffer.overflowIndices _ CONS[ IO.GetIndex[pdState.overflowStream], bandBuffer.overflowIndices ]; pdState.overflowStream.UnsafePutBlock[[base: bandDataPtr, startIndex: 0, stopIndexPlusOne: bandBufferSize*bytesPerWord]]; bandBuffer.length _ 0; }; EnterBandData: PROC [pdState: PDState, startPtr: LONG POINTER, wordCount: NAT] = TRUSTED { source: LONG POINTER TO WORD _ startPtr; bandBuffer: BandBuffer _ pdState.selectedBands[pdState.selectedBandNum].bandBuffer; WHILE wordCount > 0 DO IF wordCount <= bandBufferSize - bandBuffer.length THEN { BlockTransfer[source: startPtr, count: wordCount, dest: @(bandBuffer.word[bandBuffer.length])]; startPtr _ startPtr + wordCount; bandBuffer.length _ bandBuffer.length + wordCount; wordCount _ 0; } ELSE { count: NAT _ bandBufferSize - bandBuffer.length; bufPtr: LONG POINTER _ @(bandBuffer.word); BlockTransfer[source: startPtr, count: count, dest: bufPtr+bandBuffer.length]; startPtr _ startPtr + count; bandBuffer.length _ bandBuffer.length + count; wordCount _ wordCount - count; WriteOverflowBand[pdState, bandBuffer]; }; ENDLOOP; }; WriteLoadAdditions: PROC [pdState: PDState] = TRUSTED { WHILE pdState.loadWrittenLength < pdState.currentLoadLocation DO loadDescription: LoadDescription _ GetLoadDescription[pdState]; lengthOfAdditions: INT _ pdState.currentLoadLocation-pdState.loadWrittenLength; lengthOfChunk: INT _ MIN[lengthOfAdditions, 8*1024]; unsafeBlock: IO.UnsafeBlock = [base: loadDescription.pointer+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 bandBuffer: BandBuffer _ bands[bandNum].bandBuffer; IF bandBuffer # NIL THEN { overflowIndices: LIST OF INT _ NIL; WHILE bandBuffer.overflowIndices # NIL DO t: LIST OF INT _ bandBuffer.overflowIndices; bandBuffer.overflowIndices _ bandBuffer.overflowIndices.rest; t.rest _ overflowIndices; overflowIndices _ t; ENDLOOP; WHILE overflowIndices # NIL DO overflowBuf: ARRAY [0..bandBufferSize) OF CARDINAL; pdState.overflowStream.SetIndex[overflowIndices.first]; IF bandBufferSize*bytesPerWord # pdState.overflowStream.UnsafeGetBlock[[ base: @overflowBuf, startIndex: 0, stopIndexPlusOne: bandBufferSize*bytesPerWord ]] THEN ERROR; pdState.stream.UnsafePutBlock[[base: @overflowBuf, startIndex: 0, stopIndexPlusOne: bandBufferSize*bytesPerWord]]; overflowIndices _ overflowIndices.rest; ENDLOOP; pdState.stream.UnsafePutBlock[[base: @(bandBuffer.word), startIndex: 0, stopIndexPlusOne: bandBuffer.length*bytesPerWord]]; bandBuffer.length _ 0; }; WriteControlCommand[pdState, endBand]; ENDLOOP; }; END. æPDFileWriterImpl.mesa Michael Plass, November 22, 1983 2:53 pm We will come back and overwrite this when the file is closed. set a breakpoint here to debug strange load contents. Reserve a word in the load for fMax. Will come back to fill in sSize. Fill in fMax. 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 overflow indices. Ê È˜Jšœ™J™(šÏk ˜ J˜J˜ J˜J˜J˜Jšœ ˜ Jšœ ˜ J˜J˜J˜J˜J˜—šœœ˜Jšœ(œ˜7Jšœ ˜šœ˜J˜—šÏn œœœ œœ œœœ˜VJšœ œœœ˜*J˜—šžœœœ œœ œœœ œ˜cšœ œœ˜Jšœ%œœ˜AJšœœœ˜!Jšœœœ˜Jšœœœ˜Jšœ˜—Jšœ8˜8Jšœ˜J˜—Jšœœ˜2Jšœ œ˜0Jšœœœ˜Jšœœœ˜Jšžœœ$˜=Jšžœœ˜3Jšžœœ'˜CJšžœœ$˜=Jšœœ˜!Jšœœ˜!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šœ œŸ(˜9Jšœ œœ˜JšœœŸ%˜2Jšœœ˜Jšœ œ œœ˜7Jšœ˜J˜—Jšœœ#˜6šœœœ˜%Jšœ˜Jšœ˜Jšœœ˜Jšœœ˜Jšœ˜Jšœ˜J˜—Jšœ œœœ ˜&šœ œœœ˜"Jšœ œ˜Jšœ˜Jšœœœ˜0Jšœœœ˜Jšœ˜Jšœ˜Jšœœœ˜Jšœœ˜Jšœœ˜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šœœ˜—JšœY˜Yšœ œ)˜:Jšœœ˜*Jšœ˜—Jšœ2˜2šœ˜J™=—Jšœ˜J˜—š žœœœ'œœœ˜uJšœ*˜*Jšœ.˜.Jšœ˜J˜—šž œœœ%˜=JšœT˜TJšœ(œ˜CJšœ@˜@Jšœ˜J˜—šž œœœ%˜?JšœT˜TJšœ(œ˜CJšœB˜BJšœ˜J˜—šž œœœJœ˜lJšœC˜CJšœp˜pJšœ œ.˜:Jšœœœœ˜`Jšœ œœ˜-šœ"˜"Jšœ˜Jšœœœ˜EJšœ'˜'Jšœ"˜"Jšœ˜—Jšœ˜J˜—šžœœœœ ˜Ešœœ)˜>Jšœ ˜ Jšœ˜—Jšœ˜J˜—š ž œœœœœ˜LJšœ!˜!Jšœ!˜!Jšœ˜J˜—š ž œœœ œœœ˜gJš œœœœœ˜GJšœ œ˜/Jšœ<˜Jšœœœ ˜DJšœ!˜!Jšœ!œ˜=Jšœ"œ˜Dšœœ œ˜>Jšœ˜Jšœ!œ˜=Jšœ"œ˜DJšœ˜—Jšœ˜—Jšœ˜J˜—šž œœœ!œœœœ˜†Jš œœœœœ˜GJšœ œ˜/Jšœ<˜Jšœœœ ˜DJšœ!˜!Jšœ!œ˜=Jšœ"œ˜Dšœœ œ˜>Jšœ˜Jšœ!œ˜=Jšœ"œ˜DJšœ˜—Jšœ˜—Jšœ˜J˜—š žœœœ5œœœ˜uJšœF˜FJšœp˜pJšœT˜Tšœ%˜%Jšœ%˜%Jšœ ˜ Jšœ ˜ Jšœ˜—JšœœœœK˜jJš œœœœœ˜WJšœ œ˜/Jšœ#œœ˜0Jšœ˜JšœN˜Nšœœ)˜>Jšœœœ ˜DJšœ!˜!Jšœ!œ˜=Jšœœ˜Ašœœ œ˜>Jšœ˜Jšœ!œ˜=Jšœœ˜AJšœ˜—Jšœ˜—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šœ˜J˜—š žœœœ6œœœ˜wJšœG˜GJšœp˜pJšœU˜Ušœ&˜&Jšœ%˜%Jšœ ˜ Jšœ ˜ Jšœ˜—Jš œ œœœœ6˜XJš œ œœœœ2˜TJš œœœœœ˜KJšœ œ˜/Jšœ$œœ˜1Jšœ˜Jšœ6˜6šœœ)˜>Jšœœœ ˜DJšœ!˜!Jšœ!œ˜=Jšœœ ˜Bšœœ œ˜>Jšœ˜Jšœ!œ˜=Jšœœ ˜BJšœ˜—Jšœ˜—Jšœ˜J˜—šž œœœ9˜RJšœ œœ˜5Jšœ œ˜/šœœ œœ˜"Jšœ8˜8Jšœœ˜Jšœœ˜Jšœœœ œ˜+J˜—Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ˜šž œœœ˜šœ œ˜šœœœ˜+Jšœ ˜ Jšœ œ˜%Jšœ˜—Jšœ/˜/Jš œ œœœœœ œ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜—Jšœ˜—šž œœœ˜%Jšœ$˜$Jšœ˜Jšœœ˜0Jšœ˜—šž œœœœ˜2Jšœœ ˜$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šœ˜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šœ˜J˜—š žœœœœ œ˜JJšœ>˜>JšœœœBœ ˜uJšœ˜J˜—šžœœœ˜Išœœœ˜'Jšœ#œ#˜IJšœœ˜(Jšœ œ)˜5JšœO˜OJšœ-˜-Jšœ.˜.Jšœ*˜*Jšœ˜Jšœ*˜*Jšœ˜—Jšœ˜ Jšœ˜J˜—Jšœœœœ˜!Jšœœ˜šž œœœ˜%šœ˜$J™5Jšœ$˜$—Jšœ˜J˜—š ž œœœ6œ"œ˜Jš œ œœœœ˜,Jšœ?˜?Jšœœ˜Jšœœ˜&Jšœœ˜'Jš œœœœœ˜9Jšœœ˜Jšœœœ˜šž œœœœ˜:JšœœœŸ.˜Qšœ˜Jšœœœ˜Jšœœ8˜MJšœ+˜/Jšœ"˜"Jšœœ˜Jšœ˜—Jšœœ˜Jšœœ œ œœœœ œœ ˜Ušœ œœœ˜Jšœœœ˜Jšœ$œœ˜;Jš œœœœœ˜3Jšœ˜—Jšœœœ˜Jšœ7˜7Jšœœ˜Jšœ˜—šœœ ˜Jšœ$™$—˜J™ —Jšœœœ˜Jšœ˜JšœœœN˜gšœ˜Jšœ ™ —šœ ˜ J™—Jšœ"˜"Jšœœ"˜BJšœ&˜&Jšœ2˜2šœ"˜"Jšœ˜Jšœ(˜(Jšœ&˜&Jšœ˜Jšœ˜Jšœ˜—Jšœ˜Jšœ˜J˜—šžœœœ"œ œœœ"œ˜›Jšœ?˜?Jš œœœœœ ˜'Jšœœ'˜8Jšœœ(˜2Jšœ œ˜/Jšœ œœ˜?Jšœ œ˜$Jšœ œœœB˜^Jš œ œœœœ(˜FJšœ%œœ˜2Jšœ˜Jšœ˜Jšœ@˜@Jšœ&˜&Jšœ2˜2šœ"˜"Jšœ˜Jšœ-˜-Jšœ+˜+Jšœ˜Jšœ˜Jšœ˜—Jšœ(˜(Jšœœ(˜HJšœ˜Jšœ˜J˜—šžœœœœœœ œœœ"œ˜ÀJšœ?˜?Jš œœœœœ ˜'Jšœœ'˜8Jšœœ(˜2Jšœ œ˜/Jšœ œœ˜8Jšœ œ˜$Jšœœœœ;˜PJš œ œœœœ(˜FJšœ%œœ˜2Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ@˜@Jšœ&˜&Jšœ2˜2šœ"˜"Jšœ˜Jšœ-˜-Jšœ+˜+Jšœ˜Jšœ˜Jšœ˜—Jšœ(˜(Jšœœ(˜HJšœ˜Jšœ˜J˜—šžœœœ˜+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šœœœ$˜HJšœ˜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˜#Jšœ$˜$Jšœ$œ˜*Jšœ˜—Jšœ˜J˜—šžœœœœ˜?Jšœœ˜,Jšœœ˜,Jšœœ˜,Jšœœ˜,Jšœ˜J˜—šžœœœœ˜TJšœ œ!˜-Jšœ$˜$Jšœœœœ˜WJšœ˜Jšœ"˜"Jšœ˜J˜—šž œœœœ˜MJšœ œ*˜6Jšœ5˜5Jšœ3˜3Jšœœ˜1JšœQ˜QJšœ œ!˜-Jšœ$˜$Jšœœœœ˜WJšœ˜Jšœ"˜"šœ!œ˜*Jšœ!˜!šœœ˜#Jšœ)œ˜EJšœ)œœ˜9J˜—Jšœi˜iJšœ˜—Jšœ˜J˜—šžœœ.œ˜NJšœ œœ˜/šœœœ˜&JšœF˜FJšœJ˜JJšœ˜—šœœ˜"Jšœ"˜$Jšœ˜Jšœ˜—Jšœy˜yJšœ˜Jšœ˜J˜—š ž œœœœ œœ˜ZJš œœœœœ ˜(JšœS˜Sšœ˜šœ1œ˜9Jšœ_˜_Jšœ ˜ Jšœ2˜2Jšœ˜Jšœ˜—šœ˜Jšœœ&˜0Jšœœœ˜*JšœN˜NJšœ˜Jšœ.˜.Jšœ˜Jšœ'˜'Jšœ˜—Jš˜—Jšœ˜J˜—šžœœœ˜7J™)šœ9˜@Jšœ?˜?Jšœœ9˜OJšœœœ˜4Jšœ œ†˜•Jšœ(˜(Jšœ6˜6Jšœ&˜&Jšœ+˜+JšœF˜FJšœ˜—Jšœ˜J˜—š žœœœœœ˜IJš œ œ<œœœ˜mJšœ+˜+Jšœ˜J˜—šž œœœœ˜?Jšœ œ;œœ˜gJšœ+˜+Jšœ˜J˜—šž œœœ˜0Jšœ œHœ$˜Jšœ+˜+Jšœ˜J˜—šžœœ;œ˜]Jšœ6˜6Jšœ œAœ%˜yJšœ+˜+Jšœ˜J˜—šžœœ˜Jšœ˜Jšœœ˜Jšœœ˜Jšœ ˜ Jšœ œ˜Jšœœ˜ Jšœ œ˜Jšœ ˜Jšœœ˜ š œœœ œœ˜0Jšœ˜Jšœ˜Jšœ˜—šœ ˜ Jšœ$˜$Jšœ¢˜¢Jšœ˜—Jšœ œGœ˜xJšœ+˜+Jšœ˜J˜—šž œœ5œœ˜UJ™3šœ œœ˜4Jšœ3˜3šœœœ˜Jš œœœœœ˜#J™%šœœ˜)Jšœœœœ˜,Jšœ=˜=Jšœ˜Jšœ˜Jšœ˜—šœœ˜Jšœ œœœ˜3Jšœ7˜7šœ˜ šœ'˜'Jšœ˜Jšœ˜Jšœ-˜-Jšœ˜——Jšœœ˜ Jšœr˜rJšœ'˜'Jšœ˜—Jšœ{˜{Jšœ˜Jšœ˜—Jšœ&˜&Jšœ˜—Jšœ˜J˜—Jšœ˜——…—u—¶