// ScanConvert.bcpl // modified by Ramshaw, January 20, 1982 12:12 PM // - if Transparent, then don't count on sync codes being monotonically // increasing. Thus, check colors not codes. // Now use syncInfinity, instead of '9999' (shrug) // modified by Ramshaw, December 15, 1981 9:28 PM // - Use Ugt to compare sync's instead of "gr" // last modified by Ramshaw, March 20, 1981 1:33 PM // - ScanConvert, keep maximum character size in longLines, so // don't let longLines nextBogusChar get above longLines - 10/20 // - ScanConvert, have 15 extended rectangles - 10/16 // - ScanConvert, have ScanChar call ScanCharFault - 9/30 // - ScanConvert, don't let longLines nextBogusChar get above longIccMax - 8/8 // - this file is Joe's changed version - 4/17/80 // errors 1300 // //Controller for scan conversion process. // //ScanConvertInit() // Assumes the "file" statics contain pointers to files. Sets up // various buffers, etc. (e.g., character hash table & storage areas) // %%%% Here's where to pre-load character table %%%% //ScanConvertClose() // Finishes current scan conversion session. //ScanConvert(pg,CopyToPrint) // Scan converts the page described by the PageG structure pg, and // writes it onto the bits file starting at pg>>PageG.BitPage. Returns // number of pages of the bits file used, or -1 if not enough available. // CopyToPrint is the copy number -- governs band list interp. // pg is filled up with PageG structure of goodies. // get "PressInternals.df" get "PressParams.df" // outgoing procedures external [ ScanConvertInit ScanConvertClose ScanConvert ScanColorPassValue //to scanconvert2 ] // outgoing statics external [ //State to other "scan" routines: ScanBuf //Core buffer for bits ScanBitWc //Word count for a scan line ScanBitMargin mpSBuf //Map scan-line in band (0-15) to scan buffer ScanS //Scan line number of first in buffer ScanMin ScanMax Left1RB //RB's for leftovers (for ScanChars) Left2RB FMCycles //Font memory cycles (for metering) currentScanColor //Current color set up in ink well ScanHalftoneDot colorCache ] static [ ScanBuf ScanBitWc mpSBuf ScanBitMargin ScanS ScanMin ScanMax Left1RB Left2RB FMCycles currentScanColor ScanHalftoneDot colorCache ] // incoming procedures external [ ///SCANCONVERT2 ScanColor //SCANCHARS ScanCharInit ScanCharClose ScanChar ScanCharLO ScanCharColor //SCANDOTS InitScreen ScanDotsInit ScanDotsClose ScanDots GCD //SCANOBJECTS ScanObjectInit ScanObjectClose ScanObject //WINDOW WindowInit WindowClose WindowSetPosition WindowGetPosition WindowReadBlock WindowWriteBlock WindowNext WindowWrite WindowRead //FILES FileWritePage FileStuff //METER MeterBlock MeterTime //PRESS PressError FSGet;FSGetX FSPut GetTime DblShift //PRESSML DoubleCop DoubleAdd;DoubleAddV DoubleSub;DoubleShr MulDiv DivFull BitBLT //OS Ugt MoveBlock Zero //CURSOR CursorChar CursorDigit CursorToggle ] // incoming statics external [ //Files needed BitsFile BandFile LeftOverFile1 LeftOverFile2 BESizes //Table of lengths of BE entries. DPzero //Double-precision zero nBands ICCtot UseMicroCode Report Debug SoftScan TShirtMode InvertMode Transparent nPrinterColors printerDevice ScreenModulus //for determining color table screen frequency ScreenAngle ] external longLines; // from PreChars // internal statics static [ BandRB //RB for Bands (a Window) BandWriter //output window for Bands lastLeftOverSync //File position where last sync stored ColorPass pctSynthetic FlipVec blackPass ] compileif DebugSw then [ static [ ScanStop] ] //Debugging compileif ReportSw then [ static [ ConvertTimeIn] ] // File-wide structure and manifest declarations. manifest [ BitBLTFlag=false ] structure [ lh byte rh byte ] // Procedures let ScanConvertInit() be [ compileif ReportSw then [ ConvertTimeIn=GetTime() ] CursorChar($C) compileif offset RB.Base ne offset W.Base then [ foo=0 ] ScanCharInit() //Get char tables ScanObjectInit() //And object tables ScanDotsInit() BandRB=WindowInit(BandFile, 2) BandWriter=WindowInit(BandFile, 1) Left1RB=WindowInit(LeftOverFile1, 1) Left2RB=WindowInit(LeftOverFile2, 1) @DoubleAdd=DoubleAddTrap @DoubleSub=DoubleSubTrap @DoubleShr=DoubleShrTrap pctSynthetic = (nPrinterColors eq 4)?50,100 colorCache=FSGetX(256) colorCache!0=table [ 1;0;1;-1] colorCache!255=table [ 1;0;1;0] Zero(colorCache+1,254) if TShirtMode then [ FlipVec=FSGetX(256) for i=0 to 255 do [ let val=0 if (iÈ) ne 0 then val=1 if (id) ne 0 then val=val+#002 if (i() ne 0 then val=val+#004 if (i) ne 0 then val=val+#010 if (i ) ne 0 then val=val+#020 if (i) ne 0 then val=val+#040 if (i) ne 0 then val=val+#100 if (i) ne 0 then val=val+#200 FlipVec!i=val ] ] ] and ScanConvertClose() be [ FSPut(colorCache) ScanCharClose() ScanObjectClose() ScanDotsClose() WindowClose(BandRB) WindowClose(BandWriter) WindowClose(Left1RB) WindowClose(Left2RB) @DoubleAdd=NoTrap @DoubleSub=NoTrap @DoubleShr=NoTrap compileif ReportSw then [ GetTime(lv Report>>REP.ConvertTime, ConvertTimeIn) ] ] and ScanConvert(pg, CopyToPrint) = valof [ //Compute size of core buffer for bits. ColorPass=pg>>PageG.ColorPass //fucking bcpl & is a bit operation, not a logical one!!! let black=(pg>>PageG.ColorUsed)?false,true if black&(printerDevice eq printerPuffin)&(ColorPass ne 0) then resultis 0 blackPass=(nPrinterColors ls 4)% (ColorPass eq 3)% (black&(printerDevice eq printerPuffin)&(ColorPass eq 0)) ScanBitWc=pg>>PageG.BitWc //Get length of scan line. let lScanBuf=ScanBitWc*BANDWidth ScanBitMargin=pg>>PageG.BitMargin //Set bits file parameters let BitPage=pg>>PageG.BitPage //Units are 1024 words let nPagesPerBuf=((lScanBuf+1023)/1024) let nPagesWritten=0 let nWordsWritten=0 let usePages=(pg>>PageG.LastBand-pg>>PageG.FirstBand+1)*nPagesPerBuf let fl=vec 1 FileStuff(BitsFile, fl) DblShift(fl, 10) //Convert to 1024-word pages let BitLimit=fl!1 //test overflow later (whole bitmap is not written out) // if BitPage+usePages gr fl!1 then resultis -1 //Will not fit let nextBuffFreeList=FSGetX(BandWriter>>W.BufSize) let nextBuffFreeIndex=0 //Now guaranteed to do some work: CursorDigit(pg>>PageG.PageNumber) let SCStats=vec (size SCStat/16) compileif MeterSw then [ Zero(SCStats, (size SCStat/16)) SCStats>>SCStat.TimeIn=MeterTime() ] //Allocate scan buffer: ScanBuf=FSGetX(lScanBuf+1) //One core buffer (for now) //Reason for +1 is to make address checks // in ScanPutChar easier..(debug only) let OutputBuf=FSGetX(4097) //should be 4096: when real BitBLT gets used //Make table of beginning addresses of scan lines. Each address is // offset by the known margin (in words) let lmpSBuf=vec 16 let p=ScanBuf-(pg>>PageG.BitMargin/16) for i=0 to 15 do [ lmpSBuf!i=p p=p+ScanBitWc ] mpSBuf=lmpSBuf //Allocate color table [ let v=vec size BEDots/16 v>>BEDots.ScreenModulus=ScreenModulus //default frequency setting v>>BEDots.ScreenAngle=(table [ 30;0;60;45])!ColorPass if nPrinterColors eq 1 then v>>BEDots.ScreenAngle=ScreenAngle //default v>>BEDots.IMin=0 v>>BEDots.IMax=64 v>>BEDots.ScreenAmplitude=100 unless InitScreen(v) do [ PressError(1620);finish] let screenDef=v>>BEDots.ScreenStart let nWords,nLines,D=screenDef!0,screenDef!1,screenDef!2 let outputWordsPerLine=nWords/nLines ScanHalftoneDot=FSGetX(nWords+4) MoveBlock(ScanHalftoneDot+4,screenDef+3,nWords) FSPut(screenDef) let lenTurnOn=outputWordsPerLine let wordD=-1 [ for x=0 to lenTurnOn-1 do if ((x*16) rem lenTurnOn) eq D then [ wordD=x;break] if wordD ge 0 then break if (outputWordsPerLine&1) eq 1 then PressError(1306) outputWordsPerLine=outputWordsPerLine rshift 1 let newSHD=FSGetX(nWords*2+4) MoveBlock(newSHD,ScanHalftoneDot,nWords+4) for i=0 to nLines-1 do [ let Offset=4+i*lenTurnOn MoveBlock(newSHD+nWords+Offset,ScanHalftoneDot+Offset+D, lenTurnOn-D) MoveBlock(newSHD+nWords+Offset+lenTurnOn-D,ScanHalftoneDot+Offset, D) ] FSPut(ScanHalftoneDot) ScanHalftoneDot=newSHD nWords=nWords*2 D=(D*2) rem lenTurnOn nLines=nLines*2 ] repeat ScanHalftoneDot!0=outputWordsPerLine ScanHalftoneDot!1=wordD ScanHalftoneDot!2=nLines ScanHalftoneDot!3=lenTurnOn ] currentScanColor=-1 //Make 2-word vector to hold file pos in output leftover file of // last sync entry let vv=vec 1 lastLeftOverSync=vv //Pass global information to microcode if UseMicroCode then [ let v=vec 5 v!0=mpSBuf v!1=ScanBitWc ( table [ ScanLoadVarsTrap ] )(v) ] //Set Band position WindowSetPosition(BandRB, lv pg>>PageG.BandPos) WindowSetPosition(BandWriter, lv pg>>PageG.BandPos) //Set up RB's for bands, leftover stuff. WindowSetPosition(Left1RB, DPzero) let LeftOverOut=Left1RB //Write into LeftOverOut let LeftOverRB=Left2RB //Read from LeftOverRB //Note that first band and last band were calculated at prescan time // by knowing limits (in scan direction) of image. Thus there will be // an empty leftover list where this loop exits. let nextBogusChar=#100000+ICCtot CursorToggle(pg>>PageG.ColorPass) for b=pg>>PageG.FirstBand to pg>>PageG.LastBand do [ CursorToggle(0,MulDiv(b,600,nBands)) test SoftScan then [ ScanMin=pg>>PageG.BitMargin;ScanMax=ScanMin+pg>>PageG.BitWc*16] or [ ScanMin=4096;ScanMax=0] ScanS=b*BANDWidth let StartingBandPos=vec 3 compileif MeterSw then [ StartingBandPos!2=0; StartingBandPos!3=0 FMCycles=StartingBandPos+2 //Count memory cycles needed WindowGetPosition(BandRB, StartingBandPos) ] compileif DebugSw then [ if ScanStop ne 0 & (ScanStop𒿑) eq ScanS then PressError(1300) ] Zero(ScanBuf,lScanBuf) //Massive zeroing! //Switch leftover tables let t=LeftOverRB LeftOverRB=LeftOverOut LeftOverOut=t //Set up access to old leftovers for this band. let cRB=LeftOverRB //Current RB. WindowWrite(LeftOverRB,BEEndH) //Put 2 terminators on the leftover WindowWrite(LeftOverRB,BEEndH) //One for us, one for ScanCharFault to see let ReadingLeftOvers=true LeftOverRB>>RB.Sync=0 //Init sync stuff Zero(lv LeftOverRB>>RB.Color,lColor) ScanColor(table [ 0;0]) LeftOverRB>>RB.Reading=true WindowSetPosition(LeftOverRB, DPzero) //Start reading at beginning //And the new band stuff BandRB>>RB.Sync=0 Zero(lv BandRB>>RB.Color,lColor) //And position new leftover window. WindowSetPosition(LeftOverOut, DPzero) LeftOverOut>>RB.Reading=false lastLeftOverSync!0=-1 //No syncs out yet in leftover let v=vec BEMaxSize+10 //To hold long BE's [ //For all BE's (bands+leftover) if cRB>>RB.Offset eq 0 then AdvanceRB(cRB) let off=cRB>>RB.Offset let a=(cRB>>RB.Base)!off cRB>>RB.Offset=off+1 //Read a word of BE //Now dispatch appropriately. let LeftOverCount=0 v!0=a compileif offset BEH.Cbit ne 0 % size BEH.Cbit ne 1 then [ foo=nil ] test (a&CharBit) ne 0 //*** Testing for Cbit *** ifso [ //A Character if cRB>>RB.Offset eq 0 then AdvanceRB(cRB) let off=cRB>>RB.Offset v!1=(cRB>>RB.Base)!off cRB>>RB.Offset=off+1 //Read next word. compileif size BEChar/16 ne 2 then [ foo=0 ] test ReadingLeftOvers then [ if cRB>>RB.Offset eq 0 then AdvanceRB(cRB) let off=cRB>>RB.Offset v!2=(cRB>>RB.Base)!off cRB>>RB.Offset=off+1 //Read next word. if cRB>>RB.Offset eq 0 then AdvanceRB(cRB) let off=cRB>>RB.Offset v!3=(cRB>>RB.Base)!off cRB>>RB.Offset=off+1 //Read next word. compileif size BELOChar/16 ne 4 then [ foo=0 ] LeftOverCount=ScanCharLO(v) //Process character ] or [ unless SoftScan%(a eq CharBit)%(currentScanColor ne 0) do WindowWriteBlock(BandWriter,v,size BEChar/16) LeftOverCount = ScanChar(v); // Process character ] ] ifnot [lf //Something less frequent! v!0=a //First word. for i=1 to BESizes!a-1 do [ if cRB>>RB.Offset eq 0 then AdvanceRB(cRB) let off=cRB>>RB.Offset v!i=(cRB>>RB.Base)!off cRB>>RB.Offset=off+1 //Read next word. ] switchon a into [ case BESyncH: case BEEndH: [ //Call a procedure to deal with the sync point. Returns 0 (no leftovers), // -1 (end of processing this band). May write a leftover by hand. let a=ScanSyncProc(v,lv cRB,LeftOverRB,BandRB) if a ls 0 then break //All done with band! ReadingLeftOvers=(cRB eq LeftOverRB) ] endcase case BECopyH: [ LeftOverCount=0 unless ( v>>BECopy.Copy eq 0 % v>>BECopy.Copy eq CopyToPrint ) then [ //Call a procedure to pass up stuff not for this copy. It may encounter // sync points as it does so. In this case, it returns true, and sets // the vector v to contain an appropriate sync point, which must then // be processed as above. let a=ScanCopyProc(v,cRB,CopyToPrint) if a then [ a=ScanSyncProc(v,lv cRB,LeftOverRB,BandRB) if a ls 0 then break ReadingLeftOvers=(cRB eq LeftOverRB) ] ] ] endcase case BEDotsH: [ LeftOverCount=ScanDots(v,ReadingLeftOvers) ] endcase case BEExtendedRectangleH: //only called if SoftScan true case BERectangleH: LeftOverCount=ScanObject(v,ReadingLeftOvers) if (not SoftScan)&(currentScanColor eq 0)&(not ReadingLeftOvers) then //ORbit will do the work WindowWriteBlock(BandWriter,v,size BERectangle/16) endcase case BELineH: case BESplineH: case BEEndObjectH: [ LeftOverCount=ScanObject(v,ReadingLeftOvers) ] endcase default: if a gr BEExtendedRectangleH & a le BELastRectangleH then docase BEExtendedRectangleH; // otherwise fall through case BEMaxH + 1: [ PressError(1301); endcase; ] ] ]lf //ifnot if LeftOverCount then [ //Write out stuff. compileif DebugSw then [ if LeftOverCount ls 0 % LeftOverCount gr BEMaxSize then PressError(1302) ] WindowWriteBlock(LeftOverOut,v,LeftOverCount) ] ] repeat //For all BE's //Record size of leftovers compileif MeterSw then [ let t=vec 1 WindowGetPosition(LeftOverOut, t) let oloc=(t!1)/BandDistUnit //Left over out count let adr=(lv SCStats>>SCStat.LOSizes)+ ((oloc le BandDist-2)? oloc, BandDist-1) @adr=@adr+1 WindowGetPosition(LeftOverRB, t) let iloc=t!1 WindowGetPosition(BandRB, t) DoubleSub(t, StartingBandPos) iloc=(iloc+t!1)/BandDistUnit let adr=(lv SCStats>>SCStat.TotSizes)+ ((iloc le BandDist-2)? iloc, BandDist-1) @adr=@adr+1 let FMC=((FMCycles!0*2)+(FMCycles!1 rshift 15))*(#77777/FMCycleUnit)+ (FMCycles!1 & #77777)/FMCycleUnit let adr=(lv SCStats>>SCStat.FMCycleDist)+ ((FMC le nFMCycleDist-2)? FMC, nFMCycleDist-1) @adr=@adr+1 if oloc ls 0 % iloc ls 0 % FMC ls 0 then PressError(1303) ] if TShirtMode then //bit reverse ScanBuf [ let scanLineStart=ScanBitMargin/BANDWidth let scanLineEnd=scanLineStart+ScanBitWc-1 for s=0 to BANDWidth-1 do [ let firstAddr=mpSBuf!s+scanLineStart let lastAddr=mpSBuf!s+scanLineEnd for wordOffset=0 to (lastAddr-firstAddr)/2 do [ let leftWord=firstAddr!wordOffset let rightWord=lastAddr!(-wordOffset) let newL,newR=nil,nil newR< page boundary unless nWordsWritten eq 4096 do OutputBuf!nWordsWritten=1 //positive number is flush flag if (BitPage+nPagesWritten+4096/1024) gr BitLimit then resultis -1 //won't fit FileWritePage(BitsFile,BitPage+nPagesWritten,OutputBuf,4096/1024) nPagesWritten=nPagesWritten+4096/1024 nWordsWritten=0 nextBuffFreeList!nextBuffFreeIndex=b+1 nextBuffFreeIndex=nextBuffFreeIndex+1 ] OutputBuf!nWordsWritten=-w //-bits per scan line for ORbit OutputBuf!(nWordsWritten+1)=15 //width-1 for ORbit nWordsWritten=nWordsWritten+2 compiletest BitBLTFlag then [ //BITBLT!!!! let BLTv=vec 12;BLTv=(BLTv+1)&-2 BLTv!0=0 BLTv!3=4096 //Dest scan line length (don't care: just doing 1 scan line) BLTv!5=0 //Dest y offset BLTv!6=w //Dest width (and so, source width) BLTv!7=1 //Dest height BLTv!9=ScanBitWc BLTv!10=ScanMin //Source x offset BLTv!11=0 //Source y offset let iwWords,iwRem=0,0 for s=0 to BANDWidth-1 do [ BLTv!2=OutputBuf+nWordsWritten+iwWords //Dest BCA BLTv!4=iwRem //Dest x offset BLTv!8=mpSBuf!s //Source BCA BitBLT(BLTv) //optimize out the multiplications iwWords=iwWords+wWords iwRem=iwRem+wRem ] ] or//not BitBLTFlag, so MoveBlock [ let iwWords=0 for s=0 to BANDWidth-1 do [ MoveBlock(OutputBuf+nWordsWritten+iwWords, mpSBuf!s+ScanMin/BANDWidth, wWords) iwWords=iwWords+wWords ] ] nWordsWritten=nWordsWritten+w ] //end of "if ScanMin le ScanMax" WindowWriteBlock(BandWriter,table [ 0;0],2) //band terminator ] //end of non-ORbit case ] //end of "for b=firstband to lastband" //Write out meter compileif MeterSw then [ SCStats>>SCStat.TimeOut=MeterTime() MeterBlock(METERConvertPage,SCStats,(size SCStat/16)) ] unless printerDevice gr printerDurango do [ unless nWordsWritten eq 0 do [ if nWordsWritten eq 4096 then [ if (BitPage+nPagesWritten+4096/1024) gr BitLimit then resultis -1 FileWritePage(BitsFile,BitPage+nPagesWritten,OutputBuf,4096/1024) nWordsWritten=0 nPagesWritten=nPagesWritten+4096/1024 ] OutputBuf!nWordsWritten=0 ///end signal if (BitPage+nPagesWritten+4096/1024) gr BitLimit then resultis -1 //won't fit FileWritePage(BitsFile,BitPage+nPagesWritten,OutputBuf,4096/1024) nPagesWritten=nPagesWritten+4096/1024 ] //and insert two blank bands at the end WindowWriteBlock(BandWriter,table [ 0;0;0;0],4) let pageEnd=WindowNext(BandWriter) let v=vec 1;DoubleCop(v,lv pg>>PageG.BandPos) DblShift(v,BandWriter>>W.LogBufSize)//convert to pages pg>>PageG.nRecords=pageEnd-v!1 unless pg>>PageG.SimplePage do WindowWriteBlock(BandWriter,nextBuffFreeList,BandWriter>>W.BufSize) ] //end of ORbit cleanup case //shouldn't this stuff go in ScanConvertClose?? for i = 1 to 254 do if colorCache!i ne 0 then [ FSPut(colorCache!i);colorCache!i=0] FSPut(ScanHalftoneDot) FSPut(OutputBuf) FSPut(ScanBuf) FSPut(nextBuffFreeList) resultis nPagesWritten ] //AdvanceRB advances an RB structure to get a new usable window on // the structure. and AdvanceRB(rb) be [ WindowNext(rb,false) ] //ScanSyncProc // Process a sync point. May switch the current RB we are reading from. // Also may change color. If a leftover must be written, it does so // itself, and checks to make sure that two consecutive sync entries // are not written. // Returns: -1 if done with entire band. and ScanSyncProc(v,lvcRB,LeftOverRB,BandRB) = valof [ let cRB=@lvcRB //Current reading from let currentSync=cRB>>RB.Sync //Sync code we are currently doing. let currentColor=vec lColor MoveBlock(currentColor,lv cRB>>RB.Color, lColor) let otherRB=LeftOverRB xor BandRB xor cRB let sync=v>>BESync.Sync //New sync code we just came upon. if v>>BESync.H eq BEEndH then sync=syncInfinity //Save state of current RB (state= AFTER reading this sync) cRB>>RB.Sync=sync MoveBlock(lv cRB>>RB.Color,lv v>>BESync.Color,lColor) //Save so when we resume, correct //Now decide if we must switch. if Ugt(sync,otherRB>>RB.Sync) then [ @lvcRB=otherRB //Switched!!!!! cRB=otherRB ] //Now get stuff from newly current RB sync=cRB>>RB.Sync // If the sync we are about to execute is syncInfinity, we are done, because // it was generated by encountering an "End" indication: if sync eq syncInfinity then resultis -1 // If the sync we are about to process is the same as the one we // were processing when this procedure was called, there is // no need for a left-over or color change. // BUT: If Transparent mode is set, then sync codes will cycle, so we // must check for equal colors, not for equal sync codes. test Transparent ifso [ if currentColor>>Color.Hue eq cRB>>RB.Hue & currentColor>>Color.Saturation eq cRB>>RB.Saturation & currentColor>>Color.Intensity eq cRB>>RB.Intensity then resultis 0 ] ifnot [ if sync eq currentSync then resultis 0 ] if sync eq 0 then PressError(1304) //Should never output LO sync=0 ScanColor(lv cRB>>RB.Color) //Now set color //Prepare a leftover entry to record. v>>BESync.H=BESyncH //In case previous guy was end and this is leftover! v>>BESync.Sync=sync //Record new number. MoveBlock(lv v>>BESync.Color,lv cRB>>RB.Color,lColor) // Try to avoid duplicate sync entries in the leftover list. These // can pile up and slow down color selection tremendously. We do this // by remembering (in lastLeftOverSync) the file position just AFTER // we put out the previous sync entry. If we try to put out another // before an intervening (graphical) leftover has been put out, we // first back up the leftover file. let LeftOverOut=Left1RB xor Left2RB xor LeftOverRB let dpSyncSize= table [ 0;size BESync/16 ] let dp=vec 1 WindowGetPosition(LeftOverOut, dp) if dp!0 eq lastLeftOverSync!0 & dp!1 eq lastLeftOverSync!1 then [ //Back up over previous sync. DoubleSub(dp, dpSyncSize) WindowSetPosition(LeftOverOut, dp) ] WindowWriteBlock(LeftOverOut, v, size BESync/16) DoubleAdd(dp, dpSyncSize) DoubleCop(lastLeftOverSync, dp) resultis 0 ] and //ScanCopyProc // Scans ahead on the current RB (guaranteed to be the BandRB) and // returns when there is more info for this copy number. If there // is a sync point encountered along the way, returns true with the // vector v set up with a description of the last sync point. If no // sync point encountered, returns false. ScanCopyProc(v,cRB,CopyToPrint) = valof [ let sync=false let q=vec 10 [ let a=WindowRead(cRB) test a ls 0 then WindowRead(cRB) //Rest of char or [ v!0=a WindowReadBlock(cRB,v+1,BESizes!a-1) test a eq BESyncH then [ MoveBlock(q,v,10) sync=true ] or test a eq BEEndH then resultis true or if a eq BECopyH then [ if v>>BECopy.Copy eq 0 % v>>BECopy.Copy eq CopyToPrint then break ] ] ] repeat MoveBlock(v,q,10) resultis sync ] // returning 0 produces the most intense color here and ScanColorPassValue(colorV)=valof [ manifest [ RED=0; YELLOW=40; GREEN=80; CYAN=120 BLUE=160; MAGENTA=200 ] let hue=colorV>>Color.Hue if hue ge 240 then hue=0 //[240..255] all mean red by definition let sat=colorV>>Color.Saturation // 0 means grey let brightness = colorV>>Color.Intensity // 0 means very dark // if printing on a black-and-white printer: // colors print as 50% grey, greys print correctly if nPrinterColors eq 1 then resultis sat? 128, brightness // if it's a grey, then print it correctly // blackPass means this is a pass used to generate black // may be a color if it's a 3-color printer) // return nothing for (4-color) non-black pass if sat eq 0 then resultis blackPass? brightness, 255 let hueregion = (hue/40)*40 let amtmagenta, amtyellow, amtcyan = 0, 0, 0 switchon hueregion into [ // 40 = full saturation case RED: amtmagenta=YELLOW-hue; amtyellow=40; endcase case YELLOW: amtcyan=hue-YELLOW; amtyellow=40; endcase case GREEN: amtyellow=CYAN-hue; amtcyan=40; endcase case CYAN: amtmagenta=hue-CYAN; amtcyan=40 ; endcase case BLUE: amtcyan=MAGENTA-hue; amtmagenta=40; endcase case MAGENTA:amtyellow=hue-MAGENTA;amtmagenta=40;endcase ] amtmagenta = (amtmagenta*sat)/40 amtcyan = (amtcyan*sat)/40 amtyellow = (amtyellow*sat)/40 // at least one of these will be 0 let ourcolor = selecton ColorPass into [ case 0: amtmagenta case 1: amtyellow case 2: amtcyan case 3: 0 ] // following line says that amount of hue used to make black is // some proportion of amount of hue not used to make hue // because 255-ourcolor is hue remaining let black = MulDiv (255-ourcolor, 255-brightness, 255) // have now separated them as much as possible; // now put back the appropriate amount of synthetic black let synthamt = (pctSynthetic*black)/100 if ColorPass ne 3 then resultis 255 - (ourcolor+synthamt) // following line takes account of the fact that putting real black // over synthetic black results in some overlap resultis MulDiv (255, brightness, 255-synthamt) ] (1270)\17781i1I7296i10I (635)