mirror of
https://github.com/reactos/reactos.git
synced 2025-05-25 20:18:22 +00:00
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:
parent
f8ffccf7de
commit
c152d5480d
3 changed files with 80 additions and 71 deletions
|
@ -133,7 +133,7 @@ BOOLEAN DIB_32BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
|
||||||
BOOLEAN DIB_32BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
|
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_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 notmask[2];
|
||||||
extern unsigned char altnotmask[2];
|
extern unsigned char altnotmask[2];
|
||||||
|
|
|
@ -27,76 +27,72 @@ typedef struct _floodItem
|
||||||
ULONG y;
|
ULONG y;
|
||||||
} FLOODITEM;
|
} FLOODITEM;
|
||||||
|
|
||||||
static ULONG floodLen = 0;
|
typedef struct _floodInfo
|
||||||
static FLOODITEM *floodStart = NULL, *floodData = NULL;
|
{
|
||||||
|
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 width = DstRect->right - DstRect->left;
|
||||||
ULONG height = DstRect->bottom - DstRect->top;
|
ULONG height = DstRect->bottom - DstRect->top;
|
||||||
floodData = ExAllocatePoolWithTag(NonPagedPool, width * height * sizeof(FLOODITEM), TAG_DIB);
|
info->floodData = ExAllocatePoolWithTag(NonPagedPool, width * height * sizeof(FLOODITEM), TAG_DIB);
|
||||||
if (floodData == NULL)
|
if (info->floodData == NULL)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
floodStart = (FLOODITEM*)((PBYTE)floodData + (width * height * sizeof(FLOODITEM)));
|
info->floodStart = (FLOODITEM*)((PBYTE)info->floodData + (width * height * sizeof(FLOODITEM)));
|
||||||
return TRUE;
|
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,
|
ULONG y,
|
||||||
SURFOBJ *DstSurf,
|
SURFOBJ *DstSurf,
|
||||||
RECTL *DstRect,
|
RECTL *DstRect,
|
||||||
XLATEOBJ* ColorTranslation,
|
ULONG Color,
|
||||||
COLORREF Color,
|
|
||||||
BOOL isSurf)
|
BOOL isSurf)
|
||||||
{
|
{
|
||||||
if (x >= DstRect->left && x <= DstRect->right &&
|
if (x >= DstRect->left && x <= DstRect->right &&
|
||||||
y >= DstRect->top && y <= DstRect->bottom)
|
y >= DstRect->top && y <= DstRect->bottom)
|
||||||
{
|
{
|
||||||
if (isSurf == TRUE && XLATEOBJ_iXlate(ColorTranslation,
|
if (isSurf == TRUE &&
|
||||||
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) != Color)
|
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) != Color)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (isSurf == FALSE && XLATEOBJ_iXlate(ColorTranslation,
|
else if (isSurf == FALSE &&
|
||||||
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) == Color)
|
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) == Color)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
floodStart--;
|
info->floodStart--;
|
||||||
floodStart->x = x;
|
info->floodStart->x = x;
|
||||||
floodStart->y = y;
|
info->floodStart->y = y;
|
||||||
floodLen++;
|
info->floodLen++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static __inline VOID removeItemFlood()
|
static __inline VOID removeItemFlood(FLOODINFO *info)
|
||||||
{
|
{
|
||||||
floodStart++;
|
info->floodStart++;
|
||||||
floodLen--;
|
info->floodLen--;
|
||||||
}
|
|
||||||
static __inline BOOL isEmptyFlood()
|
|
||||||
{
|
|
||||||
if (floodLen == 0)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN DIB_XXBPP_FloodFill(SURFOBJ *DstSurf,
|
BOOLEAN DIB_XXBPP_FloodFillSolid(SURFOBJ *DstSurf,
|
||||||
BRUSHOBJ *Brush,
|
BRUSHOBJ *Brush,
|
||||||
RECTL *DstRect,
|
RECTL *DstRect,
|
||||||
POINTL *Origin,
|
POINTL *Origin,
|
||||||
XLATEOBJ *ColorTranslation,
|
ULONG ConvColor,
|
||||||
COLORREF Color,
|
UINT FillType)
|
||||||
UINT FillType)
|
|
||||||
{
|
{
|
||||||
ULONG x, y;
|
ULONG x, y;
|
||||||
ULONG BrushColor;
|
ULONG BrushColor;
|
||||||
|
FLOODINFO flood = {0, NULL, NULL};
|
||||||
|
|
||||||
BrushColor = Brush->iSolidColor;
|
BrushColor = Brush->iSolidColor;
|
||||||
x = Origin->x;
|
x = Origin->x;
|
||||||
|
@ -105,59 +101,66 @@ BOOLEAN DIB_XXBPP_FloodFill(SURFOBJ *DstSurf,
|
||||||
if (FillType == FLOODFILLBORDER)
|
if (FillType == FLOODFILLBORDER)
|
||||||
{
|
{
|
||||||
/* Check if the start pixel has the border color */
|
/* Check if the start pixel has the border color */
|
||||||
if (XLATEOBJ_iXlate(ColorTranslation,
|
if (DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) == ConvColor)
|
||||||
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) == Color)
|
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initFlood(DstRect) == FALSE)
|
if (initFlood(&flood, DstRect) == FALSE)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
addItemFlood(x, y, DstSurf, DstRect, ColorTranslation, Color, FALSE);
|
addItemFlood(&flood, x, y, DstSurf, DstRect, ConvColor, FALSE);
|
||||||
while (!isEmptyFlood())
|
while (flood.floodLen != 0)
|
||||||
{
|
{
|
||||||
x = floodStart->x;
|
x = flood.floodStart->x;
|
||||||
y = floodStart->y;
|
y = flood.floodStart->y;
|
||||||
removeItemFlood();
|
removeItemFlood(&flood);
|
||||||
|
|
||||||
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor);
|
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor);
|
||||||
addItemFlood(x, y + 1, DstSurf, DstRect, ColorTranslation, Color, FALSE);
|
addItemFlood(&flood, x, y + 1, DstSurf, DstRect, ConvColor, FALSE);
|
||||||
addItemFlood(x, y - 1, DstSurf, DstRect, ColorTranslation, Color, FALSE);
|
addItemFlood(&flood, x, y - 1, DstSurf, DstRect, ConvColor, FALSE);
|
||||||
addItemFlood(x + 1, y, DstSurf, DstRect, ColorTranslation, Color, FALSE);
|
addItemFlood(&flood, x + 1, y, DstSurf, DstRect, ConvColor, FALSE);
|
||||||
addItemFlood(x - 1, y, DstSurf, DstRect, ColorTranslation, Color, 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)
|
else if (FillType == FLOODFILLSURFACE)
|
||||||
{
|
{
|
||||||
/* Check if the start pixel has the surface color */
|
/* Check if the start pixel has the surface color */
|
||||||
if (XLATEOBJ_iXlate(ColorTranslation,
|
if (DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) != ConvColor)
|
||||||
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) != Color)
|
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initFlood(DstRect) == FALSE)
|
if (initFlood(&flood, DstRect) == FALSE)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
addItemFlood(x, y, DstSurf, DstRect, ColorTranslation, Color, TRUE);
|
addItemFlood(&flood, x, y, DstSurf, DstRect, ConvColor, TRUE);
|
||||||
while (!isEmptyFlood())
|
while (flood.floodLen != 0)
|
||||||
{
|
{
|
||||||
x = floodStart->x;
|
x = flood.floodStart->x;
|
||||||
y = floodStart->y;
|
y = flood.floodStart->y;
|
||||||
removeItemFlood();
|
removeItemFlood(&flood);
|
||||||
|
|
||||||
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor);
|
DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor);
|
||||||
addItemFlood(x, y + 1, DstSurf, DstRect, ColorTranslation, Color, TRUE);
|
addItemFlood(&flood, x, y + 1, DstSurf, DstRect, ConvColor, TRUE);
|
||||||
addItemFlood(x, y - 1, DstSurf, DstRect, ColorTranslation, Color, TRUE);
|
addItemFlood(&flood, x, y - 1, DstSurf, DstRect, ConvColor, TRUE);
|
||||||
addItemFlood(x + 1, y, DstSurf, DstRect, ColorTranslation, Color, TRUE);
|
addItemFlood(&flood, x + 1, y, DstSurf, DstRect, ConvColor, TRUE);
|
||||||
addItemFlood(x - 1, y, DstSurf, DstRect, ColorTranslation, Color, 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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1070,13 +1070,14 @@ NtGdiExtFloodFill(
|
||||||
UINT FillType)
|
UINT FillType)
|
||||||
{
|
{
|
||||||
PDC dc;
|
PDC dc;
|
||||||
PDC_ATTR pdcattr;
|
PDC_ATTR pdcattr;
|
||||||
SURFACE *psurf = NULL;
|
SURFACE *psurf = NULL;
|
||||||
HPALETTE Pal = 0;
|
HPALETTE Pal = 0;
|
||||||
XLATEOBJ *XlateObj = NULL;
|
XLATEOBJ *XlateObj = NULL;
|
||||||
BOOL Ret = FALSE;
|
BOOL Ret = FALSE;
|
||||||
RECTL DestRect;
|
RECTL DestRect;
|
||||||
POINTL Pt;
|
POINTL Pt;
|
||||||
|
ULONG ConvColor;
|
||||||
|
|
||||||
dc = DC_LockDc(hDC);
|
dc = DC_LockDc(hDC);
|
||||||
if (!dc)
|
if (!dc)
|
||||||
|
@ -1118,11 +1119,16 @@ NtGdiExtFloodFill(
|
||||||
|
|
||||||
Pal = dc->dclevel.pSurface->hDIBPalette;
|
Pal = dc->dclevel.pSurface->hDIBPalette;
|
||||||
if (!Pal) Pal = pPrimarySurface->DevInfo.hpalDefault;
|
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)
|
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);
|
EngDeleteXlate(XlateObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue