-- XBitmapFns.mesa
-- Mesa 6 version
-- Last changed by Doug Wyatt, September 23, 1980 2:57 PM

DIRECTORY
XGraphicsDefs: FROM "XGraphicsDefs",
AltoDisplay: FROM "AltoDisplay",
InlineDefs: FROM "InlineDefs",
MiscDefs: FROM "MiscDefs",
DisplayDefs: FROM "DisplayDefs",
BitBltDefs: FROM "BitBltDefs",
SegmentDefs: FROM "SegmentDefs",
XDisplayDefs: FROM "XDisplayDefs";

XBitmapFns: PROGRAM
IMPORTS XGraphicsDefs,XDisplayDefs,
InlineDefs,MiscDefs,SegmentDefs
EXPORTS XGraphicsDefs
SHARES XDisplayDefs =
BEGIN

Screen: XGraphicsDefs.Bitmap ←
[bank: 0, nWords: 0, nBits: 0, nLines: 0, bits: NIL];
screenBmd: XDisplayDefs.BitmapDescriptor;
screenBm: XDisplayDefs.BMPtr = @screenBmd;
dcba: XDisplayDefs.DcbArray;
dcb: XDisplayDefs.DcbPtr = XDisplayDefs.DcbInit[@dcba];

BitTable: ARRAY [0..20B) OF CARDINAL ←
[100000B,40000B,20000B,10000B,4000B,2000B,
1000B,400B,200B,100B,40B,20B,10B,4,2,1
];
color: DisplayDefs.Background ← white;

XM: BOOLEAN ← SegmentDefs.memConfig.useXM;

x: XDisplayDefs.BBArray;
SetPointBLT: XDisplayDefs.BBPtr ← SetPointBLTInit[@x];
SetPointBLTInit: PROCEDURE[bba: POINTER TO XDisplayDefs.BBArray]
RETURNS[XDisplayDefs.BBPtr] = INLINE
BEGIN OPEN XDisplayDefs;
bbt: BBPtr←BBInit[bba];
bbt.dw←bbt.dh←1;
bbt.gray←ALL[177777B];
RETURN[bbt];
END;

DefaultAllocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER] ←
BEGIN
RETURN [SegmentDefs.LongDataSegmentAddress[
SegmentDefs.NewDataSegment[
SegmentDefs.DefaultXMBase,(nwords+255)/256]]];
END;
DefaultFree: PROCEDURE [XVM: LONG POINTER] ←
BEGIN
SegmentDefs.DeleteDataSegment[SegmentDefs.LongVMtoDataSegment[XVM]];
END;
DefaultAllocateFromBank: PROCEDURE [nwords: CARDINAL,bank: CARDINAL] RETURNS [LONG POINTER] ←
BEGIN
RETURN [SegmentDefs.LongDataSegmentAddress[
SegmentDefs.NewDataSegment[
SegmentDefs.DefaultBase0-bank,(nwords+255)/256]]];
END;

SetXMAlloc: PUBLIC PROCEDURE [Allocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER],Free: PROCEDURE [LONG POINTER],AllocateFromBank: PROCEDURE [nwords: CARDINAL,bank: CARDINAL] RETURNS [LONG POINTER]] =
BEGIN
DefaultAllocate ← Allocate;
DefaultFree ← Free;
DefaultAllocateFromBank ← AllocateFromBank;
END;

GetXMAlloc: PUBLIC PROCEDURE RETURNS [Allocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER],Free: PROCEDURE [LONG POINTER],AllocateFromBank: PROCEDURE [nwords: CARDINAL,bank: CARDINAL] RETURNS [LONG POINTER]] =
BEGIN
RETURN[DefaultAllocate,DefaultFree,DefaultAllocateFromBank];
END;

GrayThresholds: ARRAY [0..16) OF CARDINAL ←
[00,08,02,10, --even dot distribution, maximum flicker
14,04,12,06,
03,11,01,09,
13,07,15,05
];
hff: ARRAY [0..16) OF CARDINAL ←
[00,04,10,14, --minimum flicker
01,05,11,15,
08,12,02,06,
09,13,03,07
];
GrayLevel: CARDINAL ← 0;
Gray0,Gray1,Gray2,Gray3: CARDINAL ← 177777B;

