DIRECTORY Basics USING [bitsPerWord, bytesPerWord, HighHalf, LongMult, LongNumber, LowHalf, UnsafeBlock], CountedVM USING [Allocate, Handle, Pointer, Words], FS USING [StreamOpen], IO USING [Close, GetIndex, SetIndex, SetLength, STREAM, UnsafeGetBlock, UnsafePutBlock], PDFileFormat USING [Command, ControlCom, DeviceCode, Herald, MaskRectangle, MaskRunGroupRef, MaskSamples, MaskSamplesRef, MaskTrapezoid, opaqueFlag, Run, SampleArray, SetColorTile, StartImage, Tile, Toner, transparentFlag], PDFileWriter USING [CaptureRunProc, CaptureScanLineProc, DeliverRunGroupProc, DeliverSampleArrayProc, TFlag, TonerSet], PrincOpsUtils USING [LongCopy], Rope USING [ROPE]; PDFileWriterImpl: CEDAR PROGRAM IMPORTS Basics, CountedVM, FS, IO, PrincOpsUtils EXPORTS PDFileWriter = BEGIN BlockTransfer: UNSAFE PROC [source: LONG POINTER, count: CARDINAL, dest: LONG POINTER] ~ UNCHECKED INLINE {PrincOpsUtils.LongCopy[from: source, nwords: count, to: dest]}; 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; IF count > 0 THEN BlockTransfer[source: source, count: count, dest: dest]; }; bytesPerWord: CARDINAL = Basics.bytesPerWord; bitsPerWord: CARDINAL = Basics.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; TonerSet: TYPE = PDFileWriter.TonerSet; 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. enabled: BOOLEAN _ TRUE, length: NAT _ 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, toners: TonerSet _ [black: TRUE], firstToner, lastToner: Toner _ black, feed: BOOLEAN _ TRUE, strip: BOOLEAN _ TRUE, bands: ARRAY Toner OF Bands, selectedBands: Bands _ NIL, selectedBandNum: NAT _ 0, sMinPage: CARDINAL, sMaxPage: CARDINAL, fMinPage: CARDINAL, fMaxPage: CARDINAL, currentImage: CARDINAL _ 1, currentLoadLocation: INT _ 0, loadWrittenLength: INT _ 0, loadSizeInWords: INT, leftOverMode: BOOLEAN, priorityImportant: BOOLEAN, loadDescription: LoadDescription, overflowStream: IO.STREAM _ NIL ]; Create: PUBLIC PROC [fileName: ROPE, deviceCode: PDFileFormat.DeviceCode, sResolution, fResolution, imageSSize, imageFSize: CARDINAL, 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.toners _ [black: TRUE]; pdState.feed _ pdState.strip _ TRUE; nBands _ (pdState.herald.imageSSize+pdState.herald.bandSSize-1)/pdState.herald.bandSSize; pdState.bands[black] _ NEW [BandsRec[nBands]]; pdState.stream _ FS.StreamOpen[fileName, $create]; WriteHerald[pdState]; }; SetPriorityImportant: PUBLIC PROC [pdState: PDState, priorityImportant: BOOLEAN] RETURNS [previousValue: BOOLEAN] = { previousValue _ pdState.priorityImportant; pdState.priorityImportant _ priorityImportant; }; StartImage: PUBLIC PROC [pdState: PDState, toners: TonerSet _ [black: TRUE], feed, strip: BOOLEAN _ TRUE] ~ { pdState.feed _ feed; pdState.strip _ strip; pdState.toners _ toners; pdState.firstToner _ Toner.LAST; pdState.lastToner _ Toner.FIRST; FOR t: Toner IN [Toner.FIRST..Toner.LAST] DO IF toners[t] THEN { IF pdState.bands[t] = NIL THEN { pdState.bands[t] _ NEW [BandsRec[pdState.bands[black].maxBands]]; }; IF pdState.firstToner = Toner.LAST THEN pdState.firstToner _ t; pdState.lastToner _ t; }; pdState.colorDescriptor[t] _ [ colorId: 0, length: 1, command: [control[setColorInk]], setColorTile: [addr: 0], enabled: toners[t] ]; ENDLOOP; }; SetColorInk: PUBLIC PROC [pdState: PDState, toner: Toner] = { IF NOT pdState.toners[toner] THEN ERROR; pdState.colorDescriptor[toner].colorId _ pdState.colorDescriptor[toner].colorId + 1; pdState.colorDescriptor[toner].length _ SIZE[PDFileFormat.Command]; pdState.colorDescriptor[toner].command _ [control[setColorInk]]; pdState.colorDescriptor[toner].enabled _ TRUE; }; SetColorClear: PUBLIC PROC [pdState: PDState, toner: Toner] = { IF NOT pdState.toners[toner] THEN ERROR; pdState.colorDescriptor[toner].colorId _ pdState.colorDescriptor[toner].colorId + 1; pdState.colorDescriptor[toner].length _ SIZE[PDFileFormat.Command]; pdState.colorDescriptor[toner].command _ [control[setColorClear]]; pdState.colorDescriptor[toner].enabled _ TRUE; }; SetColorOff: PUBLIC PROC [pdState: PDState, toner: Toner] = { pdState.colorDescriptor[toner].enabled _ FALSE; }; SetColorTile: PUBLIC PROC [pdState: PDState, toner: Toner, tileRef: LoadReference, tFlag: TFlag] = TRUSTED { loadEntry: LoadEntryDescription _ pdState.loadDescription[tileRef]; reference: Basics.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; IF NOT pdState.toners[toner] THEN ERROR; pdState.colorDescriptor[toner] _ [ colorId: colorId, length: SIZE[PDFileFormat.Command] + SIZE[PDFileFormat.SetColorTile], command: [control[setColorTile, tBit]], setColorTile: [addr: reference.lc], enabled: TRUE ]; }; DoForEachToner: PUBLIC PROC [pdState: PDState, proc: PROC[Toner]] = { FOR toner: Toner IN [pdState.firstToner..pdState.lastToner] DO IF pdState.toners[toner] THEN 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 IF pdState.colorDescriptor[toner].enabled THEN { 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 IF pdState.colorDescriptor[toner].enabled THEN { currentToner _ toner; deliverProc[CaptureRun]; PutBuffer[]; }; ENDLOOP; }; ColorSamples: PUBLIC PROC [pdState: PDState, toner: Toner, sMin, fMin: CARDINAL, sSize, fSize: CARDINAL, deliverProc: DeliverSampleArrayProc, tFlag: TFlag] = TRUSTED { colorCommand: PDFileFormat.Command _ [imaging[IF tFlag = opaque THEN colorSamples ELSE maskSamples]]; 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; }; IF pdState.colorDescriptor[toner].enabled THEN { 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]]; countedVM: CountedVM.Handle _ CountedVM.Allocate[pdState.loadSizeInWords]; loadDescription.storageRef _ countedVM; TRUSTED {loadDescription.pointer _ CountedVM.Pointer[countedVM]}; loadDescription.words _ CountedVM.Words[countedVM]; 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: Basics.HighHalf[origin], offsetLowBits: Basics.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 _ Basics.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: Basics.HighHalf[startOffset], offsetLowBits: Basics.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 _ Basics.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: Basics.HighHalf[startOffset], offsetLowBits: Basics.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]; IF pdState.toners[t] THEN { WriteStartImage[ pdState: pdState, feed: t = pdState.firstToner AND pdState.feed, strip: t = pdState.lastToner AND pdState.strip, toner: t, passBands: startBand, nBands: nBands, fMinPage: pdState.fMinPage, fSizePage: fSizePage ]; WriteBands[pdState, bands, startBand, nBands]; pdState.currentImage _ pdState.currentImage + 1; }; ENDLOOP; pdState.sMinPage _ pdState.herald.imageSSize; pdState.fMinPage _ pdState.herald.imageFSize; pdState.sMaxPage _ pdState.fMaxPage _ 0; IF pdState.overflowStream # NIL THEN pdState.overflowStream.SetIndex[0]; StartImage[pdState]; }; 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]; }; }; ObjectFallsOutsideOfDeclaredPageBounds: ERROR ~ CODE; 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]; IF pdState.sMaxPage > pdState.herald.imageSSize THEN ERROR ObjectFallsOutsideOfDeclaredPageBounds; IF pdState.fMaxPage > pdState.herald.imageFSize THEN ERROR ObjectFallsOutsideOfDeclaredPageBounds; }; 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: Basics.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.overflowStream _ FS.StreamOpen[fileName: "PDTemp$", accessOptions: $create]; }; bandBuffer.overflowIndices _ CONS[ IO.GetIndex[pdState.overflowStream], bandBuffer.overflowIndices ]; pdState.overflowStream.UnsafePutBlock[[base: bandDataPtr, startIndex: 0, count: 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: Basics.UnsafeBlock = [base: loadDescription.pointer+pdState.loadWrittenLength, startIndex: 0, count: 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 { base: LONG POINTER ~ @lc; pdState.stream.UnsafePutBlock[[base: base, startIndex: 0, count: SIZE[LONG CARDINAL]*bytesPerWord]]; }; WriteCardinal: PROC [pdState: PDState, c: CARDINAL] = TRUSTED { base: LONG POINTER ~ @c; pdState.stream.UnsafePutBlock[[base: base, startIndex: 0, count: SIZE[CARDINAL]*bytesPerWord]]; }; WriteHerald: PROC [pdState: PDState] = TRUSTED { base: LONG POINTER ~ @pdState.herald; pdState.stream.UnsafePutBlock[[base: base, startIndex: 0, count: SIZE[PDFileFormat.Herald]*bytesPerWord]]; }; WriteControlCommand: PROC [pdState: PDState, controlCom: PDFileFormat.ControlCom] = TRUSTED { command: PDFileFormat.Command _ [control[controlCom]]; base: LONG POINTER ~ @command; pdState.stream.UnsafePutBlock[[base: base, startIndex: 0, count: SIZE[PDFileFormat.Command]*bytesPerWord]]; }; 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] ]; base: LONG POINTER ~ @startImageBuf; pdState.stream.UnsafePutBlock[[base: base, startIndex: 0, count: SIZE[StartImageBuf]*bytesPerWord]]; }; 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; base: LONG POINTER ~ @overflowBuf; pdState.overflowStream.SetIndex[overflowIndices.first]; IF bandBufferSize*bytesPerWord # pdState.overflowStream.UnsafeGetBlock[[ base: base, startIndex: 0, count: bandBufferSize*bytesPerWord ]] THEN ERROR; pdState.stream.UnsafePutBlock[[base: base, startIndex: 0, count: bandBufferSize*bytesPerWord]]; {t: LIST OF INT _ overflowIndices; overflowIndices _ t.rest; t.rest _ NIL}; ENDLOOP; pdState.stream.UnsafePutBlock[[base: LOOPHOLE[@(bandBuffer.word)], startIndex: 0, count: bandBuffer.length*bytesPerWord]]; bandBuffer.length _ 0; }; WriteControlCommand[pdState, endBand]; bands[bandNum].colorId _ 0; ENDLOOP; }; END. òPDFileWriterImpl.mesa Copyright c 1984 Xerox Corporation. All rights reserved. Michael Plass, April 30, 1984 4:54:01 pm PDT Doug Wyatt, October 15, 1984 5:06:29 pm PDT 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. Note - this relys on FS to do the right thing when multiple instances of the file writer are around. The version number mechanism should keep us out of trouble. Writes out any additions to the font load Writes out the bands, resetting them along the way. Reverse the list of overflow indices. Ê#z˜šœ™Jšœ Ïmœ.™9J™,J™+—J˜šÏk ˜ JšœžœS˜_Jšœ žœ$˜3Jšžœžœ˜Jšžœžœ(žœ"˜XJšœ žœÍ˜ßJšœ žœe˜wJšœžœ ˜Jšœžœžœ˜J˜—šœžœž˜Jšžœžœžœ˜0Jšžœ ˜šœž˜J˜—šÏn œžœžœ žœžœ žœžœžœ˜VJšœž œžœA˜SJ˜—šŸœžœžœ žœžœ žœžœžœž œ˜cšžœ žœžœž˜Jšœ%žœžœ˜AJšœžœžœ˜!Jšœžœžœ˜Jšœžœžœ˜Jšžœ˜—Jšžœ žœ9˜JJšœ˜J˜—Jšœžœ˜-Jšœ žœ˜+Jšžœžœžœ˜Jšœžœžœ˜JšŸœžœ$˜=JšŸœžœ˜3JšŸœžœ'˜CJšŸœžœ$˜=Jšœžœ˜!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šœžœžœ˜/šœžœžœ˜#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šœ˜J˜—šŸœžœžœ žœYžœ žœ žœžœžœžœ˜õJšœžœ˜ Jšœ žœ˜Jšœ˜Jšœ'˜'Jšœ)˜)Jšœ)˜)Jšœ:˜:Jšœ:˜:Jšœ%˜%Jšœ˜Jšœ˜Jšœžœ ˜'Jšœ$˜$Jšœžœ˜"Jšœ(˜(Jšœžœ˜Jšœžœ˜$JšœY˜YJšœžœ˜.Jšœ2˜2šœ˜J™=—Jšœ˜J˜—š Ÿœžœžœ'žœžœžœ˜uJšœ*˜*Jšœ.˜.Jšœ˜J˜—š Ÿ œžœžœ/žœžœžœ˜mJšœ˜Jšœ˜Jšœ˜Jšœžœ˜ Jšœžœ˜ š žœ žœžœžœž˜,šžœ žœ˜šžœžœžœ˜ Jšœžœ+˜AJšœ˜—Jšžœžœžœ˜?Jšœ˜Jšœ˜—šœ˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜—Jšž˜—Jšœ˜J˜—šŸ œžœžœ%˜=Jšžœžœžœžœ˜(JšœT˜TJšœ(žœ˜CJšœ@˜@Jšœ)žœ˜.Jšœ˜J˜—šŸ œžœžœ%˜?Jšžœžœžœžœ˜(JšœT˜TJšœ(žœ˜CJšœB˜BJšœ)žœ˜.Jšœ˜J˜—šŸ œžœžœ%˜=Jšœ)žœ˜/Jšœ˜J˜—šŸ œžœžœJžœ˜lJšœC˜CJšœk˜kJšœ žœ.˜:Jšœžœžœžœ˜`Jšžœ žœžœ˜-Jšžœžœžœžœ˜(šœ"˜"Jšœ˜Jšœžœžœ˜EJšœ'˜'Jšœ#˜#Jšœ ž˜ Jšœ˜—Jšœ˜J˜—šŸœžœžœžœ ˜Ešžœžœ)ž˜>Jšžœžœ ˜*Jšžœ˜—Jšœ˜J˜—š Ÿ œžœžœžœžœ˜LJšœ!˜!Jšœ!˜!Jšœ˜J˜—š Ÿ œžœžœ žœžœžœ˜gJš œžœžœžœžœ˜GJšœ žœ˜/Jšœ<˜šžœ(žœ˜0Jšœžœžœ ˜DJšœ!˜!Jšœ!žœ˜=Jšœ"žœ˜Dšžœžœ žœž˜>Jšœ˜Jšœ!žœ˜=Jšœ"žœ˜DJšžœ˜—Jšœ˜—Jšžœ˜—Jšœ˜J˜—šŸ œžœžœ!žœžœžœžœ˜†Jš œžœžœžœžœ˜GJšœ žœ˜/Jšœ<˜šžœ(žœ˜0Jšœžœžœ ˜DJšœ!˜!Jšœ!žœ˜=Jšœ"žœ˜Dšžœžœ žœž˜>Jšœ˜Jšœ!žœ˜=Jšœ"žœ˜DJšžœ˜—Jšœ˜—Jšžœ˜—Jšœ˜J˜—š Ÿœžœžœ5žœžœžœ˜uJšœF˜FJšœk˜kJšœT˜Tšœ%˜%Jšœ%˜%Jšœ ˜ Jšœ ˜ Jšœ˜—JšœžœžœžœK˜jJš œžœžœžœžœ˜WJšœ žœ˜/Jšžœ#žœžœ˜0Jšœ˜JšœN˜Nšžœžœ)ž˜>šžœ(žœ˜0Jšœžœžœ ˜DJšœ!˜!Jšœ!žœ˜=Jšœžœ˜Ašžœžœ žœž˜>Jšœ˜Jšœ!žœ˜=Jšœžœ˜AJšžœ˜—Jšœ˜—Jšžœ˜—Jšœ˜J˜—šŸ œžœžœžœžœ žœ žœ)žœ˜žJšœ:˜:Jšœ žœ˜/Jšœžœ'˜8Jšœ˜Jšœ.˜.šžœžœ)ž˜>šžœ(žœ˜0Jšœžœ˜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šœ˜J˜—š Ÿœžœžœ6žœžœžœ˜wJšœG˜GJšœk˜kJšœU˜Ušœ&˜&Jšœ%˜%Jšœ ˜ Jšœ ˜ Jšœ˜—Jš œ žœžœžœžœ6˜XJš œ žœžœžœžœ2˜TJš œžœžœžœžœ˜KJšœ žœ˜/Jšžœ$žœžœ˜1Jšœ˜Jšœ6˜6šžœžœ)ž˜>šžœ(žœ˜0Jšœžœžœ ˜DJšœ!˜!Jšœ!žœ˜=Jšœžœ ˜Bšžœžœ žœž˜>Jšœ˜Jšœ!žœ˜=Jšœžœ ˜BJšžœ˜—Jšœ˜—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šœ˜—šžœžœ)ž˜>šžœ(žœ˜0Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜—Jšžœ˜—Jšœ˜J˜—šŸ œžœžœ&žœžœžœ7žœ˜§Jšœ.žœžœžœ˜eJšœ žœ˜/Jšœžœ'˜8Jšœžœ˜Jšœžœ˜Jšœžœ˜š Ÿœžœžœžœžœ˜Ešžœžœ˜šœ"˜"Jšœ˜Jšœ ˜ Jšœ˜—Jšœžœžœžœ ˜Fšœ)˜)Jšœ-˜-Jšœ ˜ Jšœ˜—Jšœ˜Jšœ&žœ˜BJšœžœ˜>Jšœ%žœ˜EJšœ˜—Jšœ:˜:Jšœ(˜(J˜ Jšœ˜—šžœ(žœ˜0Jšœ˜Jšœ.˜.Jšœ˜Jšžœžœžœ˜#Jšžœ žœžœ˜J˜—Jšœ˜J˜—š Ÿœžœžœžœ žœ˜JJšœ>˜>JšžœžœžœBžœ ˜uJšœ˜J˜—šŸœžœžœ˜Išžœžœžœ˜'Jšœ#žœ#˜IJšœJ˜JJšœ'˜'Jšžœ:˜AJšœ3˜3Jšœ˜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šœ0˜0J˜—Jšžœ˜—Jšœ-˜-Jšœ-˜-Jšœ(˜(Jšžœžœžœ$˜HJšœ˜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˜#Jšœ$˜$Jšœ$žœ˜*Jšœ˜—Jšœ˜J˜—šœ(žœžœ˜5J˜—šŸœžœžœžœ˜?Jšœžœ˜,Jšœžœ˜,Jšœžœ˜,Jšœžœ˜,Jšžœ.žœžœ(˜bJšžœ.žœžœ(˜bJšœ˜J˜—šŸœžœžœžœ˜TJšœ žœ!˜-Jšœ$˜$Jšžœžœžœžœ˜WJšœ˜Jšœ"˜"Jšœ˜J˜—šŸ œžœžœžœ˜MJšœ žœ*˜6Jšœ0˜0Jšœ3˜3Jšœžœ˜1JšœQ˜QJšœ žœ!˜-Jšœ$˜$Jšžœžœžœžœ˜WJšœ˜Jšœ"˜"šžœ!žœ˜*Jšœ!˜!šžœžœ˜#Jšœ)žœ˜EJšœ)žœžœ˜9J˜—Jšœi˜iJšœ˜—Jšœ˜J˜—šŸœžœ.žœ˜NJšœ žœžœ˜/šžœžœžœ˜&JšœT˜TJ™¡Jšœ˜—šœžœ˜"Jšžœ"˜$Jšœ˜Jšœ˜—Jšœn˜nJšœ˜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šœžœžœ˜JšœAžœžœžœ˜dJšœ˜J˜—šŸ œžœžœžœ˜?Jšœžœžœ˜JšœAžœžœ˜_Jšœ˜J˜—šŸ œžœžœ˜0Jšœžœžœ˜%JšœAžœ%˜jJšœ˜J˜—šŸœžœ;žœ˜]Jšœ6˜6Jšœžœžœ ˜JšœAžœ&˜kJšœ˜J˜—šŸœžœ˜Jšœ˜Jšœžœ˜Jšœžœ˜Jšœ ˜ Jšœ žœ˜Jšœžœ˜ Jšœ žœ˜Jšœ ž˜Jšœžœ˜ š œžœžœž œžœ˜0Jšœ˜Jšœ˜Jšœ˜—šœ ˜ Jšœ$˜$Jšœ¢˜¢Jšœ˜—Jšœžœžœ˜$JšœAžœ˜dJšœ˜J˜—šŸ œžœ5žœžœ˜UJ™3šžœ žœžœž˜4Jšœ3˜3šžœžœžœ˜Jš œžœžœžœžœ˜#J™%šžœžœž˜)Jšœžœžœžœ˜,Jšœ=˜=Jšœ˜Jšœ˜Jšžœ˜—šžœžœž˜Jšœ žœžœžœ˜3Jšœžœžœ˜"Jšœ7˜7šžœ˜ šœ'˜'Jšœ ˜ Jšœ˜Jšœ"˜"Jšœ˜——Jšžœžœ˜ Jšœ_˜_Jš œžœžœžœ7žœ˜KJšžœ˜—Jšœ%žœM˜zJšœ˜Jšœ˜—Jšœ&˜&Jšœ˜Jšžœ˜—Jšœ˜J˜—Jšžœ˜——…—| £