-- Wedges.mesa -- m.stone October 2, 1980 12:36 PM -- Last edit by Doug Wyatt, 17-Aug-81 12:06:55 DIRECTORY BitBlt USING [AlignedBBTable, BBptr, BBTableSpace, BITBLT], ColorDisplay, JaMFnsDefs USING [GetReal, PopInteger, Register], Real, RealFns; Wedges: PROGRAM IMPORTS BitBlt, ColorDisplay, JaMFnsDefs, RealFns, Real = { bbspace: BitBlt.BBTableSpace; bb: BitBlt.BBptr ← BitBlt.AlignedBBTable[@bbspace]; bitmap: LONG POINTER ← NIL; wpl: CARDINAL ← 0; xSize,ySize: [0..LAST[INTEGER]]; ClipAndRotate: PROC[lx,ty,rx,by: INTEGER] RETURNS[x,y,w,h: CARDINAL] = { lx ← MAX[lx,0]; ty ← MAX[ty,0]; rx ← MIN[rx,xSize]; by ← MIN[by,ySize]; IF rx>lx AND by>ty THEN RETURN[ySize-by,lx,by-ty,rx-lx] ELSE RETURN[0,0,0,0]; }; Oops: SIGNAL = CODE; Rect: PROC[pix,lx,ty,rx,by: INTEGER] = { --Rectangle[pix,ty,MAX[0,xSize-rx],by,MAX[0,xSize-lx]]; Rectangle[pix,lx,ty,rx,by]; }; Rectangle: PROC[pix,lx,ty,rx,by: CARDINAL] = { xlim: CARDINAL = ColorDisplay.width; ylim: CARDINAL = ColorDisplay.height; source: CARDINAL ← 256*pix + pix; dbit: [0..16); x,y,w,h: CARDINAL; [x,y,w,h] ← ClipAndRotate[lx,ty,rx,by]; IF w=0 OR h=0 THEN RETURN; dbit ← 8*(x MOD 2); bb↑ ← [ dst: [word: bitmap + LONG[y]*wpl + x/2, bit: dbit], dstBpl: 16*wpl, src: [word: @source, bit: dbit], srcDesc: [gray[[yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]]], width: 8*w, height: h, flags: [disjoint: TRUE, gray: TRUE] ]; IF NOT(x IN[0..xlim) AND y IN[0..ylim) AND (x+w)<=xlim AND (y+h)<=ylim) THEN { SIGNAL Oops; RETURN }; BitBlt.BITBLT[bb]; }; HalfTone: PROC[pixa,pixb,lx,ty,rx,by: CARDINAL] = { source: ARRAY[0..2) OF CARDINAL ← [256*pixa + pixb, 256*pixb + pixa]; dbit: [0..16); yoff: [0..2); x,y,w,h: CARDINAL; [x,y,w,h] ← ClipAndRotate[lx,ty,rx,by]; IF w=0 OR h=0 THEN RETURN; dbit ← 8*(x MOD 2); yoff ← y MOD 2; bb↑ ← [ dst: [word: bitmap + LONG[y]*wpl + x/2, bit: dbit], dstBpl: 16*wpl, src: [word: @source + yoff, bit: dbit], srcDesc: [gray[[yOffset: yoff, widthMinusOne: 0, heightMinusOne: 1]]], width: 8*w, height: h, flags: [disjoint: TRUE, gray: TRUE] ]; BitBlt.BITBLT[bb]; }; black: CARDINAL = 253; middl: CARDINAL = 254; white: CARDINAL = 255; mortar: CARDINAL = 252; SetColor: PROC[n: CARDINAL, r,g,b: [0..256)] = INLINE { ColorDisplay.SetColor[n,0,r,g,b] }; SetUpColorMap: PROC = { base: REAL ← RealFns.SqRt[2]; value: REAL ← base; x,v: INTEGER; -- set background color SetColor[0, background, background, background]; --make the colormap [1-16] logarithmic grey FOR x IN [1..16] DO v ← Real.RoundI[value]; IF v = 256 THEN v ← 255; SetColor[x, v, v, v]; --IODefs.WriteDecimal[v]; --IODefs.WriteChar[' ]; value ← value*base; ENDLOOP; --IODefs.WriteLine[" "]; --make the colormap [17..32] compensated logarithmic grey value ← base; FOR x IN [17..32] DO v ← Real.RoundI[Comp[value]]; SetColor[x, v, v, v]; --IODefs.WriteDecimal[v]; --IODefs.WriteChar[' ]; value ← value*base; ENDLOOP; --IODefs.WriteLine[" "]; --make the colormap [33-48] linear grey v ← 15; FOR x IN [33..48] DO SetColor[x, v, v, v]; --IODefs.WriteDecimal[v]; --IODefs.WriteChar[' ]; v ← v + 16; ENDLOOP; --IODefs.WriteLine[" "]; --make the colormap [49..64] compensated linear grey v ← 15; FOR x IN [49..64] DO n: CARDINAL ← Real.RoundI[Comp[v]]; SetColor[x, n, n, n]; --IODefs.WriteDecimal[n]; --IODefs.WriteChar[' ]; v ← v + 16; ENDLOOP; v ← Real.RoundI[Comp[level]]; SetColor[black, 0,0,0]; SetColor[middl, v,v,v]; SetColor[white, 255, 255, 255]; SetColor[mortar, 127,127,127]; }; ShowWedges: PROCEDURE = { nsteps: CARDINAL = 16; hsteps: CARDINAL = 23; bwidth: INTEGER ← xSize/nsteps; h: INTEGER ← ySize/hsteps; -- height unit bheight: INTEGER ← 4*h; -- band height width: INTEGER ← nsteps*bwidth; height: INTEGER ← hsteps*h; leftX: INTEGER ← (xSize - width)/2; topY: INTEGER ← (ySize - height)/2; lx, ty: INTEGER; base: REAL ← RealFns.SqRt[2]; --2↑1/2 SetUpColorMap[]; ClearScreen[]; --IODefs.WriteLine[" "]; --draw the log grey scale lx ← leftX; ty ← topY + h; FOR x: CARDINAL IN [1..16] DO Rectangle[x, lx, ty, lx + bwidth, ty + bheight]; lx ← lx + bwidth; ENDLOOP; lx ← leftX; ty ← ty + bheight + h/2; --draw the compensated log grey scale FOR x: CARDINAL IN [17..32] DO Rectangle[x, lx, ty, lx + bwidth, ty + bheight]; lx ← lx + bwidth; ENDLOOP; --draw the linear grey scale lx ← leftX; ty ← ty + bheight + h; FOR x: CARDINAL IN [33..48] DO Rectangle[x, lx, ty, lx + bwidth, ty + bheight]; lx ← lx + bwidth; ENDLOOP; lx ← leftX; ty ← ty + bheight + h/2; FOR x: CARDINAL IN [49..64] DO Rectangle[x, lx, ty, lx + bwidth, ty + bheight]; lx ← lx + bwidth; ENDLOOP; ty ← ty + bheight + h; HalfTone[black, white, leftX, ty, leftX + width, ty + 2*h]; }; background: CARDINAL ← 0; ClearScreen: PROCEDURE = { Rectangle[0, 0, 0, xSize, ySize]; }; level: INTEGER ← 128; screen: CARDINAL ← 125B; ShowBlocks: PROCEDURE = { lx, ty: CARDINAL; ClearScreen[]; lx ← 100; ty ← 120; Rectangle[middl, lx, ty, lx + 200, ty + 300]; lx ← lx + 200; HalfTone[black, white, lx, ty, lx + 200, ty + 300]; -- screen value currently ignored }; b: CARDINAL ← 100; w: CARDINAL ← 100; d: CARDINAL ← 50; h: CARDINAL ← 80; m: CARDINAL ← 2; ShowIllusion: PROC = { x,y: CARDINAL ← 0; flag: BOOLEAN ← FALSE; WHILE y<ySize DO x ← 0; IF flag THEN { Rect[white,x,y,x+d,y+h]; x ← x+d }; WHILE x<xSize DO Rect[black,x,y,x+b,y+h]; x ← x+b; Rect[white,x,y,x+w,y+h]; x ← x+w; ENDLOOP; Rect[mortar,0,y+h,xSize,y+h+m]; y ← y+h+m; flag ← NOT flag; ENDLOOP; }; ShowCorners: PROCEDURE = { s: CARDINAL = 8; Rectangle[white, 0, 0, s, s]; Rectangle[white, xSize-s, 0, xSize, s]; Rectangle[white, 0, ySize-s, s, ySize]; Rectangle[white, xSize-s, ySize-s, xSize, ySize]; }; gamma: REAL ← 1.0/2.3; Comp: PROCEDURE [intensity: REAL] RETURNS [REAL] = { intensity ← intensity/255; intensity ← RealFns.Power[intensity, gamma]; RETURN[intensity*255]; }; SetGamma: PROC = { r: REAL ← JaMFnsDefs.GetReal[]; gamma ← 1/MAX[1.1,r]; SetUpColorMap[]; }; SetLevel: PROC = { i: INTEGER ← JaMFnsDefs.PopInteger[]; level ← MAX[0,MIN[i,255]]; SetUpColorMap[]; }; SetMortar: PROC = { i: INTEGER ← JaMFnsDefs.PopInteger[]; m: [0..256) ← MAX[0,MIN[i,255]]; SetColor[mortar,m,m,m]; }; SetB: PROC = { i: INTEGER ← JaMFnsDefs.PopInteger[]; b ← MAX[1,MIN[i,1000]]; ShowIllusion[]; }; SetW: PROC = { i: INTEGER ← JaMFnsDefs.PopInteger[]; w ← MAX[1,MIN[i,1000]]; ShowIllusion[]; }; SetD: PROC = { i: INTEGER ← JaMFnsDefs.PopInteger[]; d ← MAX[0,MIN[i,1000]]; ShowIllusion[]; }; SetH: PROC = { i: INTEGER ← JaMFnsDefs.PopInteger[]; h ← MAX[1,MIN[i,1000]]; ShowIllusion[]; }; SetM: PROC = { i: INTEGER ← JaMFnsDefs.PopInteger[]; m ← MAX[0,MIN[i,1000]]; ShowIllusion[]; }; SetBackground: PROC = { r: REAL ← JaMFnsDefs.GetReal[]; background ← Real.RoundI[Comp[MAX[0,MIN[r,255]]]]; SetUpColorMap[]; }; Real.InitReals[]; IF NOT ColorDisplay.SetMode[[full: FALSE, bitsPerPixelA: 8, bitsPerPixelB: 0]] THEN ERROR; bitmap ← ColorDisplay.baseA; wpl ← ColorDisplay.wplA; -- Note: assume display is on its side xSize ← ColorDisplay.height; ySize ← ColorDisplay.width; ClearScreen[]; SetUpColorMap[]; ColorDisplay.TurnOn[]; JaMFnsDefs.Register[".wedges"L, ShowWedges]; JaMFnsDefs.Register[".blocks"L, ShowBlocks]; JaMFnsDefs.Register[".clearscreen"L, ClearScreen]; JaMFnsDefs.Register[".setgamma"L, SetGamma]; JaMFnsDefs.Register[".setlevel"L, SetLevel]; JaMFnsDefs.Register[".setmortar"L, SetMortar]; JaMFnsDefs.Register[".setbackground"L, SetBackground]; JaMFnsDefs.Register[".corners"L, ShowCorners]; JaMFnsDefs.Register[".illusion"L, ShowIllusion]; JaMFnsDefs.Register[".setb"L, SetB]; JaMFnsDefs.Register[".setw"L, SetW]; JaMFnsDefs.Register[".setd"L, SetD]; JaMFnsDefs.Register[".seth"L, SetH]; JaMFnsDefs.Register[".setm"L, SetM]; }.