-- CGJaMBrick.mesa Cedar 4.0 version
-- Last changed by Pier, October 8, 1982 3:27 pm
-- Last Edited by: Stone, March 21, 1983 5:10 pm

DIRECTORY
CGBrick USING[BuildBrick, currentBrick, FreeBrick],
CGBandImage USING [ShowBands, KillSpace, NoPrinter],
CGBandStream USING [SetBufferPages],
CGBandDevice USING [BandDevice],
JaMFnsDefs USING [JaMExec, PopInteger, PushReal, PushInteger, GetReal, Register],
RealFns USING [ Cos];

CGJaMBrick: PROGRAM
IMPORTS JaMFnsDefs, RealFns, CGBandStream, CGBrick, CGBandImage =

BEGIN OPEN CGBrick, JaMFnsDefs, RealFns;

String: TYPE = REF READONLY TEXT;
LS: TYPE = LONG STRING;

currentFilter: PROC[x,y:REAL] RETURNS [fvalue: REAL] ← TentFilter;--halftone generating proc
brickInited: BOOLEANFALSE; --FALSE before 1st brick is made and after .freebrick is called
halfPi: REAL = 3.14159/2.82;--pi/2*SqRt[2]

CallBufferPages: PROC[] = {
CGBandStream.SetBufferPages[PopInteger[]]; };

CallNoPrinter: PROC[] = {
CGBandImage.NoPrinter ← TRUE; };

CallYesPrinter: PROC[] = {
CGBandImage.NoPrinter ← FALSE; };


CallKillSpace: PROC[] = {
 CGBandImage.KillSpace[];
 };--CallKillSpace

CallShowBands: PROC[] = {
 CGBandImage.ShowBands[screen];
 };--CallShowBands

CallPrintBands: PROC[] = {
 CGBandImage.ShowBands[hornet];
 };--CallPrintBands

CallDLPBands: PROC[] = {
 CGBandImage.ShowBands[platemaker];
 };--CallDLPBands

CallBuildBrick: PROC[]=
--gets the args off the JaM stack and passes them to BuildBrick
{ freq, angle: REAL;

angle ← GetReal[];
freq ← GetReal[];
CGBrick.currentBrick^ ← CGBrick.BuildBrick[freq, angle, currentFilter];
brickInited ← TRUE;
};--CallBuildBrick

CallStripeBrick: PROC[] =
{ sw: INTEGER ← 0;

sw ← PopInteger[];
CGBrick.currentBrick^ ← CGBrick.BuildBrick[2*sw, 0, TentFilter];

FOR zeri: INTEGER IN [0..sw) DO
CGBrick.currentBrick.cBrick[zeri] ← 0.0; ENDLOOP;
FOR onei: INTEGER IN [0..sw) DO
CGBrick.currentBrick.cBrick[sw+onei] ← 0.99; ENDLOOP;
CGBrick.currentBrick.L ← 2*sw;
CGBrick.currentBrick.p ← 1;
CGBrick.currentBrick.D ← 0;
CGBrick.currentBrick.u ← 0;
CGBrick.currentBrick.v ← 0;
};--CallStripeBrick


CallCheckerBrick: PROC[] =
{ sw, index: INTEGER;

sw ← PopInteger[];
CGBrick.currentBrick^ ← CGBrick.BuildBrick[2*sw, 0, TentFilter];

FOR loop: INTEGER IN [0..sw) DO
index ← loop*sw*2;
FOR zeri: INTEGER IN [0..sw) DO
CGBrick.currentBrick.cBrick[index+zeri] ← 0.1; ENDLOOP;
index ← index+sw;
FOR onei: INTEGER IN [0..sw) DO
CGBrick.currentBrick.cBrick[index+onei] ← 0.99; ENDLOOP;
ENDLOOP;
CGBrick.currentBrick.L ← 2*sw;
CGBrick.currentBrick.p ← sw;
CGBrick.currentBrick.D ← sw;
CGBrick.currentBrick.u ← 0;
CGBrick.currentBrick.v ← 0;
};--CallCheckerBrick


CallFreeBrick: PROC[]=
{ CGBrick.FreeBrick[CGBrick.currentBrick];
brickInited ← FALSE;
};--CallFreeBrick