SetGrayThresholds: PUBLIC PROCEDURE [new: POINTER TO ARRAY [0..17B] OF CARDINAL] =
BEGIN GrayThresholds ← new↑;END;

halftoneWord: TYPE = MACHINE DEPENDENT RECORD
[
unused: [0..7777B],
val1,val2,val3,val4: BOOLEAN
];
SetGrayLevel: PUBLIC PROCEDURE [intensity: CARDINAL] =
BEGIN
h: halftoneWord;
value,scanline: CARDINAL;

IF GrayLevel = intensity THEN RETURN;
GrayLevel ← intensity;

FOR scanline IN [0..4) DO
h.val1 ← intensity <= GrayThresholds[scanline*4+0];
h.val2 ← intensity <= GrayThresholds[scanline*4+1];
h.val3 ← intensity <= GrayThresholds[scanline*4+2];
h.val4 ← intensity <= GrayThresholds[scanline*4+3];
h.unused ← 0;
value ← LOOPHOLE[h];
value ← value + value*16;
value ← value + value*256;
SELECT scanline FROM
0=> Gray0←value;
1=> Gray1←value;
2=> Gray2←value;
3=> Gray3←value;
ENDCASE;
ENDLOOP;
END;

GetGrayBlock: PUBLIC PROCEDURE RETURNS [gray0,gray1,gray2,gray3: CARDINAL] =
BEGIN RETURN [Gray0,Gray1,Gray2,Gray3];END;

SetDefaultBitmap: PUBLIC PROCEDURE [width,height: CARDINAL] =
BEGIN
IF Screen.bits # NIL THEN
MiscDefs.CallDebugger["SetDefaultBitmap called after TurnOnGraphics"];
Screen.nBits ← width;
Screen.nLines ← height;
END;

Even: PROCEDURE[p: POINTER] RETURNS[POINTER] =
BEGIN OPEN InlineDefs;
RETURN[IF BITAND[LOOPHOLE[p,CARDINAL],1]=1 THEN p+1 ELSE p];
END;

TurnOnGraphics: PUBLIC PROCEDURE RETURNS [POINTER TO XGraphicsDefs.Bitmap] =
BEGIN
IF Screen.bits # NIL THEN
MiscDefs.CallDebugger["TurnOnGraphics called twice"];
XGraphicsDefs.TurnOnText;

IF Screen.nLines=0 THEN Screen.nLines←XDisplayDefs.LinesRemaining[];
XDisplayDefs.BMDisplaySize[bm: screenBm,
width: Screen.nBits, height: Screen.nLines];
XDisplayDefs.AllocBitmap[screenBm];
Screen.bank←XDisplayDefs.LPBank[screenBm.base];
Screen.bits←XDisplayDefs.LPPtr[screenBm.base];
Screen.nWords←screenBm.raster;
Screen.nBits←16*Screen.nWords;
Screen.nLines←screenBm.lines;
EraseArea[0,0,Screen.nBits-1,Screen.nLines-1];
XDisplayDefs.DcbBitmap[dcb,screenBm];
XDisplayDefs.InsertDcb[dcb,XDisplayDefs.FirstDcb[]];
RETURN[@Screen];
END;

GetDefaultBitmapHandle: PUBLIC PROCEDURE RETURNS [POINTER TO XGraphicsDefs.Bitmap] =
BEGIN RETURN[@Screen];END;

--first, the dummy routines using default bitMap (Screen)
PutPoint: PUBLIC PROCEDURE [x,y: CARDINAL] =
BEGIN SetPointInBitmap[x,y,replace,@Screen];END;
ErasePoint: PUBLIC PROCEDURE [x,y: CARDINAL] =
BEGIN SetPointInBitmap[x,y,erase,@Screen];END;
XorPoint: PUBLIC PROCEDURE [x,y: CARDINAL] =
BEGIN SetPointInBitmap[x,y,invert,@Screen];END;

PutLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetLineInBitmap[x1,y1,x2,y2,replace,@Screen];END;
EraseLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetLineInBitmap[x1,y1,x2,y2,erase,@Screen];END;
XorLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetLineInBitmap[x1,y1,x2,y2,invert,@Screen];END;

PutPointInBitmap: PUBLIC PROCEDURE [x,y: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetPointInBitmap[x,y,replace,b];END;
ErasePointInBitmap: PUBLIC PROCEDURE [x,y: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetPointInBitmap[x,y,erase,b];END;
XorPointInBitmap: PUBLIC PROCEDURE [x,y: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetPointInBitmap[x,y,invert,b];END;

PutLineInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetLineInBitmap[x1,y1,x2,y2,replace,b];END;
EraseLineInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetLineInBitmap[x1,y1,x2,y2,erase,b];END;
XorLineInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetLineInBitmap[x1,y1,x2,y2,invert,b];END;

PutArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetAreaInBitmap[x1,y1,x2,y2,paint,@Screen];END;
EraseArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetAreaInBitmap[x1,y1,x2,y2,erase,@Screen];END;
XorArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetAreaInBitmap[x1,y1,x2,y2,invert,@Screen];END;
ReplaceArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetAreaInBitmap[x1,y1,x2,y2,replace,@Screen];END;

PutAreaInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetAreaInBitmap[x1,y1,x2,y2,paint,b];END;
EraseAreaInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetAreaInBitmap[x1,y1,x2,y2,erase,b];END;
XorAreaInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetAreaInBitmap[x1,y1,x2,y2,invert,b];END;
ReplaceAreaInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetAreaInBitmap[x1,y1,x2,y2,replace,b];END;

PutGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetGrayInBitmap[x1,y1,x2,y2,paint,@Screen];END;
EraseGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetGrayInBitmap[x1,y1,x2,y2,erase,@Screen];END;
XorGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetGrayInBitmap[x1,y1,x2,y2,invert,@Screen];END;
ReplaceGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL] =
BEGIN SetGrayInBitmap[x1,y1,x2,y2,replace,@Screen];END;

PutGrayInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetGrayInBitmap[x1,y1,x2,y2,paint,b];END;
EraseGrayInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetGrayInBitmap[x1,y1,x2,y2,erase,b];END;
XorGrayInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetGrayInBitmap[x1,y1,x2,y2,invert,b];END;
ReplaceGrayInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetGrayInBitmap[x1,y1,x2,y2,replace,b];END;

PutBitmap: PUBLIC PROCEDURE [b: POINTER TO XGraphicsDefs.Bitmap,x,y: CARDINAL] =
BEGIN SetBitmapInBitmap[b,x,y,paint,@Screen];END;
EraseBitmap: PUBLIC PROCEDURE [b: POINTER TO XGraphicsDefs.Bitmap,x,y: CARDINAL] =
BEGIN SetBitmapInBitmap[b,x,y,erase,@Screen];END;
XorBitmap: PUBLIC PROCEDURE [b: POINTER TO XGraphicsDefs.Bitmap,x,y: CARDINAL] =
BEGIN SetBitmapInBitmap[b,x,y,invert,@Screen];END;
ReplaceBitmap: PUBLIC PROCEDURE[b: POINTER TO XGraphicsDefs.Bitmap,x,y: CARDINAL]=
BEGIN SetBitmapInBitmap[b,x,y,replace,@Screen];END;

PutBitmapInBitmap: PUBLIC PROCEDURE [b: POINTER TO XGraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetBitmapInBitmap[b,x,y,paint,dest];END;
EraseBitmapInBitmap: PUBLIC PROCEDURE [b: POINTER TO XGraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetBitmapInBitmap[b,x,y,erase,dest];END;
XorBitmapInBitmap: PUBLIC PROCEDURE [b: POINTER TO XGraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN SetBitmapInBitmap[b,x,y,invert,dest];END;
ReplaceBitmapInBitmap: PUBLIC PROCEDURE[b: POINTER TO XGraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO XGraphicsDefs.Bitmap]=
BEGIN SetBitmapInBitmap[b,x,y,replace,dest];END;

--and the real guys

BmDest: PROCEDURE[bbt: XDisplayDefs.BBPtr,
bm: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN OPEN XDisplayDefs;
bmd: BitmapDescriptor←[base: LP[bm.bits,bm.bank],
raster: bm.nWords, lines: bm.nLines];
BBDest[bbt,@bmd];
END;
BmSource: PROCEDURE[bbt: XDisplayDefs.BBPtr,
bm: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN OPEN XDisplayDefs;
bmd: BitmapDescriptor←[base: LP[bm.bits,bm.bank],
raster: bm.nWords, lines: bm.nLines];
BBSource[bbt,@bmd];
END;

SetPointInBitmap: PUBLIC PROCEDURE [x,y: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN
IF x >= b.nBits THEN RETURN;
IF y >= b.nLines THEN RETURN;
-- save your ass
BmDest[SetPointBLT,b];
SetPointBLT.operation ← LOOPHOLE[fn];
SetPointBLT.dlx ← x;
SetPointBLT.dty ← y;
XDisplayDefs.BitBlt[SetPointBLT];
END;


SetLineInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN
hstep,vstep,hsign,vsign,count: INTEGER;
horizontal: BOOLEAN;

hstep ← x1-x2;
vstep ← y1-y2;
hsign ← IF hstep >= 0 THEN 1 ELSE -1;
vsign ← IF vstep >= 0 THEN 1 ELSE -1;
horizontal←ABS[hstep] > ABS[vstep];
count ← IF horizontal THEN ABS[vstep]+(ABS[hstep]-ABS[vstep])/2
ELSE ABS[hstep]+(ABS[vstep]-ABS[hstep])/2 ;

SetPointInBitmap[x2,y2,fn,b];
UNTIL (x1 = x2) AND (y1 = y2) DO
IF count >= ABS[vstep] THEN-- go horizontal
BEGIN
x2 ← x2 + hsign;
count ← count - ABS[vstep];
IF horizontal THEN SetPointInBitmap[x2,y2,fn,b];
END
ELSE BEGIN
y2 ← y2+vsign;
count ← count + ABS[hstep];
IF NOT horizontal THEN SetPointInBitmap[x2,y2,fn,b];
END;
ENDLOOP;
SetPointInBitmap[x2,y2,fn,b];

END;

SetAreaInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN
bba: XDisplayDefs.BBArray;
bbt: XDisplayDefs.BBPtr ← XDisplayDefs.BBInit[@bba];

IF INTEGER[x1] > INTEGER[x2] THEN BEGIN t: CARDINAL ← x1;x1←x2;x2←t;END;
IF INTEGER[x2] < 0 THEN RETURN;
IF INTEGER[x1] < 0 THEN x1 ← 0 ELSE IF x1 >= b.nBits THEN RETURN;
IF INTEGER[y1] > INTEGER[y2] THEN BEGIN t: CARDINAL ← y1;y1←y2;y2←t;END;
IF INTEGER[y2] < 0 THEN RETURN;
IF INTEGER[y1] < 0 THEN y1 ← 0 ELSE IF y1 >= b.nLines THEN RETURN;
IF x2 >= b.nBits THEN x2 ← b.nBits - 1;
IF y2 >= b.nLines THEN y2 ← b.nLines - 1;
BmDest[bbt,b];
bbt.operation←LOOPHOLE[fn];
bbt.dlx←x1; bbt.dty←y1;
bbt.dw←x2+1-x1; bbt.dh←y2+1-y1;
bbt.gray←ALL[177777B];
XDisplayDefs.BitBlt[bbt];
END;

SetGrayInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN
bba: XDisplayDefs.BBArray;
bbt: XDisplayDefs.BBPtr ← XDisplayDefs.BBInit[@bba];

IF x1 > x2 THEN BEGIN t: CARDINAL ← x1;x1←x2;x2←t;END;
IF y1 > y2 THEN BEGIN t: CARDINAL ← y1;y1←y2;y2←t;END;
IF x2 >= b.nBits THEN x2 ← b.nBits - 1;
IF y2 >= b.nLines THEN y2 ← b.nLines - 1;
BmDest[bbt,b];
bbt.operation←LOOPHOLE[fn];
bbt.dlx←x1; bbt.dty←y1;
bbt.dw←x2+1-x1; bbt.dh←y2+1-y1;
bbt.gray←[Gray0,Gray1,Gray2,Gray3];
XDisplayDefs.BitBlt[bbt];
END;

MaskAreaInBitmap: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN
bba: XDisplayDefs.BBArray;
bbt: XDisplayDefs.BBPtr ← XDisplayDefs.BBInit[@bba];

IF x1 > x2 THEN BEGIN t: CARDINAL ← x1;x1←x2;x2←t;END;
IF y1 > y2 THEN BEGIN t: CARDINAL ← y1;y1←y2;y2←t;END;
IF x2 >= b.nBits THEN x2 ← b.nBits - 1;
IF y2 >= b.nLines THEN y2 ← b.nLines - 1;
BmDest[bbt,b]; BmSource[bbt,b];
bbt.sourcetype←andgray;
bbt.operation←replace;
bbt.slx←x1; bbt.sty←y1;
bbt.dlx←x1; bbt.dty←y1;
bbt.dw←x2+1-x1; bbt.dh←y2+1-y1;
bbt.gray←[Gray0,Gray1,Gray2,Gray3];
XDisplayDefs.BitBlt[bbt];
END;

SetBitmapInBitmap: PUBLIC PROCEDURE [b: POINTER TO XGraphicsDefs.Bitmap,
x,y: CARDINAL,fn: BitBltDefs.BBoperation,dest: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN
bba: XDisplayDefs.BBArray;
bbt: XDisplayDefs.BBPtr ← XDisplayDefs.BBInit[@bba];
x2: CARDINAL ← x+b.nBits-1;
y2: CARDINAL ← y+b.nLines-1;

IF x >= dest.nBits OR y >= dest.nLines THEN RETURN;
IF x2 >= dest.nBits THEN x2 ← dest.nBits - 1;
IF y2 >= dest.nLines THEN y2 ← dest.nLines - 1;

BmDest[bbt,dest]; BmSource[bbt,b];
bbt.sourcetype←block;
bbt.operation←LOOPHOLE[fn];
bbt.slx←0; bbt.sty←0;
bbt.dlx←x; bbt.dty←y;
bbt.dw←x2+1-x; bbt.dh←y2+1-y;
XDisplayDefs.BitBlt[bbt];
END;

PutGrayBitmapInBitmap: PUBLIC PROCEDURE [b: POINTER TO XGraphicsDefs.Bitmap,
x,y: CARDINAL,dest: POINTER TO XGraphicsDefs.Bitmap] =
BEGIN
bba: XDisplayDefs.BBArray;
bbt: XDisplayDefs.BBPtr ← XDisplayDefs.BBInit[@bba];
x2: CARDINAL ← x+b.nBits-1;
y2: CARDINAL ← y+b.nLines-1;

IF x >= dest.nBits OR y >= dest.nLines THEN RETURN;
IF x2 >= dest.nBits THEN x2 ← dest.nBits - 1;
IF y2 >= dest.nLines THEN y2 ← dest.nLines - 1;

--first, erase
BmDest[bbt,dest]; BmSource[bbt,b];
bbt.sourcetype←block;
bbt.operation←erase;
bbt.slx←0; bbt.sty←0;
bbt.dlx←x; bbt.dty←y;
bbt.dw←x2+1-x; bbt.dh←y2+1-y;
bbt.gray←[Gray0,Gray1,Gray2,Gray3];
XDisplayDefs.BitBlt[bbt];

--now, paint gray bits
bbt.sourcetype ← andgray;
bbt.operation ← paint;
XDisplayDefs.BitBlt[bbt];
END;

END.