// P R E B A N D -- Band management for prescan // errors 1200 // //BandWriteInit() // Called at beginning and end of prescan phase. //BandWriteClose() // Close out after all pages written //BandWriteBeginPage() // Call when beginning a new PRESS page. //BandWriteEndPage(pg) // Call when ending a PRESS page. The argument is a PageG // structure that specifies some things about the page (FirstBand // and LastBand must be filled in; BandPos will be filled in). //BandWrite(s,n) // Write n words from vector BandFree (BandFree!0, !1... !n-1) into // the band corresponding to scan-line s. Put out copy synch or // regular synch if necessary. //BandSync(color) // Record a sync point in the processing of band data. //BandOnCopy(n) // Called to say that following stuff is to appear only on copy n. // n=0 means on all copies. // //Needs description of how it works..... // get "PressInternals.df" get "PressParams.df" // outgoing procedures external [ BandWriteInit BandWriteClose BandWriteBeginPage BandWriteEndPage BandWrite BandSync BandOnCopy BandRecords ] // outgoing statics external [ BandFree BandWindow //Window on band file (needed for font load) BandCurHue;BandCurSat;BandCurBright ] static [ BandFree BandWindow //Window on band file BandCurHue;BandCurSat;BandCurBright ] // incoming procedures external [ //WINDOW WindowInit WindowClose WindowFlush WindowGetPosition WindowSetPosition WindowRead WindowWrite WindowReadBlock WindowWriteBlock WindowNext //PRESCAN PreFSGet //PRESS PressError FSGetX FSPut //PRESSML Ugt DoubleAdd DoubleAddV DoubleCop DoubleSub DivFull //OS MoveBlock Zero //METER MeterBlock //CURSOR CursorToggle ] // incoming statics external [ DPzero //Double precision zero. BandFile //File for bands. nBands //Number of bands required for this device BESizes PSStats //Statistics Report nLeadingBands;nVisibleBands;nTrailingBands nPrinterColors Transparent //allow sync codes to wrap around ] // internal statics static [ BandIndex //Table of band header pointers BandCopyT //Table of copy info for each band BandSyncT //Sync number for each band BandBuf //Pointer to in core portion of bands BandPos //File position of bands for this page BandSegments //Number of "dumps" on disk BandCurCopy //Current OnCopy number BandCurSync //Current sync count ] // File-wide structure and manifest declarations. // Procedures let BandWriteInit() be [ compileif BEMaxSize ge BANDInCoreSize then [ foo=0 ] BandBuf=FSGetX(BANDInCoreSize) BandIndex=FSGetX(nBands) BandCopyT=FSGetX(nBands) BandSyncT=FSGetX(nBands) BandWindow=WindowInit(BandFile,2) BandPos=FSGetX(nBandSegmentsMax*2+2) ] and BandWriteClose() be [ FSPut(BandBuf) FSPut(BandIndex) FSPut(BandCopyT) FSPut(BandSyncT) //WindowClose(BandWindow) now called from PreScanClose ] and BandWriteBeginPage() be [ BandSegments=0 //None on the disk. BandFree=BandBuf+1 //Place for user to put entry Zero(BandCopyT,nBands) Zero(BandSyncT,nBands) Zero(BandIndex,nBands) BandCurCopy=0 BandCurSync=0 BandCurHue=0 BandCurSat=0 BandCurBright=0 ] and BandWriteEndPage(pg) be [ if BandSegments eq 0 then //Can write it out directly [ BandFlush(pg) return ] BandFlush(0) //Go handle current buffer. //Now merge all the segments. // There are BandSegments segments to merge; BandPos!(segment*2) is // the double-word file position of the beginning of the segments. Bear // in mind that initially, all segments have bands running from 0 to nBANDS-1. // let numSegs=BandSegments let delta=pg>>PageG.FirstBand //Amount to pass up. for s=0 to numSegs-1 do //ignore initial empty bands DoubleAddV(BandPos+s*2, delta) [MergeLoop if numSegs le nMaxMergeInputs then [ //only one merge step is needed now BandMergeStep(pg, 0, numSegs-1, true) break ] //we will merge nMaxMergeInputs at a time let breadth=(numSegs+nMaxMergeInputs-1)/nMaxMergeInputs for c=0 to breadth-2 do [ let l=c*nMaxMergeInputs let r=l+nMaxMergeInputs-1 BandMergeStep(pg,l,r,false) ] //the final merge on this level has a funny right end point BandMergeStep(pg, (breadth-1)*nMaxMergeInputs, numSegs-1, false) //now, compact the answers down to the low end of BandPos array for i=1 to breadth-1 do DoubleCop(BandPos+i*2,BandPos+i*nMaxMergeInputs*2) numSegs=breadth ]MergeLoop repeat //insert two empty band commands for i=1 to 2 do WindowWriteBlock(BandWindow,DPzero,2) WindowNext(BandWindow) //and, if it's a graphic page, add padding+1 page for nextBandFreeList unless pg>>PageG.SimplePage do WindowNext(BandWindow) DoubleCop(lv pg>>PageG.BandPos, BandPos) //1 segment => done let endPos=vec 1 WindowGetPosition(BandWindow,endPos) DoubleSub(endPos,BandPos) pg>>PageG.nRecords=DivFull(endPos,BandWindow>>W.BufSize) pg>>PageG.ColorPass=0 for i=2 to nPrinterColors do [ CopyPage(pg,pg+(size PageG/16));pg=pg+(size PageG/16) ] ] and BandMergeStep(pg, firstSeg, lastSeg, finalMerge) be //merge the band segments from first to last, storing the result // back in the firstSeg slot. Don't put length headers on if the // finalMerge flag is true. [ let numToMerge=lastSeg-firstSeg+1 if numToMerge gr nMaxMergeInputs then PressError(1206) let winVec=vec nMaxMergeInputs let lenVec=vec nMaxMergeInputs WindowFlush(BandWindow) let rp=vec 1 WindowGetPosition(BandWindow, rp) for s=firstSeg to lastSeg do [ let a=PreFSGet(1024+30) //Hack to ensure enough core avail. FSPut(a) let w=WindowInit(BandWindow>>W.File ,1) winVec!(s-firstSeg)=w WindowSetPosition(w,BandPos+s*2) ] let v=vec 500 //Buffer for copying for b=pg>>PageG.FirstBand to pg>>PageG.LastBand do [BandLoop CursorToggle(2) let len=0 for s=0 to numToMerge-1 do [ let l=WindowRead(winVec!s) len=len+l lenVec!s=l ] unless finalMerge then WindowWrite(BandWindow, len) for s=0 to numToMerge-1 do [ let l=lenVec!s while l ne 0 do [ let tl=l if Ugt(tl,500) then tl=500 WindowReadBlock(winVec!s, v, tl) WindowWriteBlock(BandWindow, v, tl) l=l-tl ] ] if finalMerge then [ unless pg>>PageG.SimplePage then //bogus char for conversion WindowWriteBlock(BandWindow,table [ #100000;0],2) WindowWriteBlock(BandWindow,DPzero,2) //End code = [0;0] (ORbit). compileif MeterSw then [ len=(len+1)/BandDistUnit let adr=(lv PSStats>>PSStat.BandSizes)+ ((len le BandDist-2 )? len,BandDist-1) @adr=@adr+1 ] ] ]BandLoop for s=0 to numToMerge-1 do WindowClose(winVec!s) DoubleCop(BandPos+firstSeg*2, rp) //filePos of resulting merged segment ] and BandFlush(pg) be [ compileif MeterSw then [ MeterBlock(METERBandFlush) ] compileif ReportSw then [ if pg eq 0 then Report>>REP.BandFileSorts=Report>>REP.BandFileSorts+1 ] let fband=0 let lband=nBands-1 test pg then [ fband=pg>>PageG.FirstBand lband=pg>>PageG.LastBand WindowGetPosition(BandWindow,lv pg>>PageG.BandPos) ] or [ WindowGetPosition(BandWindow,BandPos+BandSegments*2) BandSegments=BandSegments+1 if BandSegments eq nBandSegmentsMax then PressError(1200) ] compileif DebugSw then [ if fband ls 0 % lband ge nBands then PressError(1202) ] for b=fband to lband do [ CursorToggle(2) //Reverse the list of entries for this band and count length let len=0 let prev=0 let p=BandIndex!b while p do [ compileif DebugSw then [ if (p!1&CharBit) eq 0 & p!1 gr BEMaxH then PressError(1203) if Ugt(BandBuf, p) % Ugt(p, BandBuf+BANDInCoreSize-1) then PressError(1204) ] let l=size BEChar/16 if (p!1&CharBit) eq 0 then l=BESizes!(p!1) len=len+l let next=p!0 p!0=prev prev=p p=next ] //Record lengths: compileif (size BEEnd/16) ne 2 then [ foo=nil] compileif ReportSw then //account for BEEnd [ DoubleAddV(lv Report>>REP.BandSize, len+2) ] //Record length distributions if final file: compileif MeterSw then [ let adr=(lv PSStats>>PSStat.BandSizes)+ ((len le BandDist-2 )? len,BandDist-1) if pg then @adr=@adr+1 ] //Now write out length (only if intermediate file) unless pg then WindowWrite(BandWindow,len) //Now write band entries -- open code for speed let off=BandWindow>>W.Offset while prev do [ let l=size BEChar/16 if (prev!1&CharBit) eq 0 then l=BESizes!(prev!1) test -off ge l ifso [ MoveBlock(BandWindow>>W.Base+off, prev+1, l) off=off+l ] ifnot [ BandWindow>>W.Offset=off WindowWriteBlock(BandWindow,prev+1,l) off=BandWindow>>W.Offset ] prev=prev!0 ] BandWindow>>W.Offset=off //Now write end code (only if final file) if pg then [ unless pg>>PageG.SimplePage do //bogus char for conversion WindowWriteBlock(BandWindow,table [ #100000;0],2) WindowWriteBlock(BandWindow,DPzero,2) ] ] //Now reset band buffer stuff BandFree=BandBuf+1 Zero(BandIndex,nBands) if pg eq 0 then return //just an intermediate stage //insert two empty band commands for i=1 to 2 do WindowWriteBlock(BandWindow,DPzero,2) WindowNext(BandWindow) unless pg>>PageG.SimplePage do WindowNext(BandWindow) //and record nRecords let endPos=vec 1 WindowGetPosition(BandWindow,endPos) DoubleSub(endPos,lv pg>>PageG.BandPos) pg>>PageG.nRecords=DivFull(endPos,BandWindow>>W.BufSize) pg>>PageG.ColorPass=0 for i=2 to nPrinterColors do [ CopyPage(pg,pg+(size PageG/16));pg=pg+(size PageG/16) ] ] and CopyPage(inPage,outPage) be [ MoveBlock(outPage,inPage,size PageG/16) outPage>>PageG.ColorPass=inPage>>PageG.ColorPass+1 unless inPage>>PageG.ColorUsed then return //identical!! WindowGetPosition(BandWindow,lv outPage>>PageG.BandPos) let inPos=vec 1;MoveBlock(inPos,lv inPage>>PageG.BandPos,2) //kludge for funny page counts: let evenBoundary=((inPos!1)&(BandWindow>>W.BufSize-1)) eq 0 unless evenBoundary do outPage>>PageG.nRecords=outPage>>PageG.nRecords+1 let outPos=vec 1;MoveBlock(outPos,lv outPage>>PageG.BandPos,2) let v=FSGetX(BandWindow>>W.BufSize) for i=1 to outPage>>PageG.nRecords do [ WindowSetPosition(BandWindow,inPos) WindowReadBlock(BandWindow,v,BandWindow>>W.BufSize) WindowSetPosition(BandWindow,outPos) WindowWriteBlock(BandWindow,v,BandWindow>>W.BufSize) DoubleAddV(inPos,BandWindow>>W.BufSize) DoubleAddV(outPos,BandWindow>>W.BufSize) ] FSPut(v) unless evenBoundary do WindowNext(BandWindow) ] and BandRecords(n)=valof [ let r=BandFile>>F.Pagesize resultis (n+r-1) rshift BandFile>>F.LogPagesize ] and BandSync(hue,sat,bright) be [ let change=false if hue ne BandCurHue then [ BandCurHue=hue;change=true] if sat ne BandCurSat then [ BandCurSat=sat;change=true] if bright ne BandCurBright then [ BandCurBright=bright;change=true] if change then BandCurSync=BandCurSync+1 if BandCurSync eq syncInfinity then test Transparent ifso // let sync's wrap around [ BandCurSync=1; Zero(BandSyncT, nBands) ] ifnot PressError(1205) ] and BandOnCopy(c) be [ BandCurCopy=c ] and BandWrite(s,n) be [ let b=s rshift LogBANDWidth //Band number if s ls 0 % b ge nBands then [ PressError(1201); return ] if BandCopyT!b ne BandCurCopy then [ //Need to put out copy code. BandCopyT!b=BandCurCopy let save=vec BEMaxSize MoveBlock(save,BandFree,BEMaxSize) BandFree>>BECopy.H=BECopyH BandFree>>BECopy.Copy=BandCurCopy BandWrite(s,size BECopy/16) MoveBlock(BandFree,save,BEMaxSize) ] if BandSyncT!b ne BandCurSync then [ //Need to put out sync code. BandSyncT!b=BandCurSync let save=vec BEMaxSize MoveBlock(save,BandFree,BEMaxSize) BandFree>>BESync.H=BESyncH BandFree>>BESync.Sync=BandCurSync BandFree>>BESync.Hue=BandCurHue BandFree>>BESync.Saturation=BandCurSat BandFree>>BESync.Intensity=BandCurBright BandWrite(s,size BESync/16) MoveBlock(BandFree,save,BEMaxSize) ] //Now can actually write n words into band b. The word before BandFree // is available for a pointer (amazing!) BandFree!-1=BandIndex!b //Link into list for this band BandIndex!b=BandFree-1 BandFree=BandFree+n+1 if Ugt(BandFree,BandBuf+(BANDInCoreSize-BEMaxSize-2)) then BandFlush(0) //Full -- flush and reset ]