CallMagicBrick: PROC[]=
--build a 5X5 "magic square" filter
{
magic: ARRAY [0..25) OF INTEGER ← [8,4,17,11,25,
     22,15,6,19,3,
     20,21,13,2,9,
     14,7,5,23,16,
     1,18,24,10,2];
    
CGBrick.currentBrick^ ← CGBrick.BuildBrick[5, 0, currentFilter];
CGBrick.currentBrick.L ← 5;
CGBrick.currentBrick.p ← 5;
CGBrick.currentBrick.D ← 0;
CGBrick.currentBrick.u ← 0;
CGBrick.currentBrick.v ← 0;
FOR i:CARDINAL IN [0..25) DO
CGBrick.currentBrick.cBrick[i] ← magic[i]/25.0;
ENDLOOP;
brickInited ← TRUE;
};--CallMagicBrick

CallStingerBrick: PROC[]=
--build a 6X6 spiral filter for Stinger
{
dot: ARRAY [0..36) OF REAL ← [113,106,99,92,85,78,
     120,213,205,198,191,71,
     128,220,255,248,184,64,
     135,223,234,241,177,57,
     142,149,156,163,170,50,
     7,14,21,28,35,43];
    
    
CGBrick.currentBrick^ ← CGBrick.BuildBrick[6, 0, currentFilter];
CGBrick.currentBrick.L ← 6;
CGBrick.currentBrick.p ← 6;
CGBrick.currentBrick.D ← 0;
CGBrick.currentBrick.u ← 0;
CGBrick.currentBrick.v ← 0;
FOR i:CARDINAL IN [0..36) DO
CGBrick.currentBrick.cBrick[i] ← dot[i]/256.0;
ENDLOOP;
brickInited ← TRUE;
};--CallMagicBrick

TentFilter: PROC[x,y: REAL] RETURNS[val: REAL]=
{RETURN [1.0-ABS[x]];
};
SetTentFilter: PROC[] = {currentFilter ← TentFilter};

XFilter: PROC[x,y: REAL] RETURNS[val: REAL]=
{RETURN [ABS[x]];
};
SetXFilter: PROC[] = {currentFilter ← XFilter};

YFilter: PROC[x,y: REAL] RETURNS[val: REAL]=
{RETURN [ABS[y]];
};
SetYFilter: PROC[] = {currentFilter ← YFilter};

XYSumFilter: PROC[x,y: REAL] RETURNS[val: REAL]=
{RETURN [ABS[(x+y)/2]];
};
SetXYSumFilter: PROC[] = {currentFilter ← XYSumFilter};

XYDiffFilter: PROC[x,y: REAL] RETURNS[val: REAL]=
{RETURN [ABS[(x-y)/2]];
};
SetXYDiffFilter: PROC[] = {currentFilter ← XYDiffFilter};

CosFilter: PROC[x,y: REAL] RETURNS[val: REAL]=
{RETURN [Cos[halfPi*x]*Cos[halfPi*y]];
};
SetCosFilter: PROC[] = {currentFilter ← CosFilter};

TCosFilter: PROC[x,y: REAL] RETURNS[val: REAL]=
{RETURN [(3/4.0)*(Cos[halfPi*x]*Cos[halfPi*x])+(1/4.0)*(Cos[halfPi*y]*Cos[halfPi*y])];
};
TSetCosFilter: PROC[] = {currentFilter ← TCosFilter};


getp: PROC[]=
{
IF brickInited
THEN PushInteger[CGBrick.currentBrick.p]
ELSE JaMExec["brickNotThere"L];};-- .getp

getl: PROC[]=
{
IF brickInited
THEN PushInteger[CGBrick.currentBrick.L]
ELSE JaMExec["brickNotThere"L];};-- .getl

getd: PROC[]=
{
IF brickInited
THEN PushInteger[CGBrick.currentBrick.D]
ELSE JaMExec["brickNotThere"L];};-- .getd

getu: PROC[]=
{
IF brickInited
THEN PushInteger[CGBrick.currentBrick.u]
ELSE JaMExec["brickNotThere"L];};-- .getd

getv: PROC[]=
{
IF brickInited
THEN PushInteger[CGBrick.currentBrick.v]
ELSE JaMExec["brickNotThere"L];};-- .getd

getbu: PROC[]=
{l, w: INTEGER;
ret: REAL;

l ← PopInteger[];
w ← PopInteger[];
IF brickInited
THEN {ret ← CGBrick.currentBrick.cBrick[CGBrick.currentBrick.L*w + l]; PushReal[ret];}
ELSE JaMExec["brickNotThere"L]; --push this string on execution stack
};-- .getbu

rem: PROC[]=
{x, y, ret: INTEGER;

y ← PopInteger[];
x ← PopInteger[];
ret ← x MOD y;
PushInteger[ret];
};--rem

