FloodFill:

-Get rid of global variables for flood control
-Translate the provided color to the surface, not the other way around (improves speed)
-Rename the function to reflect the functionality
-Add comments on how to implement support for hatched brushes and non-standard surfaces
-Thanks to tkreuzer for feedback

svn path=/trunk/; revision=42323
This commit is contained in:
Gregor Schneider 2009-08-01 14:39:40 +00:00
parent f8ffccf7de
commit c152d5480d
3 changed files with 80 additions and 71 deletions

View file

@ -133,7 +133,7 @@ BOOLEAN DIB_32BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
BOOLEAN DIB_32BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ*,SURFOBJ*,SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,XLATEOBJ*,XLATEOBJ*,ROP4);
BOOLEAN DIB_XXBPP_FloodFill(SURFOBJ*, BRUSHOBJ*, RECTL*, POINTL*, XLATEOBJ*, COLORREF, UINT);
BOOLEAN DIB_XXBPP_FloodFillSolid(SURFOBJ*, BRUSHOBJ*, RECTL*, POINTL*, ULONG, UINT);
extern unsigned char notmask[2];
extern unsigned char altnotmask[2];

View file

@ -27,76 +27,72 @@ typedef struct _floodItem
ULONG y;
} FLOODITEM;
static ULONG floodLen = 0;
static FLOODITEM *floodStart = NULL, *floodData = NULL;
typedef struct _floodInfo
{
ULONG floodLen;
FLOODITEM *floodStart;
FLOODITEM *floodData;
} FLOODINFO;
static __inline BOOL initFlood(RECTL *DstRect)
static __inline BOOL initFlood(FLOODINFO *info, RECTL *DstRect)
{
ULONG width = DstRect->right - DstRect->left;
ULONG height = DstRect->bottom - DstRect->top;
floodData = ExAllocatePoolWithTag(NonPagedPool, width * height * sizeof(FLOODITEM), TAG_DIB);
if (floodData == NULL)
info->floodData = ExAllocatePoolWithTag(NonPagedPool, width * height * sizeof(FLOODITEM), TAG_DIB);
if (info->floodData == NULL)
{
return FALSE;
}
floodStart = (FLOODITEM*)((PBYTE)floodData + (width * height * sizeof(FLOODITEM)));
info->floodStart = (FLOODITEM*)((PBYTE)info->floodData + (width * height * sizeof(FLOODITEM)));
return TRUE;
}
static __inline VOID finalizeFlood()
static __inline VOID finalizeFlood(FLOODINFO *info)
{
ExFreePoolWithTag(floodData, TAG_DIB);
ExFreePoolWithTag(info->floodData, TAG_DIB);
}
static __inline VOID addItemFlood(ULONG x,
static __inline VOID addItemFlood(FLOODINFO *info,
ULONG x,
ULONG y,
SURFOBJ *DstSurf,
RECTL *DstRect,
XLATEOBJ* ColorTranslation,
COLORREF Color,
ULONG Color,
BOOL isSurf)
{
if (x >= DstRect->left && x <= DstRect->right &&
y >= DstRect->top && y <= DstRect->bottom)
{
if (isSurf == TRUE && XLATEOBJ_iXlate(ColorTranslation,
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) != Color)
if (isSurf == TRUE &&
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) != Color)
{
return;
}
else if (isSurf == FALSE && XLATEOBJ_iXlate(ColorTranslation,
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) == Color)
else if (isSurf == FALSE &&
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) == Color)
{
return;
}
floodStart--;
floodStart->x = x;
floodStart->y = y;
floodLen++;
info->floodStart--;
info->floodStart->x = x;
info->floodStart->y = y;
info->floodLen++;
}
}
static __inline VOID removeItemFlood()
static __inline VOID removeItemFlood(FLOODINFO *info)
{
floodStart++;
floodLen--;
}
static __inline BOOL isEmptyFlood()
{
if (floodLen == 0)
{
return TRUE;
}
return FALSE;
info->floodStart++;
info->floodLen--;
}
BOOLEAN DIB_XXBPP_FloodFill(SURFOBJ *DstSurf,
BOOLEAN DIB_XXBPP_FloodFillSolid(SURFOBJ *DstSurf,
BRUSHOBJ *Brush,
RECTL *DstRect,
POINTL *Origin,
XLATEOBJ *ColorTranslation,
COLORREF Color,
ULONG ConvColor,
UINT FillType)
{
ULONG x, y;
ULONG BrushColor;
FLOODINFO flood = {0, NULL, NULL};
BrushColor = Brush->iSolidColor;
x = Origin->x;
@ -105,59 +101,66 @@ BOOLEAN DIB_XXBPP_FloodFill(SURFOBJ *DstSurf,
if (FillType == FLOODFILLBORDER)
{
/* Check if the start pixel has the border color */
if (XLATEOBJ_iXlate(ColorTranslation,
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) == Color)
if (DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) == ConvColor)
{
return FALSE;
}
if (initFlood(DstRect) == FALSE)
if (initFlood(&flood, DstRect) == FALSE)
{
return FALSE;
}
addItemFlood(x, y, DstSurf, DstRect, ColorTranslation, Color, FALSE);
while (!isEmptyFlood())
addItemFlood(&flood, x, y, DstSurf, DstRect, ConvColor, FALSE);
while (flood.floodLen != 0)
{
x = floodStart->x;
y = floodStart->y;
removeItemFlood();
x = flood.floodStart->x;
y = flood.floodStart->y;
removeItemFlood(&flood);
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor);
addItemFlood(x, y + 1, DstSurf, DstRect, ColorTranslation, Color, FALSE);
addItemFlood(x, y - 1, DstSurf, DstRect, ColorTranslation, Color, FALSE);
addItemFlood(x + 1, y, DstSurf, DstRect, ColorTranslation, Color, FALSE);
addItemFlood(x - 1, y, DstSurf, DstRect, ColorTranslation, Color, FALSE);
addItemFlood(&flood, x, y + 1, DstSurf, DstRect, ConvColor, FALSE);
addItemFlood(&flood, x, y - 1, DstSurf, DstRect, ConvColor, FALSE);
addItemFlood(&flood, x + 1, y, DstSurf, DstRect, ConvColor, FALSE);
addItemFlood(&flood, x - 1, y, DstSurf, DstRect, ConvColor, FALSE);
if (flood.floodStart <= flood.floodData)
{
DPRINT1("Couldn't finish flooding!\n");
return FALSE;
}
finalizeFlood();
}
finalizeFlood(&flood);
}
else if (FillType == FLOODFILLSURFACE)
{
/* Check if the start pixel has the surface color */
if (XLATEOBJ_iXlate(ColorTranslation,
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) != Color)
if (DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) != ConvColor)
{
return FALSE;
}
if (initFlood(DstRect) == FALSE)
if (initFlood(&flood, DstRect) == FALSE)
{
return FALSE;
}
addItemFlood(x, y, DstSurf, DstRect, ColorTranslation, Color, TRUE);
while (!isEmptyFlood())
addItemFlood(&flood, x, y, DstSurf, DstRect, ConvColor, TRUE);
while (flood.floodLen != 0)
{
x = floodStart->x;
y = floodStart->y;
removeItemFlood();
x = flood.floodStart->x;
y = flood.floodStart->y;
removeItemFlood(&flood);
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor);
addItemFlood(x, y + 1, DstSurf, DstRect, ColorTranslation, Color, TRUE);
addItemFlood(x, y - 1, DstSurf, DstRect, ColorTranslation, Color, TRUE);
addItemFlood(x + 1, y, DstSurf, DstRect, ColorTranslation, Color, TRUE);
addItemFlood(x - 1, y, DstSurf, DstRect, ColorTranslation, Color, TRUE);
addItemFlood(&flood, x, y + 1, DstSurf, DstRect, ConvColor, TRUE);
addItemFlood(&flood, x, y - 1, DstSurf, DstRect, ConvColor, TRUE);
addItemFlood(&flood, x + 1, y, DstSurf, DstRect, ConvColor, TRUE);
addItemFlood(&flood, x - 1, y, DstSurf, DstRect, ConvColor, TRUE);
if (flood.floodStart <= flood.floodData)
{
DPRINT1("Couldn't finish flooding!\n");
return FALSE;
}
finalizeFlood();
}
finalizeFlood(&flood);
}
else
{

View file

@ -1077,6 +1077,7 @@ NtGdiExtFloodFill(
BOOL Ret = FALSE;
RECTL DestRect;
POINTL Pt;
ULONG ConvColor;
dc = DC_LockDc(hDC);
if (!dc)
@ -1118,11 +1119,16 @@ NtGdiExtFloodFill(
Pal = dc->dclevel.pSurface->hDIBPalette;
if (!Pal) Pal = pPrimarySurface->DevInfo.hpalDefault;
XlateObj = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, 0, NULL, Pal);
XlateObj = (XLATEOBJ*)IntEngCreateXlate(0, PAL_RGB, Pal, NULL);
/* Only solid fills supported for now
* How to support pattern brushes and non standard surfaces (not offering dib functions):
* Version a (most likely slow): call DrvPatBlt for every pixel
* Version b: create a flood mask and let MaskBlt blit a masked brush */
if (XlateObj != NULL)
{
Ret = DIB_XXBPP_FloodFill(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, XlateObj, Color, FillType);
ConvColor = XLATEOBJ_iXlate(XlateObj, Color);
Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);
EngDeleteXlate(XlateObj);
}