![]() |
back to part-1 |
Drawing in Delphi (part 2) : the XBitmap Class | ![]() |
![]() |
![]() |
![]() |
![]() |
procedure TXBitmap.setPenwidth(w : byte);
//make pen image
var i,j : byte;
h,v,r,r2 : single;
mask : DWORD;
begin
if w = FXpenwidth then exit;
if w > 32 then w := 32;
FXpenwidth := w;
FXpenBias := (w-1) shr 1;
//------- make pen image --------------------
for i := 0 to 31 do FXpen[i] := 0;//erase pen
r := w/2;
r2 := r * r;
for j := 0 to (w-1) shr 1 do // j is vertical movement over half height
begin
v := r - (0.5 + j);
for i := 0 to (w-1) shr 1 do // i is horizontal movement over half width
begin
h := r - (0.5 + i);
if h*h + v*v <= r2 then // pythagoras lemma
begin
mask := 1 shl i;
mask := mask or (1 shl (w-i-1)); // horizontal copy bit
FXpen[j] := FXpen[j] or mask; // set bits
FXpen[w-j-1] := FXpen[w-j-1] or mask; // vertical copy bits
end;//if
end;//for i
end;//for j
end;
|
![]() |
procedure TXBitmap.XDot(x,y : integer);
begin
Dot(x,y);
makeModRect(x,y,x,y,(FXPenwidth shr 1)+2);
end;
procedure TXBitmap.Dot(x,y : integer);
//write a single dot,
//use FXpenwidth,Xcliprect,Xlevel,FXpencolor
var i,j : byte;
bitmask,pline : DWORD;
p : PDW; //PDW is pointer to DWORD
xi,yj : integer;
begin
x := x - FXpenBias;
y := y - FXpenBias;
for j := 0 to FXpenwidth-1 do
begin
bitmask := 1;
yj := y + j;
if (yj < FXcliprect.top) or (yj >= FXcliprect.bottom) then continue;
pline := FXpbase-FXlineStep*(yj); //pline points to 1st DWORD of row
for i := 0 to FXpenWidth-1 do
begin
xi := x + i;
if (xi >= FXcliprect.left) and (xi < FXcliprect.right) then
begin
p := PDW(pline + (xi) shl 2); //p points to pixel
if (FXpen[j] and bitmask) <> 0 then
if FXpenlevel <= (p^ and $3) then p^ := FXpencolor;
end;
bitmask := bitmask shl 1;
end;//for i
end;//for j
end;
|
![]() |
//preset
const linepattern : array[0..19] of word = //dash - dot patterns
($ffff,$aaaa,$cccc,$eeee,$f0f0,
$f8f8,$fcfc,$fefe,$8888,$c0c0,
$e0e0,$ff00,$8080,$bebe,$9c9c,
$dede,$ff18,$ff88,$ffe4,$fffa);
|
![]() |
procedure TXBitmap.Xline(x1,y1,x2,y2 : integer);
//paint line from (x1,y1) to (x2,y2);
//use xpenwidth,xpenstyle,xlevel,cliprect
var dx,dy,ipen,x,y,w,PL,PD,PBX,PBY : single;
steps,i : word;
beginpijl,eindpijl : boolean;
PA,PB : array[0..2] of TPoint;
PLX,PLY : smallInt;
begin
dx := x2-x1; dy := y2 - y1;
if (dx = 0) and (dy = 0) then
begin
XDot(x1,y1); //make modrect
exit;
end;
beginpijl := (FXArrowCode and $40) <> 0; //begin-arrow
eindpijl := (FXArrowCode and $80) <> 0; //end-arrow
if beginpijl or eindpijl then
begin
w := sqrt(dx*dx+dy*dy);
pijldimensions(PL,PD); //get arrow dimensions PL, PD
eindpijl := eindpijl and (1.2*PL < w);
beginpijl := beginpijl and (2.2*PL < w);
w := 1/w;
PLX := trunc(PL*dx*w+0.5);
PLY := trunc(PL*dy*w+0.5); //arrow length
PBX := PD*dy*w;
PBY := PD*dx*w; //arrow width
end;
i := (FXPenwidth shr 1)+ 2;
if (beginPijl or EindPijl) then inc(i,trunc(PD+1));
makeModRect(x1,y1,x2,y2,i);
if beginpijl then
begin
PA[0].x := x1; x1 := x1 + PLX;
pa[1].x := trunc(x1+PBX+0.5);
pa[2].x := trunc(x1-PBX+0.5);
pa[0].y := y1; y1 := y1 + PLY;
pa[1].y := trunc(y1-PBY+0.5);
pa[2].y := trunc(y1+PBY+0.5);
end;
if eindpijl then
begin
pb[0].x := x2; x2 := x2-PLX;
pb[1].x := trunc(x2 + PBX+0.5);
pb[2].x := trunc(x2 - PBX+0.5);
pb[0].y := y2; y2 := y2 - PLY;
pb[1].y := trunc(y2 - PBY+0.5);
pb[2].y := trunc(y2 + PBY+0.5);
end;
dx := x2-x1; dy := y2 - y1; //must recalculate dx,dy
if abs(dy) <= abs(dx) then
begin //hor. orientation
steps := abs(trunc(dx)); dy := dy/steps;
if dx > 0 then dx := 1 else dx := -1;
end
else begin //vert orientation
steps := abs(trunc(dy)); dx := dx/steps;
if dy > 0 then dy := 1 else dy := -1;
end;
ipen := 1/fxpenwidth;
x := x1; y := y1;
for i := 0 to steps do
begin
if ((($8000 shr (trunc(i*ipen) and $f)) and FXlinePattern) <> 0) and
((($8000 shr (trunc(i*ipen + 0.9) and $f)) and FXlinePattern) <> 0) then
Dot(x1,y1);
x := x + dx; x1 := trunc(x + 0.5);
y := y + dy; y1 := trunc(y + 0.5);
end;
if beginpijl then Polygon1(pa);
if eindpijl then Polygon1(pb);
end;
|
![]() |
