2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS win32 subsystem
4 * PURPOSE: Flood filling support
5 * FILE: subsystems/win32/win32k/dib/floodfill.c
6 * PROGRAMMER: Gregor Schneider, <grschneider AT gmail DOT com>
15 * This floodfill algorithm is an iterative four neighbors version. It works with an internal stack like data structure.
16 * The stack is kept in an array, sized for the worst case scenario of having to add all pixels of the surface.
17 * This avoids having to allocate and free memory blocks all the time. The stack grows from the end of the array towards the start.
18 * All pixels are checked before being added, against belonging to the fill rule (FLOODFILLBORDER or FLOODFILLSURFACE)
19 * and the position in respect to the clip region. This guarantees all pixels lying on the stack belong to the filled surface.
20 * Further optimisations of the algorithm are possible.
23 /* Floodfil helper structures and functions */
24 typedef struct _floodItem
30 typedef struct _floodInfo
33 FLOODITEM
*floodStart
;
37 static __inline BOOL
initFlood(FLOODINFO
*info
, RECTL
*DstRect
)
39 ULONG width
= DstRect
->right
- DstRect
->left
;
40 ULONG height
= DstRect
->bottom
- DstRect
->top
;
41 info
->floodData
= ExAllocatePoolWithTag(NonPagedPool
, width
* height
* sizeof(FLOODITEM
), TAG_DIB
);
42 if (info
->floodData
== NULL
)
46 info
->floodStart
= info
->floodData
+ (width
* height
);
47 DPRINT("Allocated flood stack from %p to %p\n", info
->floodData
, info
->floodStart
);
50 static __inline VOID
finalizeFlood(FLOODINFO
*info
)
52 ExFreePoolWithTag(info
->floodData
, TAG_DIB
);
54 static __inline VOID
addItemFlood(FLOODINFO
*info
,
62 if (x
>= DstRect
->left
&& x
<= DstRect
->right
&&
63 y
>= DstRect
->top
&& y
<= DstRect
->bottom
)
66 DibFunctionsForBitmapFormat
[DstSurf
->iBitmapFormat
].DIB_GetPixel(DstSurf
, x
, y
) != Color
)
70 else if (isSurf
== FALSE
&&
71 DibFunctionsForBitmapFormat
[DstSurf
->iBitmapFormat
].DIB_GetPixel(DstSurf
, x
, y
) == Color
)
76 info
->floodStart
->x
= x
;
77 info
->floodStart
->y
= y
;
81 static __inline VOID
removeItemFlood(FLOODINFO
*info
)
87 BOOLEAN
DIB_XXBPP_FloodFillSolid(SURFOBJ
*DstSurf
,
96 FLOODINFO flood
= {0, NULL
, NULL
};
98 BrushColor
= Brush
->iSolidColor
;
102 if (FillType
== FLOODFILLBORDER
)
104 /* Check if the start pixel has the border color */
105 if (DibFunctionsForBitmapFormat
[DstSurf
->iBitmapFormat
].DIB_GetPixel(DstSurf
, x
, y
) == ConvColor
)
110 if (initFlood(&flood
, DstRect
) == FALSE
)
114 addItemFlood(&flood
, x
, y
, DstSurf
, DstRect
, ConvColor
, FALSE
);
115 while (flood
.floodLen
!= 0)
117 x
= flood
.floodStart
->x
;
118 y
= flood
.floodStart
->y
;
119 removeItemFlood(&flood
);
121 DibFunctionsForBitmapFormat
[DstSurf
->iBitmapFormat
].DIB_PutPixel(DstSurf
, x
, y
, BrushColor
);
122 if (flood
.floodStart
- 4 < flood
.floodData
)
124 DPRINT1("Can't finish flooding!\n");
125 finalizeFlood(&flood
);
128 addItemFlood(&flood
, x
, y
+ 1, DstSurf
, DstRect
, ConvColor
, FALSE
);
129 addItemFlood(&flood
, x
, y
- 1, DstSurf
, DstRect
, ConvColor
, FALSE
);
130 addItemFlood(&flood
, x
+ 1, y
, DstSurf
, DstRect
, ConvColor
, FALSE
);
131 addItemFlood(&flood
, x
- 1, y
, DstSurf
, DstRect
, ConvColor
, FALSE
);
133 finalizeFlood(&flood
);
135 else if (FillType
== FLOODFILLSURFACE
)
137 /* Check if the start pixel has the surface color */
138 if (DibFunctionsForBitmapFormat
[DstSurf
->iBitmapFormat
].DIB_GetPixel(DstSurf
, x
, y
) != ConvColor
)
143 if (initFlood(&flood
, DstRect
) == FALSE
)
147 addItemFlood(&flood
, x
, y
, DstSurf
, DstRect
, ConvColor
, TRUE
);
148 while (flood
.floodLen
!= 0)
150 x
= flood
.floodStart
->x
;
151 y
= flood
.floodStart
->y
;
152 removeItemFlood(&flood
);
154 DibFunctionsForBitmapFormat
[DstSurf
->iBitmapFormat
].DIB_PutPixel(DstSurf
, x
, y
, BrushColor
);
155 if (flood
.floodStart
- 4 < flood
.floodData
)
157 DPRINT1("Can't finish flooding!\n");
158 finalizeFlood(&flood
);
161 addItemFlood(&flood
, x
, y
+ 1, DstSurf
, DstRect
, ConvColor
, TRUE
);
162 addItemFlood(&flood
, x
, y
- 1, DstSurf
, DstRect
, ConvColor
, TRUE
);
163 addItemFlood(&flood
, x
+ 1, y
, DstSurf
, DstRect
, ConvColor
, TRUE
);
164 addItemFlood(&flood
, x
- 1, y
, DstSurf
, DstRect
, ConvColor
, TRUE
);
166 finalizeFlood(&flood
);
170 DPRINT1("Unsupported FloodFill type!\n");