-- CGBandDeviceImpl.mesa -- Last changed by Ken Pier, July 11, 1983 6:03 pm -- Last changed by Eric Bier, November 16, 1982 4:07 pm DIRECTORY CGBandDevice, GraphicsBasic USING [Box, Trap], GraphicsColor USING [Color, ColorToIntensity, ColorToRGB, black, white], CGBandStream USING[BandPrefix, BandIndex, BandStreamHandle, OpenBand, PutBand, CloseBand], CGBandFormat USING [ObjectRef, Object, objectSize, Run, runSize, LineRef, Line, HeraldRef, HeraldObject, heraldObjectSize, EndRef, EndObject, endObjectSize, TBrickRef, TBrickRep, tBrickSize], CGBrick USING [BrickHandle, GetCurrentBrick, GetRow, GetCol, GetSize], CGArea USING [Ref, Remove, Empty], CGColor USING [GetStipple], CGDevice USING [Ref, Rep], CGMatrix USING [Ref, Make, Inv, InvRel], CGScreen USING [Bits], CGSource USING [Type, Ref], CGStorage USING [qZone, pZone], UnsafeStorage USING[GetSystemUZone], Inline USING [LongNumber, LowByte, LongCOPY], Environment USING[bitsPerWord], CGFullSample USING [Pointer, SAMPLE, Table], PressNetDefs USING [PrinterAttributes, GetPrinterAttributes], Real USING [Fix, FixC, Float]; CGBandDeviceImpl: PROGRAM IMPORTS CGArea, CGColor, CGBandStream, CGBrick, CGMatrix, CGScreen, CGStorage, Real, UnsafeStorage, PressNetDefs, Inline, CGFullSample, GraphicsColor EXPORTS CGBandDevice, GraphicsBasic = { OPEN Area: CGArea, Brick: CGBrick, BDevice: CGBandDevice, Device: CGDevice, Matrix: CGMatrix, Source: CGSource, BStream: CGBandStream, BFormat: CGBandFormat, GB: GraphicsBasic, GC: GraphicsColor, Real; DeviceObject: PUBLIC TYPE = CGDevice.Rep; -- exported to GraphicsBasic dataZone: ZONE = CGStorage.qZone; repZone: ZONE = CGStorage.qZone; pZone: ZONE = CGStorage.pZone; uZone: UNCOUNTED ZONE _ UnsafeStorage.GetSystemUZone[]; bitsPerWord: CARDINAL = Environment.bitsPerWord; Byte: TYPE = [0..377B]; Error: SIGNAL = CODE; Data: TYPE = REF DataRep; DataRep: TYPE = RECORD [ base: LONG POINTER, -- base address of bitmap raster: CARDINAL, -- bitmap words per line lines: CARDINAL, -- bitmap lines matrix: Matrix.Ref, -- virtual to device transformation matrix htBrick: REF CGBrick.BrickHandle, -- for halftoning bands: BDevice.BandRef --list of band parameters for each band ]; New: PUBLIC PROC[bDevice: BDevice.BandDevice] RETURNS[Device.Ref] = { bCount: CARDINAL; data: Data _ dataZone.NEW[DataRep _ [ base: NIL, raster: 0, lines: 0, matrix: NIL, htBrick: NIL, bands: NIL]]; [base: data.base, raster: data.raster, height: data.lines, matrix: data.matrix, bandCount: bCount] _ GetBParameters[bDevice]; data.htBrick _ CGBrick.GetCurrentBrick[]; oldBh _ NIL; data.bands _ InitBands[data.lines, data.raster, bCount, bDevice]; RETURN[repZone.NEW[Device.Rep _ [ GetMatrix: GetMatrix, GetBounds: GetBounds, Show: Show, GetRaster: GetRaster, data: data]]]; }; GetMatrix: SAFE PROC[self: Device.Ref] RETURNS[Matrix.Ref] = CHECKED { data: Data _ NARROW[self.data]; RETURN[data.matrix]; }; GetBounds: SAFE PROC[self: Device.Ref] RETURNS[GB.Box] = TRUSTED { data: Data _ NARROW[self.data]; w: CARDINAL _ 16*data.raster; h: CARDINAL _ data.lines; e: REAL = 0.1; -- small fudge factor RETURN[[xmin: e, ymin: e, xmax: w-e, ymax: h-e]]; }; GetRaster: SAFE PROC[self: Device.Ref] RETURNS[LONG POINTER,CARDINAL] = TRUSTED { data: Data _ NARROW[self.data]; RETURN[data.base,data.raster]; }; Show: SAFE PROC[self: Device.Ref, area: Area.Ref, src: Source.Ref, map: Matrix.Ref] = TRUSTED { data: Data _ NARROW[self.data]; UNTIL Area.Empty[area] DO trap: GB.Trap _ Area.Remove[area]; ShowTrap[data,trap,src,map]; ENDLOOP; }; Close: PUBLIC PROC[self: Device.Ref] = { data: Data _ NARROW[self.data]; bands: BDevice.BandRef _ data.bands; bcount: CARDINAL _ bands.count; FOR bI: BStream.BandIndex IN [0..bcount) DO BStream.PutBand[bands[bI].stream, endRef, BFormat.endObjectSize]; BStream.CloseBand[bands[bI].stream];--tho already closed, must release space ENDLOOP; };--Close GetBParameters: PUBLIC PROC[b: BDevice.BandDevice] RETURNS [base: LONG POINTER, raster,height: CARDINAL, matrix: Matrix.Ref, bandCount, brickloadSize, fontloadSize: CARDINAL _ 0] = { pA: PressNetDefs.PrinterAttributes; base _ NIL; --no direct screen refs for building bands SELECT b FROM screen => { [ , raster, height] _ CGScreen.Bits[]; matrix _ Matrix.Make[[1,0,0,-1,0,height]];--y _ Height-y bandCount _ 4; }; hornet => { pA _ PressNetDefs.GetPrinterAttributes[Stinger]; raster _ Real.FixC[((Real.Float[pA.resolutionB]*Real.Float[pA.scanLengthInches]/10) +bitsPerWord-1)/bitsPerWord]; height _ Real.FixC[Real.Float[pA.resolutionS]*8.5]; matrix _ Matrix.Make[[0, pA.resolutionB/72.0, pA.resolutionS/72.0, 0, 0, 0]]; bandCount _ 16; }; platemaker => { pA _ PressNetDefs.GetPrinterAttributes[DLP1]; raster _ Real.FixC[((Real.Float[pA.resolutionB]*Real.Float[pA.scanLengthInches]/10) +bitsPerWord-1)/bitsPerWord]; height _ Real.FixC[Real.Float[pA.resolutionS]*11.0]; matrix _ Matrix.Make[[pA.resolutionB/72.0, 0, 0, -pA.resolutionS/72.0, 0, height]]; bandCount _ 72; }; ENDCASE => ERROR; }; SetSeparation: PUBLIC PROC[s: BDevice.Separation] = { colorSep _ s; }; InitBands: PROC [lines, raster, bandCount: CARDINAL, bDevice: BDevice.BandDevice] RETURNS [bRef: BDevice.BandRef] = { bandHeight: CARDINAL _ (lines + bandCount - 1)/bandCount; bandName: LONG STRING = "PBAND."L; heraldRef^ _ [mark: --Marker--, flags: [type: herald, rect: FALSE], band: ,--7777B unused: , device: bDevice, bandCount: bandCount, bandHeight: bandHeight, bandWidth: raster]; bRef _ repZone.NEW[BDevice.BandsRep[bandCount] _ [count: bandCount, height: bandHeight, width: raster, list: ]]; FOR i: CARDINAL IN [0..bandCount) DO bRef[i] _ [ymin: i*bandHeight, ymax: (i+1)*bandHeight, stream: BStream.OpenBand[ bandName, i, overwrite]]; ENDLOOP; --PBAND.0 _ herald record: BStream.PutBand[bRef[0].stream, heraldRef, BFormat.heraldObjectSize]; --get a scanline buffer for "raster" words lineRef _ uZone.NEW[Scanline[(raster+bitsPerWord-1)*bitsPerWord]]; --get a run buffer large enough for the max # of runs possible for this device runsRef _ uZone.NEW[RunsBuffer[bandHeight]]; };--InitBands Bot: PROC[r: REAL] RETURNS[CARDINAL] = INLINE { RETURN[Real.FixC[r]] }; Top: PROC[r: REAL] RETURNS[CARDINAL] = INLINE { RETURN[Real.FixC[r]+1] }; Fix: PROC[r: REAL] RETURNS[CARDINAL] = INLINE { RETURN[Real.FixC[r]] }; Rnd: PROC[r: REAL] RETURNS[CARDINAL] = INLINE { RETURN[Real.FixC[r+.5]] }; RndI: PROC[r: REAL] RETURNS[INTEGER] = INLINE { RETURN[Real.FixC[r+(LAST[INTEGER]+.5)]-LAST[INTEGER]] }; Frac: TYPE = Inline.LongNumber; fscl: Frac = [num[lowbits: 0, highbits: 1]]; FixF: PROC[r: REAL] RETURNS[Frac] = INLINE { RETURN[[li[Real.Fix[r*fscl.li]]]] }; ShowTrap: PROC [data: Data, trap: GB.Trap, src: Source.Ref, map: Matrix.Ref] = { type: Source.Type _ src.type; easy: BOOLEAN _ (SELECT type FROM const, tile => TRUE, -- always easy array => FALSE, -- never easy proc => ERROR, --can't handle procs any more ENDCASE => ERROR); maskOnly: BOOLEAN _ src.bps=0;--kludge yb,yt,yl,xl,xr, yStart, objHeight: CARDINAL _ 0; rdxl,rdxr: REAL _ 0; -- left and right x increments rsdx,rsdy: REAL _ 0; -- increments for source position fsdx,fsdy: Frac; -- fractional versions of source position fat: BOOLEAN _ src.fat; rect: BOOLEAN _ FALSE; bps: CARDINAL = 8;--assumed for constant color trapezoids maxSample: REAL = 255.0;--should be 2**bps bSampPerWord: CARDINAL = bitsPerWord/bps; hy: CARDINAL; -- index into halftone cBrick lpx: CARDINAL _ 0;-- (L*px) bands: BDevice.BandRef _ data.bands; bandCount: CARDINAL _ bands.count; bI: BStream.BandIndex _ 0; DoHardLine: PROC[xmin,xmax,y: CARDINAL] = { rsx,rsy: REAL; -- current source position IF xmin>=xmax THEN RETURN; -- degenerate run tPtr.count _ (xmax-xmin); IF ~maskOnly THEN { hy _ CGBrick.GetRow[bH, 0, y]; tPtr.bLine _ LOOPHOLE[cBrick+SIZE[NAT]+((L*hy)/bSampPerWord)]; --pointer to row of brick samples tPtr.bi _ CGBrick.GetCol[bH, xmin, y]--+((L*hy) MOD bSampPerWord)--; -- starting x in brick }; [[rsx,rsy]] _ Matrix.Inv[map,[xmin+0.5,y+0.5]]; tPtr.sx _ FixF[rsx].li; tPtr.sy _ FixF[rsy].li; tPtr.sdx _ fsdx.li; tPtr.sdy _ fsdy.li; CGFullSample.SAMPLE[tPtr]; BStream.PutBand[bands[bI].stream, lineRef, (tPtr.count+bitsPerWord-1)/bitsPerWord]; };--DoHardLine DoRun: PROC[xmin, xmax: CARDINAL] = { runsRef[runsIndex] _ [xmin: xmin, xmax: xmax]; runsIndex _ runsIndex+1; }; -- main code for ShowTrap starts here bH _ data.htBrick^; IF bH#oldBh THEN {--prepare bricks [L,p,D] _ CGBrick.GetSize[bH];--either cBrick or tBrick needs this lpx _ L*p; IF cBrick.size < lpx THEN {--need bigger brick buffers uZone.FREE[@cBrick]; uZone.FREE[@tBrickTemp]; cBrick _ uZone.NEW[CBrick[lpx]]; tBrickTemp _ uZone.NEW[BFormat.TBrickRep[lpx]]; };--need bigger brick buffers --fill in the scaled brick FOR px: CARDINAL IN [0..p) DO lpx _ L*px; FOR lx: CARDINAL IN [0..L) DO cBrick[lpx+lx] _ Inline.LowByte[Fix[maxSample*bH.cBrick[lpx+lx]]]; ENDLOOP; ENDLOOP; oldBh _ bH};--prepare bricks --Initialize the nearly constant parts of the sample table if needed IF ~easy THEN { tPtr.dLine _ lineRef; --initialize scanline buffer tPtr.sBase _ src.xbase; -- pointer to first word of source array tPtr.sRast _ src.xrast; -- words per raster line in source array tPtr.sh _ LAST[CARDINAL]; --large faked value IF ~maskOnly THEN { --general array with source and brick tPtr.bConst _ tPtr.sConst _ FALSE; tPtr.mConst _ TRUE; tPtr.bw _ L; -- width of brick row, in samples tPtr.size _ src.bps; -- sample size for source and brick tPtr.sw _ src.xrast*(bitsPerWord/tPtr.size); tPtr.function _ 14B; --opaque } ELSE { --mask only, no brick, use source like a mask tPtr.bConst _ tPtr.mConst _ TRUE; tPtr.sConst _ FALSE; tPtr.bValue _ 0; tPtr.size _ 1; tPtr.sw _ src.xrast*bitsPerWord; tPtr.function _ 3B; --transparent }; }; FOR bI IN [0..bandCount) DO IF SplitTrap[trap, bands[bI]] --writes the global lTrap-- THEN {--lTrap is in current band -- compute yb (bottom of first scanline) and yt (top of last scanline) IF fat THEN { yb_Bot[lTrap.ybot]; yt_Top[lTrap.ytop] } ELSE { yb_Rnd[lTrap.ybot]; yt_Rnd[lTrap.ytop] }; IF ybyt OR fat THEN SIGNAL Error; GO TO exit };--skip this degenerate lTrap -- /////////////////////////////////////////////////////////////////////////////// rect _ objectRef.flags.rect _ (lTrap.xbotL = lTrap.xtopL) AND (lTrap.xbotR = lTrap.xtopR); objectRef.band _ bI; yStart _ objectRef.yStart _ yb; objHeight _ objectRef.height _ yt-yb; -- ////////////////////////////////////////////////////////////////////////////// -- begin scan conversion; generate ALL runs first runsIndex _ 0; [[rsdx,rsdy]] _ Matrix.InvRel[map,[1,0]]; fsdx _ FixF[rsdx]; fsdy _ FixF[rsdy]; rdxl_(lTrap.xtopL-lTrap.xbotL); -- delta x, left rdxr_(lTrap.xtopR-lTrap.xbotR); -- delta x, right IF NOT(fat AND yb=yl) THEN { rdy: REAL_lTrap.ytop-lTrap.ybot; -- delta y rdxl_rdxl/rdy; rdxr_rdxr/rdy; -- dx/dy, left right }; IF fat THEN { rxlb,rxrb,rxlt,rxrt: REAL _ 0; -- x at bottom and top of current line ltop: BOOLEAN _ rdxl<0; -- TRUE means leftmost x is at top of line rtop: BOOLEAN _ rdxr>0; -- TRUE means rightmost x is at top of line FOR y: CARDINAL IN[yb..yl] DO -- for each scan line IF y=yb THEN { rxlb_lTrap.xbotL; rxrb_lTrap.xbotR } -- first line ELSE { rxlb_rxlt; rxrb_rxrt }; -- successive lines IF y=yl THEN { rxlt_lTrap.xtopL; rxrt_lTrap.xtopR } -- last line ELSE IF y=yb THEN { -- first line, if yl>yb d: REAL_(yb+1)-lTrap.ybot; -- distance to top of line rxlt_rxlb+d*rdxl; rxrt_rxrb+d*rdxr; } ELSE { rxlt_rxlb+rdxl; rxrt_rxrb+rdxr }; -- middle lines xl_Bot[IF ltop THEN rxlt ELSE rxlb]; xr_Top[IF rtop THEN rxrt ELSE rxrb]; IF xl<=xr THEN DoRun[xmin: xl, xmax: xr] ELSE ERROR; IF rect THEN EXIT; ENDLOOP; } ELSE { rxl,rxr: REAL _ 0; -- left and right x at middle of current line FOR y: CARDINAL IN[yb..yl] DO -- for each scan line IF y=yb THEN { -- first line d: REAL_(yb+0.5)-lTrap.ybot; -- distance to middle of line rxl_lTrap.xbotL+d*rdxl; rxr_lTrap.xbotR+d*rdxr; } ELSE { rxl_rxl+rdxl; rxr_rxr+rdxr }; -- successive lines xl_Rnd[rxl]; xr_Rnd[rxr]; IF xl<=xr THEN DoRun[xmin: xl, xmax: xr] ELSE ERROR; IF rect THEN EXIT; ENDLOOP; }; -- now generate the actual data for the runs runsWords _ BFormat.runSize*runsIndex; IF easy THEN { -- three cases for constant: all0, all1, threshold a brick if other IF src.type = tile THEN { tBrickTemp.L _ 16; tBrickTemp.p _ 16; tBrickTemp.D _ 0; tBrickTemp.color _ LAST[CARDINAL];--unused tBrickTemp.brickSize _ 256; tBrickWords _ BFormat.tBrickSize+16; Inline.LongCOPY[to: @tBrickTemp.brick+1, from: src.xbase, nwords: 16]; objectRef.flags.type _ brick; } ELSE IF src.color.tag = stipple THEN { tBrickTemp.L _ 4; tBrickTemp.p _ 4; tBrickTemp.D _ 0; tBrickTemp.color _ CGColor.GetStipple[src.color]; tBrickTemp.brickSize _ 16; tBrickWords _ BFormat.tBrickSize+1; LOOPHOLE[@tBrickTemp.brick+1, LONG POINTER]^ _ tBrickTemp.color; objectRef.flags.type _ brick; } ELSE IF src.color = GC.black OR src.color = GC.white THEN objectRef.flags.type _ IF src.color = GC.black THEN all1 ELSE all0 ELSE { -- intensity other than black or white tBrickTemp.L _ L; tBrickTemp.p _ p; tBrickTemp.D _ D; tBrickTemp.color _ FixC[maxSample*GetColorSep[src.color]]; tBrickTemp.brickSize _ L*p; tBrickWords_BFormat.tBrickSize+(tBrickTemp.brickSize+bitsPerWord-1)/bitsPerWord; FOR px: CARDINAL IN [0..p) DO lpx _ L*px; FOR lx: CARDINAL IN [0..L) DO tBrickTemp[lpx+lx] _ IF tBrickTemp.color >= Fix[maxSample*bH[lpx+lx]] THEN FALSE ELSE TRUE; ENDLOOP; ENDLOOP; objectRef.flags.type _ brick; };-- intenstiy other than black or white --write out the completed Object (sans Runs) BStream.PutBand[bands[bI].stream, objectRef, BFormat.objectSize]; BStream.PutBand[bands[bI].stream, runsRef, runsWords];--write runs IF objectRef.flags.type = brick THEN BStream.PutBand[bands[bI].stream, tBrickTemp, tBrickWords];--write tBrick }--three easy cases ELSE { -- hard case objectRef.flags.type _ bits; BStream.PutBand[bands[bI].stream, objectRef, BFormat.objectSize];--write object BStream.PutBand[bands[bI].stream, runsRef, runsWords];--write out the runs FOR rI: CARDINAL IN [0..objHeight) DO -- write out successive scanlines runsIndex _ IF rect THEN 0 ELSE rI; -- must use (not band relative) y=yStart+rI DoHardLine[xmin: runsRef[runsIndex].xmin, xmax: runsRef[runsIndex].xmax, y: yStart+rI]; ENDLOOP; };-- hard case EXITS exit => NULL; };--lTrap is in current band ENDLOOP;-- end of [0..bcount) loop };--ShowTrap SplitTrap: PROC [t: GB.Trap, band: BDevice.Band] RETURNS [BOOLEAN _ TRUE] = { --this proc takes a trapezoid and a band and "returns" --the interesection of these in global lTrap bymin: REAL _ band.ymin;--bottom line included in band bymax: REAL _ band.ymax;--top line included in band xbotL,xbotR,ybot,xtopL,xtopR,ytop: REAL; maxratio: REAL; --first case: t completely out of band IF t.ytop < bymin OR t.ybot > bymax THEN RETURN[FALSE]; xbotL _ t.xbotL; xbotR _ t.xbotR; ybot _ t.ybot; xtopL _ t.xtopL ; xtopR _ t.xtopR ; ytop _ t.ytop ; --second case: t body in band, t top above band IF ytop > bymax THEN { lTrap.ytop _ bymax; -- band relative coordinate of top of band maxratio _ (bymax-ybot)/(ytop-ybot);--zero denom blows up lTrap.xtopR _ xbotR + maxratio*(xtopR-xbotR); lTrap.xtopL _ xbotL + maxratio*(xtopL-xbotL); } ELSE {--third case: t top in band lTrap.ytop _ ytop; lTrap.xtopL _ xtopL; lTrap.xtopR _ xtopR; }; --fourth case: t bottom in band IF ybot >= bymin THEN { lTrap.ybot _ ybot; lTrap.xbotL _ xbotL; lTrap.xbotR _ xbotR; } ELSE { --fifth case: t bottom below band lTrap.ybot _ bymin; maxratio _ (bymin-ybot)/(ytop-ybot);--zero denom blows up lTrap.xbotR _ xbotR + maxratio*(xtopR-xbotR); lTrap.xbotL _ xbotL + maxratio*(xtopL-xbotL); }; };--SplitTrap GetColorSep: PROC [color: GC.Color] RETURNS [REAL] = { SELECT colorSep FROM red=> RETURN [GC.ColorToRGB[color].r]; green => RETURN [GC.ColorToRGB[color].g]; blue => RETURN [GC.ColorToRGB[color].b]; none => RETURN [GC.ColorToIntensity[color]]; ENDCASE => ERROR; }; -- START CODE --brick storage brickStartSize: CARDINAL = 100;--nominal size for bricks CBrick: TYPE = RECORD[PACKED SEQUENCE size: NAT OF Byte]; cBrick: LONG POINTER TO CBrick _ uZone.NEW[CBrick[brickStartSize]]; tBrickTemp: BFormat.TBrickRef _ uZone.NEW[BFormat.TBrickRep[brickStartSize*bitsPerWord]]; tBrickWords: CARDINAL _ 0;--size of actual tBrick calculated lTrap: REF GB.Trap _ repZone.NEW[GB.Trap _ [0,0,0,0,0,0, FALSE, FALSE]]; L,p: CARDINAL;--brick is L wide by p high D: INTEGER _ 0; heraldRef: BFormat.HeraldRef _ uZone.NEW[BFormat.HeraldObject]; --storage for herald obj endRef: BFormat.EndRef _ uZone.NEW[BFormat.EndObject]; --initialized by this NEW call objectRef: BFormat.ObjectRef _ uZone.NEW[BFormat.Object[1]]; --object head buffer RunsBuffer: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF BFormat.Run]; RunsRef: TYPE = LONG POINTER TO RunsBuffer; runsRef: RunsRef _ NIL; -- initialized by InitBands runsIndex: CARDINAL _ 0; -- runs buffer index runsWords: CARDINAL _ 0; -- runsIndex*SIZE[Run] Scanline: TYPE = BFormat.Line; LineRef: TYPE = BFormat.LineRef; lineRef: LineRef _ NIL; -- initialized by InitBands lineIndex: CARDINAL _ 0;-- Scanline bit index defaultTable: CGFullSample.Table _ [ function: 0, -- function mConst: FALSE, -- mask value is constant bConst: FALSE, -- brick value is constant sConst: FALSE, -- source value is constant useMap: FALSE, -- look up sample values in map size: 0, -- sample size, for brick and source count: 0, -- number of samples to process bValue: 0, -- constant brick value, used if bConst=TRUE sValue: 0, -- constant source value, used if sConst=TRUE -- destination and mask information dLine: NIL, -- pointer to row of destination bits mLine: NIL, -- pointer to row of mask bits di: 0, -- starting bit index in destination mi: 0, -- starting bit index in mask -- source to sample mapping table map: NIL, -- brick information bLine: NIL, -- pointer to row of brick samples bi: 0, -- starting sample index in brick bw: 0, -- width of brick row, in samples -- source information sBase: NIL, -- pointer to first word of source array sRast: 0, -- words per raster line in source array sSpare: 0, -- not used sw: 0, -- width of source, in samples sh: 0, -- height of source, in lines sox: 0, -- x offset of source, in samples soy: 0, -- y offset of source, in lines sx: 0, -- starting x position in source * 2^16 sy: 0, -- starting y position in source * 2^16 sdx: 0, -- increment to source x position * 2^16 sdy: 0 -- increment to source y position * 2^16 ]; tPtr: CGFullSample.Pointer _ uZone.NEW[CGFullSample.Table _ defaultTable]; colorSep: BDevice.Separation _ none; bH, oldBh: CGBrick.BrickHandle _ NIL; }. -- CGBandDeviceImpl LOG --created 15-Feb-82 14:10:40 by Pier -- complete rewrite for new band file format --changed to use LONG POINTERS instead of REFs, removed singleFile, 3/30/82 --swapped Heap with UnsafeStorage; NIL out all bases 5/3/82 --fixed bug in DLP bandcount, increasing from 32 to 72, 5/17/82 --fixed bug in SAMPLE setup when src.bps=0; eliminated MONITOR, 5/24/82 --changed to use color as defined in CGColor, 6/28/82 --upgrade to Cedar 3.2, 7/13/82 --upgrade to Cedar 3.3, added color separation kludge, September 18, 1982 --fixed bug in inverted tBricks, September 21, 1982 3:23 pm Bier on October 11, 1982 11:02 am Changed platemaker page size back to 11.0 and number of bands to 72. Ę M˜Jš Īc“œĪk œ!žœžœEžœtžœķžœCžœ!žœžœžœ&žœžœžœ!žœžœ0žœžœ žœžœ3žœ(žœžœ›žœ"žœĒžœžœ&žœžœœ žœžœžœž œžœ0žœ"žœžœžœ žœžœžœžœ žœžœœ žœœ žœœ+œ žœœ(œĪnœžœžœžœžœžœžœžœ žœ žœŧžœHžœ žœ{Ÿ œžœžœžœžœžœžœŸ œžœžœžœžœžœžœžœžœžœœžœ2Ÿ œžœžœžœžœžœžœžœžœžœŸœžœžœGžœžœžœžœ žœ@žœŸœžœžœ&žœ>žœžœžœ žœo)œžœœŸœžœžœ+žœžœžœžœržœ9žœ+œžœžœnœ–žœžœŸ œžœžœ5Ÿ œžœžœ#žœ,žœ2žœžœ$ œžœ œ‘žœužœžœžœžœƒžœœJ+œžœ2Oœžœ œŸœžœžœžœžœžœžœŸœžœžœžœžœžœžœŸœžœžœžœžœžœžœŸœžœžœžœžœžœžœŸœžœžœžœžœžœžœžœžœžœžœ žœDŸœžœžœžœ žœžœ ŸœžœžœUžœžœžœžœœ žœœ žœœžœžœžœ  œ)žœžœœ žœ"œ*œ žœžœžœ žœ(œ žœ œžœžœœžœ œ8žœ0Ÿ œžœžœžœœ žœ žœžœœ#žœ žœ;žœžœžœžœ"œ+œœŽžœf œŸœžœ žœf&œžœ žœœžœžœ%œ žœžœžœœ žœžœ$žœ(žœ"œœžœžœžœžœ žœ žœžœžœžœžœPžœžœœEœžœžœœ)œ)œžœžœœžœ žœ&œ"žœžœžœ"œ(œN œ žœ.œ"žœžœkœžœžœžœžœœžœœ Gœžœžœ2žœ3žœžœ œžœžœžœžœžœžœžœœSœMžœ‹Rœ 2œ—œ&œžœžœžœžœžœ œ&œžœžœ žœ'œžœ +œžœ ,œžœžœžœ žœœ žœžœ(œ žœœ žœžœ( œ žœžœžœœžœœHžœ%œžœžœžœžœžœžœžœžœžœžœžœžœžœ žœžœžœ.œ žœžœžœ žœœ žœžœœžœœWžœ!œ2žœžœžœžœžœžœžœžœ-œ9žœžœDœ žœžœžœ%žœ%žœžœ œņžœžœžœžœ#žœ žœžœžœcžœžœ žœžœ žœžœ$žœ žœžœžœ žœ'œžœžœžœžœlžœmžœžœžœžœžœžœžœžœžœžœ&žœ/žœžœžœžœžœžœ;'œ-œˆ œžœžœFœ œ žœ œjœ>œžœžœžœžœ"œžœžœžœ,œižœ  œžœžœ œžœœ œŸ œžœžœžœžœžœdœ žœ œ žœ œ%žœžœ'œžœžœžœžœžœv0œžœžœ+œ(œržœœX œžœžœ[žœ"œ@œo œŸ œžœ žœžœžœžœ žœ žœžœ$žœžœ#žœžœ#žœžœžœžœ œœžœœžœžœžœžœžœžœžœžœžœžœ@žœ>žœ#œžœžœžœžœžœžœžœžœžœžœ,žœœ"žœœ%žœœ žœžœžœžœžœžœžœžœžœžœ žœœ žœœ žœœ žœžœ(žœœ žœœ6 œ žœœ žœœ žœœ žœ œ %œ œ-œ.œ$œ žœ&œ žœ œ %œ œ#œžœœ žœ#œ "œ "œœ žœ)œ )œ œ œ œ "œ  œ (œ (œ )œ )œ+žœkžœ œžœ'œ+ėœg˜Ŧ¨—…—T.^