DIRECTORY
DisplayListDefs,
GraphicsDefs,
HalftoneDefs,
IODefs,
PressDefs,
StrawDefs,
StreamDefs,
SystemDefs;
StrawImage: PROGRAM IMPORTS DisplayListDefs, GraphicsDefs, HalftoneDefs, IODefs, PressDefs, StrawDefs, SystemDefs
EXPORTS StrawDefs =
BEGIN
Buttons: TYPE = MACHINE DEPENDENT RECORD
[ KeyPadAndGarbage: [0..10000B),
Mark: BOOLEAN, --TRUE means button up
Select: BOOLEAN,
Draw: BOOLEAN
];
KeyWord2: TYPE = MACHINE DEPENDENT RECORD
[ One,Esc,Tab,F,Ctrl,C,J,B,Z,LShift,Period,Semi,Return,LArrow,Del,xxx: BOOLEAN
];
KeyWord: POINTER TO KeyWord2 = LOOPHOLE[177036B];
MouseButtons: POINTER TO Buttons = LOOPHOLE[177030B];
CursorX: POINTER TO CARDINAL = LOOPHOLE[426B];
CursorY: POINTER TO CARDINAL = LOOPHOLE[427B];
keys: StreamDefs.StreamHandle ← IODefs.GetInputStream[];
ScreenHeight: CARDINAL ← GraphicsDefs.GetDefaultBitmapHandle[].nLines;
selectGray: CARDINAL ← 15;
bitsPerInch: CARDINAL ← 72;
micasPerInch: CARDINAL = 2540;
Mica: TYPE = CARDINAL;
dc: PROCEDURE [m: Mica] RETURNS [CARDINAL] = INLINE
BEGIN
RETURN[PressDefs.SignedMulDiv[m,bitsPerInch,micasPerInch]];
END;
mc: PROCEDURE [c: CARDINAL] RETURNS [Mica] = INLINE
BEGIN
RETURN[PressDefs.MulDiv[c,micasPerInch,bitsPerInch]];
END;
EditGrayImage: PUBLIC PROCEDURE [do: POINTER TO StrawDefs.DotObject] =
BEGIN
pdd: POINTER TO PressDefs.PressDotsData ← do.DotsData;
borderWidth: CARDINAL ← MIN[16,
MIN[do.Box.boxBitmap.nBits,do.Box.boxBitmap.nLines]/6];
x: INTEGER ← CursorX↑;
y: INTEGER ← CursorY↑;
RealCursor: GraphicsDefs.Bitmap ← [bank: 0,nWords: 1,nBits:16,nLines:16, bits:LOOPHOLE[431B]];
Cursor: GraphicsDefs.Bitmap ← [bank: 0,nWords: 1,nBits:16,nLines:16, bits:SystemDefs.AllocateHeapNode[16]];
xThird,yThird: CARDINAL;
WhiteBox: GraphicsDefs.Box;
GraphicsDefs.CreateBox[@WhiteBox,18,18];
GraphicsDefs.DisplayBox[@WhiteBox,x-1,y-1];
WHILE x IN [INTEGER[do.Box.displayX-borderWidth]..
INTEGER[do.Box.displayX+do.Box.boxBitmap.nBits+borderWidth]] AND
y IN [INTEGER[do.Box.displayY-borderWidth]..
INTEGER[do.Box.displayY+do.Box.boxBitmap.nLines+borderWidth]] DO
--check which edit border
xThird ← MIN[2,(x-(do.Box.displayX-borderWidth))/
((do.Box.boxBitmap.nBits+borderWidth+1)/3)];
yThird ← MIN[2,(y-(do.Box.displayY-borderWidth))/
((do.Box.boxBitmap.nLines+borderWidth+1)/3)];
SELECT TRUE FROM
Bounded[do,x,y,0,borderWidth] => --stretch border
BEGIN
MakeArrow[SELECT xThird FROM 0=>1,1=>7,ENDCASE=>14,
SELECT yThird FROM 0=>1,1=>7,ENDCASE=>14,
SELECT xThird FROM 0=>14,1=>7,ENDCASE=>1,
SELECT yThird FROM 0=>14,1=>7,ENDCASE=>1,FALSE,@Cursor];
GraphicsDefs.MoveBox[@WhiteBox,x-1,y-1];
GraphicsDefs.ReplaceBitmap[@Cursor,0,0,@RealCursor];
IF NOT MouseButtons.Select THEN
BEGIN
GraphicsDefs.RemoveBox[@WhiteBox];
DisplayListDefs.DeleteDisplayItem[@do.Box];
StrawDefs.RestoreGrid[@do.Box]; --must have correct bit counts
XorBox[do];
UNTIL MouseButtons.Select DO
IF yThird = 1 OR xThird = 1 THEN StretchEdge[do,yThird*3+xThird]
ELSE StretchCorner[do,yThird*3+xThird];
ENDLOOP;
XorBox[do];
ReDisplay[do];
END;
END;
((xThird # 1) OR (yThird # 1)) AND
Bounded[do,x,y,-borderWidth,borderWidth] => --window border
BEGIN
MakeArrow[SELECT xThird FROM 0=>0,1=>7,ENDCASE=>15,
SELECT yThird FROM 0=>0,1=>7,ENDCASE=>15,
SELECT xThird FROM 0=>8,1=>7,ENDCASE=>7,
SELECT yThird FROM 0=>8,1=>7,ENDCASE=>7,TRUE,@Cursor];
GraphicsDefs.MoveBox[@WhiteBox,x-1,y-1];
GraphicsDefs.ReplaceBitmap[@Cursor,0,0,@RealCursor];
IF NOT MouseButtons.Select THEN
BEGIN
newDo: StrawDefs.DotObject ← do↑; --copy it
dd: PressDefs.PressDotsData ← do.DotsData↑;
dx1,dx2,dy1,dy2: INTEGER;
ndd: POINTER TO PressDefs.PressDotsData ← newDo.DotsData;
nb: POINTER TO GraphicsDefs.Box ← @newDo.Box;
nbm: POINTER TO GraphicsDefs.Bitmap ← @nb.boxBitmap;
bMode: CARDINAL ← pdd.mode/4;
sMode: CARDINAL ← pdd.mode MOD 4;
normal: BOOLEAN = sMode IN [2..3];
PtoD: PROCEDURE [pixels: INTEGER] RETURNS [dots: INTEGER] = INLINE
BEGIN
dots ← PressDefs.SignedMulDiv[pixels,
dc[IF normal THEN dd.micaWidth ELSE dd.micaHeight],
dd.displayPixels];
END;
DtoP: PROCEDURE [dots: INTEGER] RETURNS [pixels: INTEGER] = INLINE
BEGIN
pixels ← PressDefs.SignedMulDiv[dots,dd.displayPixels,
dc[IF normal THEN dd.micaWidth ELSE dd.micaHeight]];
END;
LtoD: PROCEDURE [lines: INTEGER] RETURNS [dots: INTEGER] = INLINE
BEGIN
dots ← PressDefs.SignedMulDiv[lines,
dc[IF normal THEN dd.micaHeight ELSE dd.micaWidth],
dd.displayLines];
END;
DtoL: PROCEDURE [dots: INTEGER] RETURNS [lines: INTEGER] = INLINE
BEGIN
lines ← PressDefs.SignedMulDiv[dots,dd.displayLines,
dc[IF normal THEN dd.micaHeight ELSE dd.micaWidth]];
END;
GraphicsDefs.RemoveBox[@WhiteBox];
XorBox[do];
UNTIL MouseButtons.Select DO
WindowDots[@newDo,yThird*3+xThird];
ENDLOOP;
XorBox[@newDo];
DisplayListDefs.DeleteDisplayItem[@do.Box];
StrawDefs.RestoreGrid[@do.Box]; --must have correct bit counts
--calculate new window
dx1 ← nb.displayX-do.Box.displayX;
dy1 ← nb.displayY-do.Box.displayY;
dx2 ← (do.Box.displayX+do.Box.boxBitmap.nBits)-
(nb.displayX+nbm.nBits);
dy2 ← (do.Box.displayY+do.Box.boxBitmap.nLines)-
(nb.displayY+nbm.nLines);
ndd.passPixels ← MAX[0,INTEGER[dd.passPixels+DtoP[SELECT bMode FROM
0=>dx1, 1=>dx2, 2=>dy2, ENDCASE=>dy1]]];
ndd.passLines ← MAX[0,INTEGER[dd.passLines+DtoL[SELECT sMode FROM
0=>dx1, 1=>dx2, 2=>dy2, ENDCASE=>dy1]]];
ndd.displayPixels ← MIN[ndd.nPixels-ndd.passPixels,
dd.displayPixels+dd.passPixels-ndd.passPixels-
DtoP[SELECT bMode FROM 0=>dx2, 1=>dx1, 2=>dy1, ENDCASE=>dy2]];
ndd.displayLines ← MIN[ndd.nLines-ndd.passLines,
dd.displayLines+dd.passLines-ndd.passLines-
DtoL[SELECT sMode FROM 0=>dx2, 1=>dx1, 2=>dy1, ENDCASE=>dy2]];
IF normal THEN
BEGIN
nbm.nBits ← PtoD[ndd.displayPixels];
nbm.nLines ← LtoD[ndd.displayLines];
nb.displayX ← do.Box.displayX+
(IF bMode=0 THEN PtoD[ndd.passPixels-dd.passPixels]
ELSE PtoD[(dd.passPixels+dd.displayPixels)-
(ndd.passPixels+ndd.displayPixels)]);
nb.displayY ← do.Box.displayY+
(IF sMode=3 THEN LtoD[ndd.passLines-dd.passLines]
ELSE LtoD[(dd.passLines+dd.displayLines)-
(ndd.passLines+ndd.displayLines)]);
END
ELSE
BEGIN
nbm.nBits ← LtoD[ndd.displayLines];
nbm.nLines ← PtoD[ndd.displayPixels];
nb.displayX ← do.Box.displayX+
(IF sMode=0 THEN LtoD[ndd.passLines-dd.passLines]
ELSE LtoD[(dd.passLines+dd.displayLines)-
(ndd.passLines+ndd.displayLines)]);
nb.displayY ← do.Box.displayY+
(IF bMode=3 THEN PtoD[ndd.passPixels-dd.passPixels]
ELSE PtoD[(dd.passPixels+dd.displayPixels)-
(ndd.passPixels+ndd.displayPixels)]);
END;
do↑ ← newDo;
ReDisplay[do];
END;
END;
--check rotation border
Bounded[do,x,y,-borderWidth*2,borderWidth] =>
BEGIN
xLeft: BOOLEAN ←
CARDINAL[x]<do.Box.displayX+(do.Box.boxBitmap.nBits+borderWidth)/2;
yTop: BOOLEAN ←
CARDINAL[y]<do.Box.displayY+(do.Box.boxBitmap.nLines+borderWidth)/2;
quadrant: CARDINAL ← SELECT TRUE FROM
xLeft AND yTop=>1,
xLeft=>2,
yTop=>0,
ENDCASE=>3;
MakeRotateCursor[quadrant,@Cursor];
GraphicsDefs.MoveBox[@WhiteBox,x-1,y-1];
GraphicsDefs.ReplaceBitmap[@Cursor,0,0,@RealCursor];
IF NOT MouseButtons.Select THEN
BEGIN
bMode: [0..3] ← do.DotsData.mode/4;
sMode: [0..3] ← do.DotsData.mode MOD 4;
GraphicsDefs.RemoveBox[@WhiteBox];
DisplayListDefs.DeleteDisplayItem[@do.Box];
StrawDefs.RestoreGrid[@do.Box]; --must have correct bit counts
IF quadrant = 3 THEN
BEGIN bMode ← Mirror[bMode];sMode ← Mirror[sMode];END
ELSE
BEGIN
THROUGH [0..quadrant] DO
bMode ← R90[bMode];sMode ← R90[sMode];
ENDLOOP;
IF quadrant=0 OR quadrant=2 THEN --flip width, height
BEGIN
t: CARDINAL ← do.Box.boxBitmap.nBits;
do.Box.boxBitmap.nBits ← do.Box.boxBitmap.nLines;
do.Box.boxBitmap.nLines ← t;
END;
END;
do.DotsData.mode ← bMode*4+sMode;
ReDisplay[do];
END;
END;
ENDCASE => --selection area
BEGIN
StrawDefs.NormalCursor[];
GraphicsDefs.RemoveBox[@WhiteBox];
IF NOT MouseButtons.Select THEN EXIT;
END;
--check for Draw button (gray scale adjust)
IF (NOT MouseButtons.Draw) AND KeyWord.Ctrl AND KeyWord.LShift THEN
BEGIN
StrawDefs.NormalCursor[];
GraphicsDefs.RemoveBox[@WhiteBox];
SetGrayLevels[do];
DisplayListDefs.DeleteDisplayItem[@do.Box];
StrawDefs.RestoreGrid[@do.Box]; --must have correct bit counts
ReDisplay[do];
END;
--check non-select button
IF (NOT MouseButtons.Mark) OR (NOT MouseButtons.Draw) OR
(NOT keys.endof[keys]) THEN EXIT;
--update x,y
x ← CursorX↑;
y ← CursorY↑;
ENDLOOP;
GraphicsDefs.DestroyBox[@WhiteBox,TRUE];
SystemDefs.FreeHeapNode[Cursor.bits];
StrawDefs.NormalCursor[];
END;
Mirror: PROCEDURE [mode: [0..3]] RETURNS [[0..3]] = INLINE
BEGIN
RETURN[SELECT mode FROM 0=>1,1=>0,2=>2,ENDCASE=>3];
END;
R90: PROCEDURE [mode: [0..3]] RETURNS [[0..3]] = INLINE
BEGIN
RETURN[SELECT mode FROM 0=>2,1=>3,2=>1,ENDCASE=>0];
END;
ReDisplay: PROCEDURE [do: POINTER TO StrawDefs.DotObject] =
BEGIN
StrawDefs.WaitCursor[];
GraphicsDefs.DestroyBox[@do.Box,FALSE];
do.DotsData.micaWidth ← mc[do.Box.boxBitmap.nBits+1];
do.DotsData.micaHeight ← mc[do.Box.boxBitmap.nLines+1];
do.Object.micaX ← mc[do.Box.displayX];
do.Object.micaY ←
mc[ScreenHeight-(do.Box.displayY+do.Box.boxBitmap.nLines+1)];
StrawDefs.CreateDotsBox[do];
DisplayListDefs.AddDisplayItem[@do.Box];
GraphicsDefs.SetGrayLevel[selectGray];
GraphicsDefs.XorGray[0,0,do.Box.boxBitmap.nBits,do.Box.boxBitmap.nLines,
@do.Box.boxBitmap];
GraphicsDefs.DisplayBox[@do.Box,do.Box.displayX,do.Box.displayY];
StrawDefs.NormalCursor[];
END;
XorBox: PROCEDURE [do: POINTER TO StrawDefs.DotObject] =
BEGIN
xl: CARDINAL ← do.Box.displayX;
xr: CARDINAL ← xl+do.Box.boxBitmap.nBits;
yt: CARDINAL ← do.Box.displayY;
yb: CARDINAL ← yt+do.Box.boxBitmap.nLines;
GraphicsDefs.XorArea[xl,yt,xr,yt];
GraphicsDefs.XorArea[xr,yt,xr,yb];
GraphicsDefs.XorArea[xr,yb,xl,yb];
GraphicsDefs.XorArea[xl,yb,xl,yt];
END;
WindowDots: PUBLIC PROCEDURE [do: POINTER TO StrawDefs.DotObject,
octant: CARDINAL] =
BEGIN
b: POINTER TO GraphicsDefs.Box ← @do.Box;
bm: POINTER TO GraphicsDefs.Bitmap ← @b.boxBitmap;
dx: INTEGER ← b.displayX-CursorX↑;
dy: INTEGER ← b.displayY-CursorY↑;
XorBox[do];
SELECT octant MOD 3 FROM
0=> --left edge
IF INTEGER[bm.nBits+dx] > 0 THEN
BEGIN bm.nBits ← bm.nBits+dx;b.displayX ← b.displayX-dx;END;
2=> --right edge
bm.nBits ← MAX[1,-(dx+1)];
ENDCASE;
SELECT octant/3 FROM
0=> --top edge
IF INTEGER[bm.nLines+dy] > 0 THEN
BEGIN bm.nLines ← bm.nLines+dy;b.displayY ← b.displayY-dy;END;
2=> --bottom edge
bm.nLines ← MAX[1,-(dy+1)];
ENDCASE;
XorBox[do];
END;
StretchEdge: PUBLIC PROCEDURE [do: POINTER TO StrawDefs.DotObject,
octant: CARDINAL] =
BEGIN
b: POINTER TO GraphicsDefs.Box ← @do.Box;
bm: POINTER TO GraphicsDefs.Bitmap ← @b.boxBitmap;
dx: INTEGER ← b.displayX-CursorX↑;
dy: INTEGER ← b.displayY-CursorY↑;
XorBox[do];
SELECT octant FROM
1=> --top edge
IF INTEGER[bm.nLines+dy] > 0 THEN
BEGIN bm.nLines ← bm.nLines+dy;b.displayY ← b.displayY-dy;END;
3=> --left edge
IF INTEGER[bm.nBits+dx] > 0 THEN
BEGIN bm.nBits ← bm.nBits+dx;b.displayX ← b.displayX-dx;END;
5=> --right edge
bm.nBits ← MAX[1,-(dx+1)];
7=> --bottom edge
bm.nLines ← MAX[1,-(dy+1)];
ENDCASE=>ERROR;
XorBox[do];
END;
StretchCorner: PUBLIC PROCEDURE [do: POINTER TO StrawDefs.DotObject,
octant: CARDINAL] =
BEGIN
b: POINTER TO GraphicsDefs.Box ← @do.Box;
bm: POINTER TO GraphicsDefs.Bitmap ← @b.boxBitmap;
xRatio: CARDINAL ← do.DotsData.micaWidth;
yRatio: CARDINAL ← do.DotsData.micaHeight;
calculatedX,calculatedY: INTEGER;
dx,dy: INTEGER;
XorBox[do];
dx ← MAX[1,INTEGER[SELECT octant MOD 3 FROM
0=>b.displayX+bm.nBits+1-CursorX↑,2=>CursorX↑-b.displayX,ENDCASE=>ERROR]];
dy ← MAX[1,INTEGER[SELECT octant/3 FROM
0=>b.displayY+bm.nLines+1-CursorY↑,2=>CursorY↑-b.displayY,ENDCASE=>ERROR]];
calculatedX ← PressDefs.MulDiv[dy,xRatio,yRatio];
calculatedY ← PressDefs.MulDiv[dx,yRatio,xRatio];
IF ABS[calculatedX-dx] > ABS[calculatedY-dy]
THEN dy ← calculatedY ELSE dx ← calculatedX;
IF octant MOD 3 = 0 THEN b.displayX ← b.displayX-(dx-bm.nBits);
IF octant/3 = 0 THEN b.displayY ← b.displayY-(dy-bm.nLines);
bm.nBits ← dx;
bm.nLines ← dy;
XorBox[do];
END;
MakeRotateCursor: PROCEDURE [quadrant: CARDINAL,cursor: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
IF quadrant=3 THEN --mirror icon
BEGIN
MakeArrow[2,7,13,7,FALSE,cursor];
GraphicsDefs.PutArea[7,1,8,14,cursor];
RETURN;
END;
GraphicsDefs.EraseArea[0,0,16,16,cursor];
GraphicsDefs.PutArea[4,4,11,5,cursor];
IF quadrant>0 THEN GraphicsDefs.PutArea[4,4,5,11,cursor];
IF quadrant>1 THEN GraphicsDefs.PutArea[4,10,11,11,cursor];
SELECT quadrant FROM
0=>
BEGIN
GraphicsDefs.PutArea[5,3,5,6,cursor];
GraphicsDefs.PutArea[6,2,6,7,cursor];
END;
1=>
BEGIN
GraphicsDefs.PutArea[2,9,7,9,cursor];
GraphicsDefs.PutArea[3,10,6,10,cursor];
END;
ENDCASE=>
BEGIN
GraphicsDefs.PutArea[9,8,9,13,cursor];
GraphicsDefs.PutArea[10,9,10,12,cursor];
END;
END;
MakeArrow: PROCEDURE [x1,y1,x2,y2: CARDINAL,box: BOOLEAN,cursor: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
GraphicsDefs.EraseArea[0,0,16,16,cursor];
SELECT TRUE FROM
x1 = x2 => --vertical
BEGIN
t: CARDINAL;
IF y1 > y2 THEN BEGIN t ← y1;y1 ← y2;y2 ← t;END;
GraphicsDefs.PutArea[x1,y1,x1+1,y2,cursor];
GraphicsDefs.PutArea[x1-1,y1+1,x1+2,y1+1,cursor];
GraphicsDefs.PutArea[x1-2,y1+2,x1+3,y1+2,cursor];
GraphicsDefs.PutArea[x1-1,y2-1,x1+2,y2-1,cursor];
GraphicsDefs.PutArea[x1-2,y2-2,x1+3,y2-2,cursor];
END;
y1 = y2 => --horizontal
BEGIN
t: CARDINAL;
IF x1 > x2 THEN BEGIN t ← x1;x1 ← x2;x2 ← t;END;
GraphicsDefs.PutArea[x1,y1,x2,y1+1,cursor];
GraphicsDefs.PutArea[x1+1,y1-1,x1+1,y1+2,cursor];
GraphicsDefs.PutArea[x1+2,y1-2,x1+2,y1+3,cursor];
GraphicsDefs.PutArea[x2-1,y1-1,x2-1,y1+2,cursor];
GraphicsDefs.PutArea[x2-2,y1-2,x2-2,y1+3,cursor];
END;
ENDCASE => --diagonal
BEGIN
dx: INTEGER ← IF x1<x2 THEN 1 ELSE -1;
dy: INTEGER ← IF y1<y2 THEN 1 ELSE -1;
GraphicsDefs.PutLine[x1,y1,x2,y2,cursor];
GraphicsDefs.PutLine[x1+dx,y1,x2,y2-dy,cursor];
GraphicsDefs.PutLine[x1,y1+dy,x2-dx,y2,cursor];
GraphicsDefs.PutLine[x1,y1,x1+4*dx,y1,cursor];
GraphicsDefs.PutLine[x2-4*dx,y2,x2,y2,cursor];
GraphicsDefs.PutLine[x1,y1,x1,y1+4*dy,cursor];
GraphicsDefs.PutLine[x2,y2-4*dy,x2,y2,cursor];
END;
IF box THEN
BEGIN
GraphicsDefs.PutLine[4,4,4,11,cursor];
GraphicsDefs.PutLine[4,11,11,11,cursor];
GraphicsDefs.PutLine[11,11,11,4,cursor];
GraphicsDefs.PutLine[11,4,4,4,cursor];
END;
END;
Bounded: PROCEDURE [do: POINTER TO StrawDefs.DotObject,x,y: INTEGER,
lowBound,border: INTEGER] RETURNS [BOOLEAN] =
BEGIN
highBound: INTEGER ← lowBound+border;
lx: INTEGER ← do.Box.displayX-highBound;
ty: INTEGER ← do.Box.displayY-highBound;
rx: INTEGER ← do.Box.displayX+do.Box.boxBitmap.nBits-1+highBound-border;
by: INTEGER ← do.Box.displayY+do.Box.boxBitmap.nLines-1+highBound-border;
IF x IN [lx..lx+border] AND y IN [ty..by] THEN RETURN[TRUE]; --left edge
IF x IN [rx-border..rx] AND y IN [ty..by] THEN RETURN[TRUE]; --right edge
IF x IN [lx..rx] AND y IN [ty..ty+border] THEN RETURN[TRUE]; --top edge
IF x IN [lx..rx] AND y IN [by-border..by] THEN RETURN[TRUE]; --bottom edge
RETURN[FALSE];
END;
--adjust gray scale range routines
SetGrayLevels: PROCEDURE [do: POINTER TO StrawDefs.DotObject] =
BEGIN
x: CARDINAL;
AdjustBox: GraphicsDefs.Box;
AdjustBitmap: POINTER TO GraphicsDefs.Bitmap ← @AdjustBox.boxBitmap;
minSep: INTEGER ← 2;
xOffset: INTEGER ← 8;
eraseBoolean: BOOLEAN = TRUE;
black,white,blackX,whiteX: INTEGER;
blackTop,whiteTop: BOOLEAN;
source: PACKED ARRAY [0..256) OF [0..377B];
MakeRect: PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
GraphicsDefs.ReplaceArea[x1,y1,x1,y2,AdjustBitmap];
GraphicsDefs.ReplaceArea[x1,y2,x2,y2,AdjustBitmap];
GraphicsDefs.ReplaceArea[x2,y2,x2,y1,AdjustBitmap];
GraphicsDefs.ReplaceArea[x2,y1,x1,y1,AdjustBitmap];
END;
XorMarks: PROCEDURE =
BEGIN
blackY: CARDINAL ← IF blackTop THEN 16 ELSE 32;
whiteY: CARDINAL ← IF whiteTop THEN 16 ELSE 32;
IF blackTop THEN
GraphicsDefs.XorArea[blackX-7,blackY+8,blackX-1,blackY+15,AdjustBitmap]
ELSE
GraphicsDefs.XorArea[blackX-7,blackY,blackX-1,blackY+7,AdjustBitmap];
GraphicsDefs.XorArea[blackX,blackY,blackX,blackY+15,AdjustBitmap];
IF whiteTop THEN
BEGIN
GraphicsDefs.XorArea[whiteX+1,whiteY+8,whiteX+7,whiteY+15,AdjustBitmap];
GraphicsDefs.XorArea[whiteX+1,whiteY+9,whiteX+6,whiteY+14,AdjustBitmap];
END
ELSE
BEGIN
GraphicsDefs.XorArea[whiteX+1,whiteY,whiteX+7,whiteY+7,AdjustBitmap];
GraphicsDefs.XorArea[whiteX+1,whiteY+1,whiteX+6,whiteY+6,AdjustBitmap];
END;
GraphicsDefs.XorArea[whiteX,whiteY,whiteX,whiteY+15,AdjustBitmap];
END;
SetBlackWhite: PROCEDURE =
BEGIN
SELECT TRUE FROM
blackTop AND whiteTop =>
BEGIN
white ← 255+PressDefs.MulDiv[255-(whiteX-xOffset),255,whiteX-blackX];
black ← -PressDefs.MulDiv[blackX-xOffset,255,whiteX-blackX];
END;
blackTop =>
BEGIN
white ← whiteX - xOffset;
black ← white-PressDefs.MulDiv[255,white,255-(blackX-xOffset)];
IF black > 255 THEN black ← -32000; --overflow on MulDiv
END;
whiteTop =>
BEGIN
black ← blackX - xOffset;
white ← black+PressDefs.MulDiv[255-black,255,(whiteX-xOffset)];
IF white < 0 THEN white ← 32000; --overflow on MulDiv
END;
ENDCASE =>
BEGIN
black ← blackX - xOffset;
white ← whiteX - xOffset;
END;
IF white <= black THEN ERROR;
GraphicsDefs.EraseArea[xOffset,48+1,xOffset+255,48+14,AdjustBitmap];
HalftoneDefs.InitHalftone[xOffset,48+1,256,256,black,white,AdjustBitmap,1,14];
[] ← HalftoneDefs.PrintHalftoneLine[@source];
XorMarks[];
GraphicsDefs.MoveBox[@AdjustBox,AdjustBox.displayX,AdjustBox.displayY];
END;
BlackAdjust: PROCEDURE =
BEGIN
x: INTEGER ← CursorX↑-AdjustBox.displayX;
XorMarks[];
blackX ← MIN[254,MAX[0,x-xOffset]]+xOffset;
SELECT (CursorY↑-AdjustBox.displayY)/16 FROM
1=> --top adjust
BEGIN
IF whiteTop THEN
IF whiteX-minSep < blackX THEN
BEGIN
blackX ← MIN[(255-minSep)+xOffset,blackX];
whiteX ← blackX+minSep;
END;
blackTop ← TRUE;
SetBlackWhite[];
END;
2=> --bottom adjust
BEGIN
IF NOT whiteTop THEN
IF whiteX <= blackX THEN whiteX ← blackX+1;
blackTop ← FALSE;
SetBlackWhite[];
END;
ENDCASE => XorMarks[];
END;
WhiteAdjust: PROCEDURE =
BEGIN
x: INTEGER ← CursorX↑-AdjustBox.displayX;
XorMarks[];
whiteX ← MIN[255,MAX[1,x-xOffset]]+xOffset;
SELECT (CursorY↑-AdjustBox.displayY)/16 FROM
1=> --top adjust
BEGIN
IF blackTop THEN
IF blackX+minSep > whiteX THEN
BEGIN
whiteX ← MAX[minSep+xOffset,whiteX];
blackX ← whiteX-minSep;
END;
whiteTop ← TRUE;
SetBlackWhite[];
END;
2=> --bottom adjust
BEGIN
IF NOT blackTop THEN
IF blackX >= whiteX THEN blackX ← whiteX-1;
whiteTop ← FALSE;
SetBlackWhite[];
END;
ENDCASE => XorMarks[];
END;
SetBlackXWhiteX: PROCEDURE =
BEGIN
SELECT TRUE FROM
blackTop AND whiteTop =>
BEGIN
blackX ← 255 - PressDefs.MulDiv[white,255,white-black] + xOffset;
whiteX ← PressDefs.MulDiv[255-black,255,white-black] + xOffset;
END;
blackTop =>
BEGIN
whiteX ← white + xOffset;
blackX ← 255 - PressDefs.MulDiv[white,255,white-black] + xOffset;
END;
whiteTop =>
BEGIN
blackX ← black + xOffset;
whiteX ← PressDefs.MulDiv[255-black,255,white-black] + xOffset;
END;
ENDCASE =>
BEGIN
blackX ← black + xOffset;
whiteX ← white + xOffset;
END;
END;
--set up global variables
black ← do.DotsData.min;
white ← do.DotsData.max;
blackTop ← black < 0;
whiteTop ← white > 255;
SetBlackXWhiteX[];
--talk to user
FOR x IN [0..256) DO source[x] ← x;ENDLOOP;
GraphicsDefs.CreateBox[@AdjustBox,256+16,16*6];
MakeRect[0,0,256+16-1,16*6-1,AdjustBitmap];
MakeRect[xOffset-1,0,xOffset+256,15,AdjustBitmap];
MakeRect[xOffset-1,48,xOffset+256,48+15,AdjustBitmap];
HalftoneDefs.InitHalftone[xOffset,1,256,256,0,255,AdjustBitmap,1,14];
[] ← HalftoneDefs.PrintHalftoneLine[@source];
HalftoneDefs.InitHalftone[xOffset,48+1,256,256,black,white,AdjustBitmap,1,14];
[] ← HalftoneDefs.PrintHalftoneLine[@source];
XorMarks[];
GraphicsDefs.DisplayBox[@AdjustBox,CursorX↑-272/2,CursorY↑-16*6/2];
WHILE GraphicsDefs.CursorInBox[@AdjustBox] DO
BEGIN
x: INTEGER ← CursorX↑-AdjustBox.displayX;
IF MouseButtons.Mark THEN LOOP;
SELECT (CursorY↑-AdjustBox.displayY)/16 FROM
0=> LOOP; --full range display
1=> --top adjust
BEGIN
IF blackTop THEN
BEGIN
IF x IN [blackX-8..blackX] THEN
BEGIN
WHILE NOT MouseButtons.Mark DO BlackAdjust[];ENDLOOP;
LOOP;
END;
END;
IF whiteTop THEN
BEGIN
IF x IN [whiteX..whiteX+8] THEN
BEGIN
WHILE NOT MouseButtons.Mark DO WhiteAdjust[];ENDLOOP;
LOOP;
END;
END;
END;
2=> --bottom adjust
BEGIN
IF NOT blackTop THEN
BEGIN
IF x IN [blackX-8..blackX] THEN
BEGIN
WHILE NOT MouseButtons.Mark DO BlackAdjust[];ENDLOOP;
LOOP;
END;
END;
IF NOT whiteTop THEN
BEGIN
IF x IN [whiteX..whiteX+8] THEN
BEGIN
WHILE NOT MouseButtons.Mark DO WhiteAdjust[];ENDLOOP;
LOOP;
END;
END;
END;
ENDCASE=> LOOP; --nothing
END;
ENDLOOP;
do.DotsData.min ← black;
do.DotsData.max ← white;
GraphicsDefs.DestroyBox[@AdjustBox,TRUE];
END;
END.