-- 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];
}.