<> <> <> <> DIRECTORY Basics USING [BITAND, BITOR, BITSHIFT, BITXOR, Byte, HighHalf, LongMult, LongNumber, LowByte, LowHalf], CGArea USING [Empty, Ref, Remove], CGColor USING [GetStipple], CGDevice USING [Ref, Rep], CGMatrix USING [Inv, InvRel, IsTrivial, Make, Ref], CGSource USING [Mode, Ref, Type], CGStorage USING [qZone], ColorDevice USING [], -- only for EXPORTS ColorMap USING [GetGrayTable, GrayTable, GetIndex, GrayRec], GraphicsBasic USING [Box, Color, Trap], GraphicsColor USING [blue, cyan, green, magenta, red, white, yellow], Interminal USING [terminal], PrincOps, PrincOpsUtils USING [AlignedBBTable, BITBLT], Real USING [Fix, FixC, RoundC], Terminal USING [GetColorBitmapState, GetColorMode, Virtual], TerminalExtras USING [LockColorFrame, UnlockColorFrame]; ColorDeviceImpl: MONITOR IMPORTS Basics, CGArea, CGColor, CGMatrix, CGStorage, ColorMap, Interminal, PrincOpsUtils, Real, Terminal, TerminalExtras EXPORTS ColorDevice, GraphicsBasic = { OPEN Area: CGArea, Matrix: CGMatrix, Source: CGSource, CGDevice, GraphicsBasic; DeviceObject: PUBLIC TYPE = CGDevice.Rep; -- exported to GraphicsBasic Byte: TYPE = Basics.Byte; dataZone: ZONE = CGStorage.qZone; repZone: ZONE = CGStorage.qZone; Error: PUBLIC SAFE ERROR = CODE; bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr _ PrincOpsUtils.AlignedBBTable[@bbspace]; terminal: Terminal.Virtual ~ Interminal.terminal; Data: TYPE = REF DataRep; DataRep: TYPE = RECORD [ width,height: CARDINAL _ 0, grayTable: ColorMap.GrayTable _ NIL, lastColor: Color _ [tag: rgb, r: 0, g: 0, b: 0], lastPixel: LONG CARDINAL, stipple: CARDINAL _ 0, <> matrix: Matrix.Ref _ NIL -- base transformation matrix ]; allOnes: LONG CARDINAL ~ LAST[LONG CARDINAL]; New: PUBLIC SAFE PROC[raster, height: CARDINAL _ 0] RETURNS[CGDevice.Ref] = CHECKED { data: Data _ dataZone.NEW[DataRep]; IF raster = 0 THEN data.width _ terminal.colorWidth ELSE data.width _ raster; IF height = 0 THEN data.height _ terminal.colorHeight ELSE data.height _ height; data.grayTable _ ColorMap.GetGrayTable[]; data.matrix _ Matrix.Make[[1,0,0,-1,0,data.height]]; --should be a function of pixelsPerInch RETURN[repZone.NEW[CGDevice.Rep _ [ GetMatrix: GetMatrix, GetBounds: GetBounds, Show: Show, GetRaster: GetRaster, MoveBlock: MoveBlock, data: data]]]; }; GetMatrix: SAFE PROC[self: Ref] RETURNS[Matrix.Ref] = CHECKED { data: Data _ NARROW[self.data]; RETURN[data.matrix]; }; GetBounds: SAFE PROC[self: Ref] RETURNS[Box] = CHECKED { data: Data _ NARROW[self.data]; w: CARDINAL _ data.width; h: CARDINAL _ data.height; e: REAL = 0.1; -- small fudge factor RETURN[[xmin: e, ymin: e, xmax: w-e, ymax: h-e]]; }; <> GetRaster: SAFE PROC[self: Ref] RETURNS[LONG POINTER,CARDINAL] = CHECKED { RETURN[NIL,0] }; Show: ENTRY SAFE PROC[self: Ref, area: Area.Ref, src: Source.Ref, map: Matrix.Ref] = TRUSTED { data: Data _ NARROW[self.data]; bitmap: BOOLEAN _ (src.type=array AND src.bps=0 AND CGMatrix.IsTrivial[map]); invertHack: LONG CARDINAL _ data.lastPixel; IF terminal.GetColorBitmapState=none THEN RETURN; --colordisplay is disconnected IF src.mode=invert THEN { IF terminal.GetColorMode.full THEN data.lastPixel _ allOnes ELSE data.lastPixel _ 255} ELSE SetColor[data,src.color]; --sets up the values for color IF NOT terminal.GetColorMode.full AND src.bps >0 AND ~src.raw THEN SetGrayTable[data,src.bps]; --sets up a lookup table for source grays UNTIL Area.Empty[area] DO trap: Trap _ Area.Remove[area]; IF bitmap AND trap.xbotL=trap.xtopL AND trap.xbotR=trap.xtopR THEN { box: GraphicsBasic.Box _ [trap.xbotL, trap.ybot, trap.xbotR, trap.ytop]; ShowBitmap[data,box,src,map] } ELSE ShowTrap[data,trap,src,map]; ENDLOOP; IF src.mode=invert THEN data.lastPixel _ invertHack; }; SetColor: PROC [data: Data, color: GraphicsBasic.Color] = { IF color = data.lastColor THEN RETURN; IF color.tag = stipple THEN data.stipple _ CGColor.GetStipple[color] ELSE IF terminal.GetColorMode.full THEN data.lastPixel _ Pack[color.r,color.g,color.b] ELSE data.lastPixel _ ColorMap.GetIndex[color.r,color.g,color.b]; data.lastColor _ color; }; SetGrayTable: PROC [data: Data, srcBps: CARDINAL] = { cmapGrays: ColorMap.GrayTable _ ColorMap.GetGrayTable[]; slen: REAL _ TwoToThe[srcBps]; scaler: REAL _ 255.0/(slen-1); IF data.grayTable=NIL OR data.grayTable.length#slen THEN data.grayTable _ NEW[ColorMap.GrayRec[TwoToThe[srcBps]]]; FOR i: CARDINAL IN [0..data.grayTable.length) DO data.grayTable[i] _ cmapGrays[Real.RoundC[i*scaler]]; ENDLOOP; }; <> TwoToThe: PROC[power: INTEGER] RETURNS[INTEGER] = { RETURN[Basics.BITSHIFT[value: 2, count: power-1]]; }; GetBBColor: PROC[color: CARDINAL, bps: CARDINAL] RETURNS [CARDINAL] = { grey,temp: CARDINAL _ 0; IF color#0 THEN { SELECT bps FROM 1 => temp _ Basics.BITAND[color,mask1]; 2 => temp _ Basics.BITAND[color,mask2]; 4 => temp _ Basics.BITAND[color,mask4]; 8 => temp _ Basics.BITAND[color,mask8]; ENDCASE => ERROR Error; FOR b: CARDINAL IN [0..16/bps) DO grey _ Basics.BITOR[temp,grey]; temp _ Basics.BITSHIFT[temp,bps]; ENDLOOP; }; RETURN[grey]; }; Line1: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..1B]]; Line2: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..3B]]; Line4: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..17B]]; Line8: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..377B]]; Line16: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF CARDINAL]; Pair: TYPE = MACHINE DEPENDENT RECORD[r,g: Byte]; ByteSeq: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Byte]; PairSeq: TYPE = RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Pair]; GetR: PROC[x,y: CARDINAL] RETURNS[Byte] = INLINE { RETURN[ LOOPHOLE[terminal.colorBitmapA + Basics.LongMult[terminal.colorWordsPerLineA,y], LONG POINTER TO PairSeq][x].r] }; GetG: PROC[x,y: CARDINAL] RETURNS[Byte] = INLINE { RETURN[ LOOPHOLE[terminal.colorBitmapA + Basics.LongMult[terminal.colorWordsPerLineA,y], LONG POINTER TO PairSeq][x].g] }; GetB: PROC[x,y: CARDINAL] RETURNS[Byte] = INLINE { RETURN[ LOOPHOLE[terminal.colorBitmapB + Basics.LongMult[terminal.colorWordsPerLineB,y], LONG POINTER TO ByteSeq][x]] }; SetR: PROC[x,y: CARDINAL, r: Byte] = INLINE { LOOPHOLE[terminal.colorBitmapA + Basics.LongMult[terminal.colorWordsPerLineA,y], LONG POINTER TO PairSeq][x].r _ r }; SetG: PROC[x,y: CARDINAL, g: Byte] = INLINE { LOOPHOLE[terminal.colorBitmapA + Basics.LongMult[terminal.colorWordsPerLineA,y], LONG POINTER TO PairSeq][x].g _ g }; SetB: PROC[x,y: CARDINAL, b: Byte] = INLINE { LOOPHOLE[terminal.colorBitmapB + Basics.LongMult[terminal.colorWordsPerLineB,y], LONG POINTER TO ByteSeq][x] _ b }; GetPixel: PUBLIC PROC[x,y: CARDINAL] RETURNS[r,g,b: Byte] = INLINE { RETURN[r: GetR[x,y], g: GetG[x,y], b: GetB[x,y]] }; <> <> SetPixel: PUBLIC PROC[x,y: CARDINAL, r,g,b: Byte] = INLINE { SetR[x,y,r]; SetG[x,y,g]; SetB[x,y,b] }; <> <> SetRed: PUBLIC PROC[x,y: CARDINAL, value: Byte] = INLINE { SetR[x,y,value] }; SetGreen: PUBLIC PROC[x,y: CARDINAL, value: Byte] = INLINE { SetG[x,y,value] }; SetBlue: PUBLIC PROC[x,y: CARDINAL, value: Byte] = INLINE { SetB[x,y,value] }; <> <> <> Put: PROC[dbase: LONG POINTER, drast: CARDINAL, x,y: CARDINAL, v: LONG CARDINAL] = { xline: LONG POINTER _ dbase + Basics.LongMult[y,drast]; IF terminal.GetColorMode.full THEN { pair: Pair _ LOOPHOLE[Basics.LowHalf[v]]; blue: Byte _ Basics.LowByte[Basics.HighHalf[v]]; SetPixel[x,y,pair.r,pair.g,blue]; } ELSE { short: CARDINAL _ Basics.LowHalf[v]; SELECT terminal.GetColorMode.bitsPerPixelChannelA FROM 1 => LOOPHOLE[xline,LONG POINTER TO Line1][x] _ Basics.BITAND[short,mask1]; 2 => LOOPHOLE[xline,LONG POINTER TO Line2][x] _ Basics.BITAND[short,mask2]; 4 => LOOPHOLE[xline,LONG POINTER TO Line4][x] _ Basics.BITAND[short,mask4]; 8 => LOOPHOLE[xline,LONG POINTER TO Line8][x] _ Basics.BITAND[short,mask8]; ENDCASE => ERROR Error; }; }; <<"transparent mode">> Transparent: PROC[dbase: LONG POINTER, drast: CARDINAL, x,y: CARDINAL, value: LONG CARDINAL] = { xline: LONG POINTER _ dbase + Basics.LongMult[y,drast]; IF terminal.GetColorMode.full THEN { pair: Pair _ LOOPHOLE[Basics.LowHalf[value]]; blue: Byte _ Basics.LowByte[Basics.HighHalf[value]]; r,g,b: Byte; [r,g,b] _ GetPixel[x,y]; pair.r _ MIN[pair.r+r,255]; pair.g _ MIN[pair.g+g,255]; blue _ MIN[blue+b,255]; SetPixel[x,y,pair.r,pair.g,blue]; } ELSE SELECT terminal.GetColorMode.bitsPerPixelChannelA FROM 1 => IF value=1 THEN LOOPHOLE[xline,LONG POINTER TO Line1][x] _ value; 2 => {v: CARDINAL _ LOOPHOLE[xline,LONG POINTER TO Line2][x]; v _ MIN[v+value,3]; LOOPHOLE[xline,LONG POINTER TO Line2][x] _ v}; 4 => {v: CARDINAL _ LOOPHOLE[xline,LONG POINTER TO Line4][x]; v _ MIN[v+value,15]; LOOPHOLE[xline,LONG POINTER TO Line4][x] _ v}; 8 => {v: CARDINAL _ LOOPHOLE[xline,LONG POINTER TO Line8][x]; v _ MIN[v+value,255]; LOOPHOLE[xline,LONG POINTER TO Line8][x] _ v}; ENDCASE => ERROR Error; }; <<"invert mode">> Invert: PROC[dbase: LONG POINTER, drast: CARDINAL, x,y: CARDINAL] = { xline: LONG POINTER _ dbase + Basics.LongMult[y,drast]; IF terminal.GetColorMode.full THEN { r,g,b: Byte; temp: Byte _ 377B; [r,g,b] _ GetPixel[x,y]; r _ Basics.BITXOR[temp,r]; g _ Basics.BITXOR[temp,g]; b _ Basics.BITXOR[temp,b]; SetPixel[x,y,r,g,b]; } ELSE { temp: CARDINAL _ 177777B; SELECT terminal.GetColorMode.bitsPerPixelChannelA FROM 1 => {v: CARDINAL _ LOOPHOLE[xline,LONG POINTER TO Line1][x]; v _ Basics.BITXOR[v,temp]; v _ Basics.BITAND[v,mask1]; LOOPHOLE[xline,LONG POINTER TO Line1][x] _ v}; 2 => {v: CARDINAL _ LOOPHOLE[xline,LONG POINTER TO Line2][x]; v _ Basics.BITXOR[v,temp]; v _ Basics.BITAND[v,mask2]; LOOPHOLE[xline,LONG POINTER TO Line2][x] _ v}; 4 => {v: CARDINAL _ LOOPHOLE[xline,LONG POINTER TO Line4][x]; v _ Basics.BITXOR[v,temp]; v _ Basics.BITAND[v,mask4]; LOOPHOLE[xline,LONG POINTER TO Line4][x] _ v}; 8 => {v: CARDINAL _ LOOPHOLE[xline,LONG POINTER TO Line8][x]; v _ Basics.BITXOR[v,temp]; v _ Basics.BITAND[v,mask8]; LOOPHOLE[xline,LONG POINTER TO Line8][x] _ v}; ENDCASE => ERROR Error; }; }; <> AGet: PROC[src: Source.Ref, x,y: CARDINAL] RETURNS[value: LONG CARDINAL] = { xline: LONG POINTER _ src.xbase + Basics.LongMult[y,src.xrast]; SELECT src.bps FROM 0 => value _ LOOPHOLE[xline,LONG POINTER TO Line1][x]; 1 => value _ LOOPHOLE[xline,LONG POINTER TO Line1][x]; 2 => value _ LOOPHOLE[xline,LONG POINTER TO Line2][x]; 4 => value _ LOOPHOLE[xline,LONG POINTER TO Line4][x]; 8 => value _ LOOPHOLE[xline,LONG POINTER TO Line8][x]; ENDCASE => ERROR Error; }; mask1: CARDINAL = 1B; mask2: CARDINAL = 3B; mask4: CARDINAL = 17B; mask8: CARDINAL = 377B; <> FullTint: PROC[in: LONG CARDINAL, bps: INTEGER, color: GraphicsBasic.Color] RETURNS[out: LONG CARDINAL] = {OPEN GraphicsColor; intensity: REAL _ REAL[in]/(TwoToThe[bps]); v: Byte _ Real.RoundC[intensity*255]; SELECT color FROM red => out _ Pack[v,0,0]; green => out _ Pack[0,v,0]; blue => out _ Pack[0,0,v]; magenta => out _ Pack[v,0,v]; cyan => out _ Pack[0,v,v]; yellow => out _ Pack[v,v,0]; white => out _ Pack[v,v,v]; ENDCASE => { ir: Byte _ Real.RoundC[intensity*color.r]; ig: Byte _ Real.RoundC[intensity*color.g]; ib: Byte _ Real.RoundC[intensity*color.b]; out _ Pack[ir,ig,ib]; }; RETURN[out]; }; white: LONG CARDINAL _ Pack[377B,377B,377B]; black: LONG CARDINAL _ 0; Pack: PROC[r,g,b: Byte] RETURNS [LONG CARDINAL] = { rg: Pair; out: Basics.LongNumber _ [num[0,0]]; rg.r _ r; rg.g _ g; out.lowbits _ LOOPHOLE[rg,CARDINAL]; out.highbits _ LOOPHOLE[b,CARDINAL]; RETURN[out.lc]; }; Masks: TYPE = ARRAY [0..16) OF WORD; masksArray: Masks _ [ 100000B, 040000B, 020000B, 010000B, 004000B, 002000B, 001000B, 000400B, 000200B, 000100B, 000040B, 000020B, 000010B, 000004B, 000002B, 000001B]; masks: POINTER TO Masks _ @masksArray; cursorWidth: INTEGER ~ 16; cursorHeight: INTEGER ~ 16; ShowBitmap: PROC[data: Data, rect: Box, src: CGSource.Ref, map: CGMatrix.Ref] = { type: CGSource.Type _ src.type; mode: CGSource.Mode _ src.mode; xmin, xmax, ymin, ymax: NAT; xmin _ Rnd[rect.xmin]; xmax _ Rnd[rect.xmax]; ymin _ Rnd[rect.ymin]; ymax _ Rnd[rect.ymax]; IF NOT(xmin> <> <> sxmin: INTEGER _ xmin - tx; symin: INTEGER _ ymin - ty; sBase: LONG POINTER _ src.xbase; sRast: CARDINAL _ src.xrast; sLine: LONG POINTER _ sBase + Basics.LongMult[symin, sRast]; y: CARDINAL _ ymin; TerminalExtras.LockColorFrame[vt: terminal, xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax]; IF terminal.GetColorMode.full THEN { baseA: LONG POINTER _ terminal.colorBitmapA; wplA: CARDINAL _ terminal.colorWordsPerLineA; baseB: LONG POINTER _ terminal.colorBitmapB; wplB: CARDINAL _ terminal.colorWordsPerLineB; lineA: LONG POINTER TO Line16 _ baseA+Basics.LongMult[y, wplA]; lineB: LONG POINTER TO Line8 _ baseB+Basics.LongMult[y, wplB]; pixel1A: CARDINAL _ Basics.LowHalf[data.lastPixel]; pixel0A: CARDINAL _ Basics.LowHalf[white]; pixel1B: [0..256) _ Basics.HighHalf[data.lastPixel] MOD 256; pixel0B: [0..256) _ Basics.HighHalf[white] MOD 256; DO sAddr: LONG POINTER TO CARDINAL _ sLine+sxmin/16; sWord: CARDINAL _ sAddr^; si: CARDINAL _ sxmin MOD 16; SELECT mode FROM opaque => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN { lineA[x] _ pixel1A; lineB[x] _ pixel1B } ELSE { lineA[x] _ pixel0A; lineB[x] _ pixel0B }; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; transparent => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN { lineA[x] _ pixel1A; lineB[x] _ pixel1B }; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; invert => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN { lineA[x] _ Basics.BITXOR[lineA[x],177777B]; lineB[x] _ Basics.BITXOR[lineB[x],377B] }; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; ENDCASE; IF (y _ y+1)=ymax THEN EXIT; sLine _ sLine + sRast; -- next source line lineA _ lineA + wplA; lineB _ lineB + wplB; -- next destination lines ENDLOOP; } ELSE IF terminal.GetColorMode.bitsPerPixelChannelA=8 THEN { baseA: LONG POINTER _ terminal.colorBitmapA; wplA: CARDINAL _ terminal.colorWordsPerLineA; lineA: LONG POINTER TO Line8 _ baseA+Basics.LongMult[y, wplA]; pixel1: [0..256) _ Basics.LowHalf[data.lastPixel] MOD 256; pixel0: [0..256) _ Basics.LowHalf[white] MOD 256; DO sAddr: LONG POINTER TO CARDINAL _ sLine+sxmin/16; sWord: CARDINAL _ sAddr^; si: CARDINAL _ sxmin MOD 16; SELECT mode FROM opaque => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN lineA[x] _ pixel1 ELSE lineA[x] _ pixel0; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; transparent => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN lineA[x] _ pixel1; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; invert => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN lineA[x] _ Basics.BITXOR[lineA[x],377B]; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; ENDCASE; IF (y _ y+1)=ymax THEN EXIT; sLine _ sLine + sRast; -- move to next source line lineA _ lineA + wplA; -- move to next destination line ENDLOOP; } ELSE IF terminal.GetColorMode.bitsPerPixelChannelA=4 THEN { baseA: LONG POINTER _ terminal.colorBitmapA; wplA: CARDINAL _ terminal.colorWordsPerLineA; lineA: LONG POINTER TO Line4 _ baseA+Basics.LongMult[y, wplA]; pixel1: [0..16) _ Basics.LowHalf[data.lastPixel] MOD 16; pixel0: [0..16) _ Basics.LowHalf[white] MOD 16; DO sAddr: LONG POINTER TO CARDINAL _ sLine+sxmin/16; sWord: CARDINAL _ sAddr^; si: CARDINAL _ sxmin MOD 16; SELECT mode FROM opaque => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN lineA[x] _ pixel1 ELSE lineA[x] _ pixel0; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; transparent => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN lineA[x] _ pixel1; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; invert => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN lineA[x] _ Basics.BITXOR[lineA[x],17B]; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; ENDCASE; IF (y _ y+1)=ymax THEN EXIT; sLine _ sLine + sRast; -- move to next source line lineA _ lineA + wplA; -- move to next destination line ENDLOOP; } ELSE{ dbase: LONG POINTER _ terminal.colorBitmapA; drast: CARDINAL _ terminal.colorWordsPerLineA; pixel: LONG CARDINAL _ data.lastPixel; DO sAddr: LONG POINTER TO CARDINAL _ sLine+sxmin/16; sWord: CARDINAL _ sAddr^; si: CARDINAL _ sxmin MOD 16; SELECT mode FROM opaque => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN Put[dbase, drast, x, y, pixel] ELSE Put[dbase, drast, x, y, white]; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; transparent => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN Put[dbase, drast, x, y, pixel]; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; invert => FOR x: CARDINAL IN[xmin..xmax) DO IF Basics.BITAND[sWord, masks[si]]#0 THEN Invert[dbase, drast, x, y]; IF (si _ si+1)=16 THEN { sWord _ (sAddr _ sAddr+1)^; si _ 0 }; ENDLOOP; ENDCASE; IF (y _ y+1)=ymax THEN EXIT; sLine _ sLine + sRast; -- move to next source line <> ENDLOOP; }; TerminalExtras.UnlockColorFrame[terminal]; } ELSE ERROR; }; ShowTrap: PROC[data: Data, trap: Trap, src: Source.Ref, map: Matrix.Ref] = { easy: BOOLEAN _ IF src.mode=invert OR (src.type=const AND src.mode=opaque) THEN TRUE ELSE FALSE; yb,yt,yl,xl,xr: CARDINAL _ 0; rdxl,rdxr: REAL _ 0; -- left and right x increments rsdx,rsdy: REAL _ 0; -- increments for source position fsdx,fsdy: Frac; dbase: LONG POINTER; drast: CARDINAL; fat: BOOLEAN _ src.fat; stipple: BOOLEAN _ (data.lastColor.tag=stipple); DoLine: PROC[xmin,xmax,y: CARDINAL] = { TerminalExtras.LockColorFrame[vt: terminal, xmin: xmin, ymin: y, xmax: xmax, ymax: y+1]; IF stipple OR src.type=tile THEN StippleLine[xmin,xmax,y] --the altoworld special case ELSE {IF easy THEN EasyLine[xmin,xmax,y] --split here for easy and hard lines ELSE HardLine[xmin,xmax,y]}; TerminalExtras.UnlockColorFrame[terminal]; }; EasyLine: PROC[xmin,xmax,y: CARDINAL] = { --solid colors only gray,bpp,ppw: CARDINAL _ 0; bb^ _ [dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: @gray, bit: 0], srcDesc: [gray[gray: [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]]], width: 0, height: 1, flags: [disjoint: TRUE, gray: TRUE, srcFunc: null, dstFunc: IF src.mode=invert THEN xor ELSE null]]; IF terminal.GetColorMode.full THEN { bpp _ 16; ppw _ 1; gray _ Basics.LowHalf[data.lastPixel]; --red and green together } ELSE { bpp _ terminal.GetColorMode.bitsPerPixelChannelA; ppw _ 16/bpp; gray _ GetBBColor[data.lastPixel,bpp]; --colormap index }; bb.dst.word _ terminal.colorBitmapA + Basics.LongMult[y,terminal.colorWordsPerLineA] + xmin/ppw; bb.dst.bit _ (xmin MOD ppw)*bpp; bb.dstBpl _ terminal.colorWordsPerLineA*16; bb.width _ (xmax - xmin)*bpp; PrincOpsUtils.BITBLT[bb]; IF terminal.GetColorMode.full THEN { blue: CARDINAL _ Basics.HighHalf[data.lastPixel]; bpp _ 8; ppw _ 2; gray _ GetBBColor[Basics.LowByte[blue],bpp]; --get the blue color bb.dst.word _ terminal.colorBitmapB + Basics.LongMult[y,terminal.colorWordsPerLineB] + xmin/ppw; bb.dst.bit _ (xmin MOD ppw)*bpp; bb.dstBpl _ terminal.colorWordsPerLineB*16; bb.width _ (xmax - xmin)*bpp; PrincOpsUtils.BITBLT[bb]; }; }; StippleLine: PROC[xmin,xmax,y: CARDINAL] = { base: CARDINAL _ IF src.type=tile THEN 16 ELSE 4; sx: CARDINAL; yoff: CARDINAL _ base*(y MOD base); bit: CARDINAL; bits: LONG POINTER TO Line1 _ IF src.type=tile THEN LOOPHOLE[src.xbase] ELSE LOOPHOLE[@data.stipple]; FOR x: CARDINAL IN[xmin..xmax) DO sx _ x MOD base + yoff; bit _ bits[sx]; IF bit=0 THEN { IF src.mode=opaque THEN Put[dbase,drast,x,y,white] ELSE LOOP; } ELSE{ --bit=1 IF src.mode=invert THEN Invert[dbase,drast,x,y] ELSE Put[dbase,drast,x,y,black]; }; ENDLOOP; }; HardLine: PROC[xmin,xmax,y: CARDINAL] = { rsx,rsy: REAL; -- current source position fsx,fsy: Frac; sx,sy: CARDINAL; -- truncated source position value: LONG CARDINAL; IF src.type=array AND src.bps=0 THEN FOR x: CARDINAL IN[xmin..xmax) DO xline: LONG POINTER; bit: CARDINAL; IF x=xmin THEN { [[rsx,rsy]] _ Matrix.Inv[map,[x+0.5,y+0.5]]; fsx _ FixF[rsx]; fsy _ FixF[rsy]; } ELSE {fsx _ AddF[fsx,fsdx]; fsy _ AddF[fsy,fsdy]}; xline _ src.xbase + Basics.LongMult[IntF[fsy],src.xrast]; bit _ LOOPHOLE[xline,LONG POINTER TO Line1][IntF[fsx]]; IF bit=0 THEN { IF src.mode=opaque THEN Put[dbase,drast,x,y,white] ELSE LOOP; } ELSE{ --bit=1 IF src.mode=invert THEN Invert[dbase,drast,x,y] ELSE Put[dbase,drast,x,y,data.lastPixel]; }; ENDLOOP ELSE FOR x: CARDINAL IN[xmin..xmax) DO IF x=xmin THEN { [[rsx,rsy]] _ Matrix.Inv[map,[x+0.5,y+0.5]]; fsx _ FixF[rsx]; fsy _ FixF[rsy]; } ELSE {fsx _ AddF[fsx,fsdx]; fsy _ AddF[fsy,fsdy]}; <> SELECT src.type FROM proc => value _ src.Get[FltF[fsx],FltF[fsy]]; array => { sv: LONG CARDINAL; sx _ IntF[fsx]; sy _ IntF[fsy]; sv _ AGet[src,sx,sy]; IF terminal.GetColorMode.full THEN value _ FullTint[sv,src.bps,src.color] ELSE value _ (IF src.raw THEN sv ELSE data.grayTable[sv]); }; const => value _ data.lastPixel; ENDCASE; IF src.mode=transparent THEN Transparent[dbase,drast,x,y,value] ELSE Put[dbase,drast,x,y,value]; ENDLOOP; }; <
> <> dbase _ terminal.colorBitmapA; drast _ terminal.colorWordsPerLineA; IF fat THEN { yb_Bot[trap.ybot]; yt_Top[trap.ytop] } ELSE { yb_Rnd[trap.ybot]; yt_Rnd[trap.ytop] }; IF ybyt OR fat THEN ERROR Error; RETURN }; <> IF src.type=array THEN { [[rsdx,rsdy]] _ Matrix.InvRel[map,[1,0]]; fsdx _ FixF[rsdx]; fsdy _ FixF[rsdy]; }; rdxl_(trap.xtopL-trap.xbotL); -- delta x, left rdxr_(trap.xtopR-trap.xbotR); -- delta x, right IF NOT(fat AND yb=yl) THEN { rdy: REAL_trap.ytop-trap.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_trap.xbotL; rxrb_trap.xbotR } -- first line ELSE { rxlb_rxlt; rxrb_rxrt }; -- successive lines IF y=yl THEN { rxlt_trap.xtopL; rxrt_trap.xtopR } -- last line ELSE IF y=yb THEN { -- first line, if yl>yb d: REAL_(yb+1)-trap.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 xl0 AND height>0 AND fromXdx AND (dx+w)>sx AND (sy+h)>dy AND (dy+h)>sy THEN { bb.flags.disjoint _ FALSE; -- the rectangles overlap IF dy=sy THEN bb.flags.disjointItems _ FALSE; -- so do the items IF dy>sy OR (dy=sy AND dx>sx) THEN { -- reverse direction bb.flags.direction _ backward; backwardsFlag _ -1; sy _ sy + (h-1); dy _ dy + (h-1); }; }; bb.dst.word _ terminal.colorBitmapA + Basics.LongMult[dy, terminal.colorWordsPerLineA] + dx/ppw; bb.dst.bit _ (dx MOD ppw)*bpp; bb.src.word _ terminal.colorBitmapA + Basics.LongMult[sy, terminal.colorWordsPerLineA] + sx/ppw; bb.src.bit _ (sx MOD ppw)*bpp; bb.dstBpl _ bb.srcDesc.srcBpl _ terminal.colorWordsPerLineA*16*backwardsFlag; bb.width _ w*bpp; bb.height _ h; PrincOpsUtils.BITBLT[bb]; IF terminal.GetColorMode.full THEN { bpp _ 8; ppw _ 2; bb.dst.word _ terminal.colorBitmapB + Basics.LongMult[dy,terminal.colorWordsPerLineB] + dx/ppw; bb.dst.bit _ (dx MOD ppw)*bpp; bb.src.word _ terminal.colorBitmapB + Basics.LongMult[sy, terminal.colorWordsPerLineB] + sx/ppw; bb.src.bit _ (sx MOD ppw)*bpp; bb.dstBpl _ bb.srcDesc.srcBpl _ terminal.colorWordsPerLineB*16*backwardsFlag; bb.width _ w*bpp; PrincOpsUtils.BITBLT[bb]; }; TerminalExtras.UnlockColorFrame[terminal]; }; }; }.