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: 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: 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 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]; }; }; }. ÎColorDeviceImpl.mesa Last changed by Ken Pier July 11, 1983 12:05 pm Last changed by Maureen Stone September 13, 1984 11:05:35 am PDT Last changed by Doug Wyatt, December 20, 1983 7:17 pm base and words per line all available thru ColorDisplay bitmap speedup hack, not valid for color display v is assumed to be 8 bps or less Return the color of the pixel at coordinates (x,y). The pixel with coordinates (0,0) is at the upper left corner of the screen. Set the pixel at coordinates (x,y) to the specified color. The pixel with coordinates (0,0) is at the upper left corner of the screen. Set red, green, or blue value for a pixel independently. these routines put stuff in the bitmap assume that s is already masked "transparent mode" "invert mode" this gets a source sample from an array of values this converts from a bps bit array value to a 24 bps color map transforms source coordinates to device coordinates Here, we know map is a simple translation, so subtracting map's translation elements will take us from device to source table.dLine _ table.dLine+drast; Get a sample from the source main code for PTrap starts here compute yb (bottom of first scanline) and yt (top of last scanline) Setup for calls on DoLine Ê"˜Jšœ™Jšœ/™/Jšœ@™@Jšœ5™5J˜šÏk ˜ Jš œœœœœœ:˜gJšœœ˜"Jšœœ˜Jšœ œ ˜Jšœ œ%˜3Jšœ œ˜!Jšœ œ ˜Jšœ œÏc˜)Jšœ œ.˜šœœœ œ ˜>Jšœž)˜K—šœ˜J˜šœœœœ˜DJ˜HJ˜—Jšœ˜!Jšœ˜—Jšœœ˜4J˜J˜—šŸœœ-˜;Jšœœœ˜&Jšœœ)˜Dš˜Jšœœ/˜QJšœ=˜A—J˜J˜J˜—šŸ œœœ˜5J˜8Jšœœ˜Jšœœ˜šœœœ˜3Jšœœ%˜>—šœœœœ˜1J˜5Jšœ˜—J˜J˜—Jšœ ™ š Ÿœœœœœ˜3Jšœœ˜2J˜J˜—š Ÿ œœœœœœ˜GJšœ œ˜šœ œ˜šœ˜Jšœœ˜'Jšœœ˜'Jšœœ˜'Jšœœ˜'Jšœœ˜—šœœœ ˜!Jšœœ ˜šœœ ˜!Jšœ˜——J˜—Jšœ˜ J˜J˜—Jšœœœœœœœœ ˜CJšœœœœœœœœ ˜CJšœœœœœœœœ ˜DJšœœœœœœœœ ˜EJšœœœœœœœœ˜>J˜Jš œœœ œœ ˜1Jšœ œœœœœœœ˜BJšœ œœœœœœœ˜BJ˜š Ÿœœœœ œœ˜:JšœH˜PJšœœœ˜!—š Ÿœœœœ œœ˜:JšœH˜PJšœœœ˜!—š Ÿœœœœ œœ˜:JšœH˜PJšœœœ˜J˜—šŸœœœ œ˜-JšœH˜PJšœœœ˜$—šŸœœœ œ˜-JšœH˜PJšœœœ˜$—šŸœœœ œ˜-JšœH˜PJšœœœ˜"J˜—š Ÿœœœœœœ˜DJšœ-˜3—Jšœ3™3JšœK™KJ˜š Ÿœœœœœ˜Jšœœœ˜&Jšœœ˜šœœ˜Jšœ7™7Jšœ?™?Jšœ7™7—Jšœœ ˜Jšœœ ˜Jšœœœ ˜ Jšœœ ˜Jšœœœ)˜Jšœ œ"˜3Jšœ œ˜*Jšœ4œ˜Jšœ˜—šœœœœ ˜0šœœ˜$Jšœ,˜0—Jšœœ(˜>Jšœ˜—šœ œœœ ˜+šœœœ˜+Jšœœ˜+Jšœœ˜*—Jšœœ(˜>Jšœ˜—Jšœ˜J˜Jšœœœ˜Jšœž˜*Jšœ,ž˜EJšœ˜—J˜—šœœ.œ˜;Jšœœœ˜,Jšœœ˜-Jšœœœœ(˜>Jšœ2œ˜:Jšœ)œ˜1š˜Jš œœœœœ˜1Jšœœ ˜Jšœœ œ˜J˜Jšœ˜šœ œœœ ˜+Jšœœœœ˜SJšœœ(˜>Jšœ˜—šœœœœ ˜0Jšœœœ˜Jšœ˜—šœ œœœ ˜+Jšœœœœ˜RJšœœ(˜>Jšœ˜—Jšœ˜J˜Jšœœœ˜Jšœž˜2Jšœž ˜6Jšœ˜—J˜—šœœ.œ˜;Jšœœœ˜,Jšœœ˜-Jšœœœœ(˜>Jšœ1œ˜8Jšœ(œ˜/š˜Jš œœœœœ˜1Jšœœ ˜Jšœœ œ˜J˜Jšœ˜šœ œœœ ˜+Jšœœœœ˜SJšœœ(˜>Jšœ˜—šœœœœ ˜0Jšœœœ˜Jšœ˜—šœ œœœ ˜+Jšœœœœ˜QJšœœ(˜>Jšœ˜—Jšœ˜J˜Jšœœœ˜Jšœž˜2Jšœž ˜6Jšœ˜—J˜—šœ˜Jšœœœ˜,Jšœœ˜.Jšœœœ˜&š˜Jš œœœœœ˜1Jšœœ ˜Jšœœ œ˜J˜Jšœ˜šœ œœœ ˜+Jšœœœ˜HJšœ ˜$Jšœœ(˜>Jšœ˜—šœœœœ ˜0Jšœœœ ˜IJšœœ(˜>Jšœ˜—šœ œœœ ˜+Jšœœœ˜EJšœœ(˜>Jšœ˜—Jšœ˜J˜Jšœœœ˜Jšœž˜2Jšœ ™ Jšœ˜—J˜—Jšœ*˜*J˜—Jšœœ˜ J˜J˜—šŸœœ>˜LJšœœœœœœœœœ˜`Jšœœ˜Jšœ œž˜3Jšœ œž!˜6J˜Jšœœœ˜Jšœœ˜Jšœœ ˜Jšœ œ ˜0šŸœœœ˜(˜+Jšœ,˜,—Jšœ œœž˜Wšœœ˜ Jšœž$˜AJšœ˜—Jšœ*˜*J˜J˜—šŸœœœž˜?Jšœœ˜šœœ1˜GJ˜IJšœ'œœ˜GJšœ œœœ˜1—šœœ˜%J˜ J˜Jšœ'ž˜?J˜—šœ˜Jšœ1˜1J˜ Jšœ(ž˜8J˜—Jšœ`˜`Jšœœ ˜ Jšœ+˜+J˜Jšœœ˜šœœ˜$Jšœœ#˜1J˜J˜Jšœ-ž˜AJšœ`˜`Jšœœ ˜ Jšœ+˜+J˜Jšœœ˜J˜—J˜J˜—šŸ œœœ˜,Jš œœœœœ˜1Jšœœ˜ Jšœœ œ˜#Jšœœ˜šœœœœ˜Jš œœœ œœ˜G—šœœœ ˜!Jšœœ ˜J˜šœœ˜Jšœœ˜2Jšœœ˜ J˜—šœž˜Jšœœ˜/Jšœ˜ J˜—Jšœ˜—J˜—J˜šŸœœœ˜)Jšœ œž˜)J˜Jšœœž˜-Jšœœœ˜J˜š œœ œœœœ ˜GJšœœœ˜Jšœœ˜šœœ˜J˜,J˜!J˜—Jšœ.˜2Jšœ9˜9Jš œœœœœ˜7šœœ˜Jšœœ˜2Jšœœ˜ J˜—šœž˜Jšœœ˜/Jšœ%˜)J˜—Jš˜J˜J˜—š œœœœ ˜&šœœ˜J˜,J˜!J˜—Jšœ.˜2Jšœ™šœ ˜J˜.˜ Jšœœœ˜J˜J˜J˜Jšœœ'˜IJšœ œ œœ˜:J˜˜ Jšœ˜———Jšœœ#˜?Jšœ˜ Jšœ˜—J˜J˜—Jšœ™JšœC™CJšœ˜Jšœ$˜$Jšœœ)˜4Jšœ*˜.Jšœœ ž˜(Jš œœœœœœ˜2Jšœ™šœœ˜J˜)J˜%J˜—Jšœž˜.Jšœž˜/šœœœœ˜Jšœœž ˜)Jšœž˜2J˜—šœœ˜ Jšœœž&˜EJšœœ ž*˜BJšœœ ž+˜Cš œœœ œž˜3Jšœœ&ž ˜?Jšœž˜2Jšœœ&ž ˜>šœœœž˜+Jšœœž˜4J˜$—Jšœ%ž˜8Jšœœœœ˜$Jšœœœœ˜$Jšœœ"˜/Jšœ˜—J˜—šœ˜Jšœ œž-˜@š œœœ œž˜3šœœž ˜Jšœœž˜9J˜.—Jšœ!ž˜8J˜Jšœœ˜Jšœ˜—J˜—J˜J˜—JšŸœœœœœœœ˜GJšŸœœœœœœœ˜IJšŸœœœœœœœ˜GJšŸœœœœœœœ˜Jš Ÿœœœœœœ˜/Jš œœœœœ˜8J˜—Jšœœ˜J˜,J˜š Ÿœœœœ œ˜,Jšœ˜$J˜—š Ÿœœ œœœ˜,Jšœœ œ˜$J˜—šŸœœ œ œ˜.Jšœ˜J˜—š Ÿœœ œœœ˜/Jšœœ œ˜'J˜—š Ÿ œœœ3œœ˜WJšœ œ ˜Jšœœ˜Jšœœ˜Jšœ#œœž˜Qšœ œ ˜š œ œ œ œ œœ˜BJšœœž'˜CJšœœ ˜Jšœœ ˜Jšœœ˜Jšœœ˜Jšœœœ˜+Jšœœœ˜,J˜J˜EJš œœœœœ,˜fJšœœ ˜šœœ"œ ˜EJ˜+šœ&œœ˜@Jšœœ!˜,——˜+Jš œœœœœ ˜P—š œ œ œ œ œ˜=Jšœœž˜4Jšœœœž˜@š œœœœž˜9J˜J˜5J˜—J˜—Jšœ`˜`Jšœœ ˜Jšœ`˜`Jšœœ ˜JšœM˜MJ˜ Jšœœ˜šœœ˜$J˜Jšœ_˜_Jšœœ ˜Jšœ`˜`Jšœœ ˜JšœM˜MJ˜Jšœœ˜J˜—Jšœ*˜*J˜——J˜J˜J˜—J˜J˜J˜—…—fzM