mod: PROC[]=
{ x, y, ret: INTEGER;

y ← PopInteger[];
x ← PopInteger[];
ret ← (IF x >= 0 THEN (x MOD y) ELSE ((y-1) + (x+1) MOD y) );
PushInteger[ret];

};--mod (not Mesa MOD, which doesn't work correctly for negative numbers

ShowBrick: PROC[freq: REAL, angle: REAL, threshold: REAL,
filter: PROC[x,y:REAL] RETURNS [fvalue: REAL] ← TentFilter,
xFrom, xTo, yFrom, yTo: CARDINAL] = {

-- Modd COPIED FROM CGBRICKIMPL !!

-- Modd: PROC[x, y: LONG INTEGER] RETURNS [LONG INTEGER] = {
-- RETURN [IF x >= 0 THEN (x MOD y) ELSE ((y-1) + (x+1) MOD y)];
-- };
--
-- colI: LONG INTEGER;
-- yI,xI, row, col: CARDINAL ← 0;
-- bvalue: REAL ← 0.0;
-- gc: Graphics.Context;
-- oldFat: BOOLEAN ← FALSE;
--
-- gc ← JaMGraphics.GetDC[];
-- oldFat ← Graphics.SetFat[gc, TRUE];
--
-- IF brickInited THEN CallFreeBrick[];
-- CGBrick.currentBrick^ ← CGBrick.BuildBrick[freq, angle, filter];
-- brickInited ← TRUE;
-- FOR xI IN [xFrom.. xTo] DO
-- FOR yI IN [yFrom..yTo] DO
-- row ← yI MOD CGBrick.currentBrick.p;
-- colI ← Modd[(xI - LONG[CGBrick.currentBrick.D] * (yI/CGBrick.currentBrick.p)), CGBrick.currentBrick.L];
-- col ← Inline.LowHalf[colI];
-- bvalue ← CGBrick.currentBrick.cBrick[CGBrick.currentBrick.L*row + col];
-- IF bvalue >= threshold THEN {Graphics.MoveTo[gc, xI, yI]; Graphics.DrawTo[gc, xI, yI];};
-- ENDLOOP;
-- ENDLOOP;
-- [] ← Graphics.SetFat[gc, oldFat];
};--ShowBrick

CallShowBrick: PROC[] = {

xFrom, xTo, yFrom, yTo: CARDINAL;
freq, threshold, angle: REAL ← 0.0;

threshold ← GetReal[];
angle ← GetReal[];
freq ← GetReal[];
yTo ← PopInteger[];
yFrom ← PopInteger[];
xTo ← PopInteger[];
xFrom ← PopInteger[];
ShowBrick[freq, angle, threshold, currentFilter, xFrom, xTo, yFrom, yTo];
};--CallShowBrick

--REGISTRATION WITH JAM

Register[".tentfilter"L, SetTentFilter];
Register[".xfilter"L, SetXFilter];
Register[".yfilter"L, SetYFilter];
Register[".xysumfilter"L, SetXYSumFilter];
Register[".xydifffilter"L, SetXYDiffFilter];
Register[".cosfilter"L, SetCosFilter];
Register[".tcosfilter"L, TSetCosFilter];

Register[".showbrick"L, CallShowBrick];
Register[".buildbrick"L, CallBuildBrick];
Register[".magicbrick"L, CallMagicBrick];
Register[".freebrick"L, CallFreeBrick];
Register[".stingerbrick"L, CallStingerBrick];
Register[".getp"L, getp];

Register[".getl"L, getl];
Register[".getd"L, getd];
Register[".getbu"L, getbu];
Register[".getv"L, getv];
Register[".getu"L, getu];
Register[".rem"L, rem];
Register[".mod"L, mod];

Register[".dlpbands"L, CallDLPBands];
Register[".showbands"L, CallShowBands];
Register[".printbands"L, CallPrintBands];
Register[".killspace"L, CallKillSpace];
Register[".stripebrick"L, CallStripeBrick];
Register[".checkerbrick"L, CallCheckerBrick];
Register[".noprinter"L, CallNoPrinter];
Register[".yesprinter"L, CallYesPrinter];
Register[".setbufferpages"L, CallBufferPages];

END.

LOG
-- created 20-Oct-81 by Pier
--added ShowBands, 2-Dec-81 12:05:11
--added StripeBands, 12-Jan-82 15:37:49
--added stingerbrick, 20-JAN-82
--fixed Modd to be like CGBrickImpl, added local version of ToString
because Cedar 2.2 ConvertUnsafe has bug! 21-JAN-82
--added TCosFilter 2/1/82
--revised TCosFilter, added singleFile 2/2/82
--changed to use L,p,D,cBrick form of brick, 2/22/82
--removed SetSingleFile, 3/30/82
--convert to Cedar 3.2, 6/29/82