mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-07 13:10:34 +02:00
* made floodfill a *LOT* faster (better DrawnPoints management)
This commit is contained in:
parent
96b6cdedae
commit
0e4fe19488
@ -95,7 +95,7 @@ type
|
||||
If (frac(x)<0) then dec(t);
|
||||
floor := t;
|
||||
end;
|
||||
|
||||
(*
|
||||
{ simple descriptive name }
|
||||
function max(a, b : graph_int) : graph_int;
|
||||
begin
|
||||
@ -109,7 +109,7 @@ type
|
||||
if (a <= b) then min := a
|
||||
else min := b;
|
||||
end;
|
||||
|
||||
*)
|
||||
{ needed for the compare functions; should NOT be used for anything else }
|
||||
var
|
||||
ptable : ppointarray; { pointer to points list }
|
||||
@ -273,19 +273,24 @@ begin
|
||||
DrawPoly(NumPoints, PolyPoints);
|
||||
end;
|
||||
|
||||
|
||||
{ maximum supported Y resultion }
|
||||
const
|
||||
MaxYRes = 2048;
|
||||
{ changing this to 1 or 2 doesn't improve performance noticably }
|
||||
YResDiv = 4;
|
||||
|
||||
type
|
||||
PFloodLine = ^TFloodLine;
|
||||
TFloodLine = record
|
||||
next: PFloodLine;
|
||||
x1 : smallint;
|
||||
x2 : smallint;
|
||||
y : smallint;
|
||||
end;
|
||||
|
||||
TDrawnList = Array[0..StdBuffersize] of TFloodLine;
|
||||
TDrawnList = Array[0..(MaxYRes - 1) div 4] of PFloodLine;
|
||||
|
||||
var
|
||||
DrawnIndex : Word;
|
||||
DrawnList : TDrawnList;
|
||||
Buffer : Record { Union for byte and word addressing of buffer }
|
||||
ByteIndex : Word;
|
||||
@ -346,11 +351,14 @@ var
|
||||
{ Y axis, from the x1 to x2 coordinates. }
|
||||
{********************************************************}
|
||||
Procedure AddLinePoints(x1,x2,y: smallint);
|
||||
var temp: PFloodLine;
|
||||
begin
|
||||
DrawnList[DrawnIndex].x1 := x1;
|
||||
DrawnList[DrawnIndex].x2 := x2;
|
||||
DrawnList[DrawnIndex].y := y;
|
||||
Inc(DrawnIndex);
|
||||
new(temp);
|
||||
temp^.x1 := x1;
|
||||
temp^.x2 := x2;
|
||||
temp^.y := y;
|
||||
temp^.next := DrawnList[y div YResDiv];
|
||||
DrawnList[y div YResDiv] := temp;
|
||||
end;
|
||||
|
||||
{********************************************************}
|
||||
@ -366,28 +374,46 @@ var
|
||||
{ to draw, otherwise returns FALSE. }
|
||||
{********************************************************}
|
||||
Function AlreadyDrawn(x, y: smallint): boolean;
|
||||
var
|
||||
LocalIndex : smallint;
|
||||
var
|
||||
temp : PFloodLine;
|
||||
begin
|
||||
AlreadyDrawn := FALSE;
|
||||
LocalIndex := 0;
|
||||
while LocalIndex < DrawnIndex do
|
||||
Begin
|
||||
{ if vertical val is equal to our y point ... }
|
||||
if DrawnList[LocalIndex].y = y then
|
||||
Begin
|
||||
{ then check if x >< ... }
|
||||
if (x >= DrawnList[LocalIndex].x1) and
|
||||
(x <= DrawnList[LocalIndex].x2) then
|
||||
Begin
|
||||
AlreadyDrawn := TRUE;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
Inc(LocalIndex);
|
||||
end;
|
||||
AlreadyDrawn := false;
|
||||
temp := DrawnList[y div YResDiv];
|
||||
while assigned(temp) do
|
||||
begin
|
||||
if (temp^.y = y) and
|
||||
(temp^.x1 <= x) and
|
||||
(temp^.x2 >= x) then
|
||||
begin
|
||||
AlreadyDrawn := true;
|
||||
exit;
|
||||
end;
|
||||
temp := temp^.next;
|
||||
end;
|
||||
end;
|
||||
|
||||
{********************************************************}
|
||||
{ Procedure CleanUpDrawnList }
|
||||
{--------------------------------------------------------}
|
||||
{ removes all elements from the DrawnList. Doesn't init }
|
||||
{ elements of it with NILL }
|
||||
{********************************************************}
|
||||
Procedure CleanUpDrawnList;
|
||||
var
|
||||
l: longint;
|
||||
temp1, temp2: PFloodLine;
|
||||
begin
|
||||
for l := 0 to high(DrawnList) do
|
||||
begin
|
||||
temp1 := DrawnList[l];
|
||||
while assigned(temp1) do
|
||||
begin
|
||||
temp2 := temp1;
|
||||
temp1 := temp1^.next;
|
||||
dispose(temp2);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure FloodFill (x, y : smallint; Border: word);
|
||||
{********************************************************}
|
||||
@ -407,6 +433,7 @@ var
|
||||
x1, x2, prevy: smallint;
|
||||
Index : smallint;
|
||||
Begin
|
||||
FillChar(DrawnList,sizeof(DrawnList),0);
|
||||
{ init prevy }
|
||||
prevy := 32767;
|
||||
{ Save current drawing color }
|
||||
@ -425,8 +452,6 @@ var
|
||||
(x>ViewWidth) Or (y>ViewHeight) then Exit;
|
||||
{ Some internal variables }
|
||||
Index := 0;
|
||||
{ Index of segments to draw }
|
||||
DrawnIndex := 0;
|
||||
{ Index of points to check }
|
||||
Buffer.WordIndex:=0;
|
||||
PushPoint (x,y);
|
||||
@ -434,25 +459,35 @@ var
|
||||
Begin
|
||||
PopPoint (x,y);
|
||||
{ Get the complete lines for the following }
|
||||
If (prevy - y = 1) then
|
||||
{ previous line was one below the new one, so the previous s2 }
|
||||
{ = new s1 }
|
||||
Begin
|
||||
stemp := s1;
|
||||
s1 := s2;
|
||||
s2 := stemp;
|
||||
End
|
||||
Else If (y - prevy = 1) then
|
||||
{ previous line was one above the new one, so the previous s3 }
|
||||
{ = new s1 }
|
||||
Begin
|
||||
stemp := s1;
|
||||
s1 := s3;
|
||||
s3 := stemp;
|
||||
End
|
||||
Else GetScanline(0,ViewWidth,y,s1^);
|
||||
GetScanline(0,ViewWidth,y-1,s2^);
|
||||
GetScanline(0,ViewWidth,y+1,s3^);
|
||||
If y <> prevy then
|
||||
begin
|
||||
If (prevy - y = 1) then
|
||||
{ previous line was one below the new one, so the previous s2 }
|
||||
{ = new s1 }
|
||||
Begin
|
||||
stemp := s3;
|
||||
s3 := s1;
|
||||
s1 := s2;
|
||||
s2 := stemp;
|
||||
GetScanline(0,ViewWidth,y-1,s2^);
|
||||
End
|
||||
Else If (y - prevy = 1) then
|
||||
{ previous line was one above the new one, so the previous s3 }
|
||||
{ = new s1 }
|
||||
Begin
|
||||
stemp := s2;
|
||||
s2 := s1;
|
||||
s1 := s3;
|
||||
s3 := stemp;
|
||||
GetScanline(0,ViewWidth,y+1,s3^);
|
||||
End
|
||||
Else
|
||||
begin
|
||||
GetScanline(0,ViewWidth,y-1,s2^);
|
||||
GetScanline(0,ViewWidth,y,s1^);
|
||||
GetScanline(0,ViewWidth,y+1,s3^);
|
||||
end;
|
||||
end;
|
||||
prevy := y;
|
||||
{ check the current scan line }
|
||||
While (s1^[x]<>Border) And (x<=ViewWidth) Do Inc (x);
|
||||
@ -504,12 +539,16 @@ var
|
||||
FreeMem (s1,(ViewWidth+1)*2);
|
||||
FreeMem (s2,(ViewWidth+1)*2);
|
||||
FreeMem (s3,(ViewWidth+1)*2);
|
||||
CleanUpDrawnList;
|
||||
CurrentColor := BackUpColor;
|
||||
End;
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.13 1999-12-20 11:22:36 peter
|
||||
Revision 1.14 2000-01-02 19:01:32 jonas
|
||||
* made floodfill a *LOT* faster (better DrawnPoints management)
|
||||
|
||||
Revision 1.13 1999/12/20 11:22:36 peter
|
||||
* integer -> smallint to overcome -S2 switch needed for ggi version
|
||||
|
||||
Revision 1.12 1999/12/11 23:41:38 jonas
|
||||
|
Loading…
Reference in New Issue
Block a user