diff --git a/reactos/subsystems/win32/win32k/dib/dib.h b/reactos/subsystems/win32/win32k/dib/dib.h index 5a7b36ebda1..97508e57da1 100644 --- a/reactos/subsystems/win32/win32k/dib/dib.h +++ b/reactos/subsystems/win32/win32k/dib/dib.h @@ -133,6 +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); extern unsigned char notmask[2]; extern unsigned char altnotmask[2]; diff --git a/reactos/subsystems/win32/win32k/dib/floodfill.c b/reactos/subsystems/win32/win32k/dib/floodfill.c new file mode 100644 index 00000000000..b18b1af6d1a --- /dev/null +++ b/reactos/subsystems/win32/win32k/dib/floodfill.c @@ -0,0 +1,168 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS win32 subsystem + * PURPOSE: Flood filling support + * FILE: subsystems/win32/win32k/dib/floodfill.c + * PROGRAMMER: Gregor Schneider, + */ + +#include + +#define NDEBUG +#include + +/* +* This floodfill algorithm is an iterative four neighbors version. It works with an internal stack like data structure. +* The stack is kept in an array, sized for the worst case scenario of having to add all pixels of the surface. +* This avoids having to allocate and free memory blocks all the time. The stack grows from the end of the array towards the start. +* All pixels are checked before being added, against belonging to the fill rule (FLOODFILLBORDER or FLOODFILLSURFACE) +* and the position in respect to the clip region. This guarantees all pixels lying on the stack belong to the filled surface. +* Further optimisations of the algorithm are possible. +*/ + +/* Floodfil helper structures and functions */ +typedef struct _floodItem +{ + ULONG x; + ULONG y; +} FLOODITEM; + +static ULONG floodLen = 0; +static FLOODITEM *floodStart = NULL, *floodData = NULL; + +static __inline BOOL initFlood(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) + { + return FALSE; + } + floodStart = (FLOODITEM*)((PBYTE)floodData + (width * height * sizeof(FLOODITEM))); + return TRUE; +} +static __inline VOID finalizeFlood() +{ + ExFreePoolWithTag(floodData, TAG_DIB); +} +static __inline VOID addItemFlood(ULONG x, + ULONG y, + SURFOBJ *DstSurf, + RECTL *DstRect, + XLATEOBJ* ColorTranslation, + COLORREF 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) + { + return; + } + else if (isSurf == FALSE && XLATEOBJ_iXlate(ColorTranslation, + DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y)) == Color) + { + return; + } + floodStart--; + floodStart->x = x; + floodStart->y = y; + floodLen++; + } +} +static __inline VOID removeItemFlood() +{ + floodStart++; + floodLen--; +} +static __inline BOOL isEmptyFlood() +{ + if (floodLen == 0) + { + return TRUE; + } + return FALSE; +} + +BOOLEAN DIB_XXBPP_FloodFill(SURFOBJ *DstSurf, + BRUSHOBJ *Brush, + RECTL *DstRect, + POINTL *Origin, + XLATEOBJ *ColorTranslation, + COLORREF Color, + UINT FillType) +{ + ULONG x, y; + ULONG BrushColor; + + BrushColor = Brush->iSolidColor; + x = Origin->x; + y = Origin->y; + + 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) + { + return FALSE; + } + + if (initFlood(DstRect) == FALSE) + { + return FALSE; + } + addItemFlood(x, y, DstSurf, DstRect, ColorTranslation, Color, FALSE); + while (!isEmptyFlood()) + { + x = floodStart->x; + y = floodStart->y; + removeItemFlood(); + + 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); + } + finalizeFlood(); + } + 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) + { + return FALSE; + } + + if (initFlood(DstRect) == FALSE) + { + return FALSE; + } + addItemFlood(x, y, DstSurf, DstRect, ColorTranslation, Color, TRUE); + while (!isEmptyFlood()) + { + x = floodStart->x; + y = floodStart->y; + removeItemFlood(); + + 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); + + } + finalizeFlood(); + } + else + { + DPRINT1("Unsupported FloodFill type!\n"); + return FALSE; + } + return TRUE; +} diff --git a/reactos/subsystems/win32/win32k/objects/fillshap.c b/reactos/subsystems/win32/win32k/objects/fillshap.c index 19174495690..bc3273ec090 100644 --- a/reactos/subsystems/win32/win32k/objects/fillshap.c +++ b/reactos/subsystems/win32/win32k/objects/fillshap.c @@ -1072,13 +1072,12 @@ NtGdiExtFloodFill( PDC dc; PDC_ATTR pdcattr; SURFACE *psurf = NULL; - PBRUSH pbrFill = NULL; + HPALETTE Pal = 0; + XLATEOBJ *XlateObj = NULL; BOOL Ret = FALSE; RECTL DestRect; POINTL Pt; - DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n"); - dc = DC_LockDc(hDC); if (!dc) { @@ -1110,12 +1109,6 @@ NtGdiExtFloodFill( else goto cleanup; - pbrFill = dc->dclevel.pbrFill; - if (!pbrFill) - { - Ret = FALSE; - goto cleanup; - } psurf = dc->dclevel.pSurface; if (!psurf) { @@ -1123,6 +1116,16 @@ NtGdiExtFloodFill( goto cleanup; } + Pal = dc->dclevel.pSurface->hDIBPalette; + if (!Pal) Pal = pPrimarySurface->DevInfo.hpalDefault; + XlateObj = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, 0, NULL, Pal); + + if (XlateObj != NULL) + { + Ret = DIB_XXBPP_FloodFill(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, XlateObj, Color, FillType); + EngDeleteXlate(XlateObj); + } + cleanup: DC_UnlockDc(dc); return Ret; diff --git a/reactos/subsystems/win32/win32k/win32k.rbuild b/reactos/subsystems/win32/win32k/win32k.rbuild index 8035ffb1fd9..68766f584d2 100644 --- a/reactos/subsystems/win32/win32k/win32k.rbuild +++ b/reactos/subsystems/win32/win32k/win32k.rbuild @@ -31,6 +31,7 @@ dib32bpp.c dibXXbpp.c dib.c + floodfill.c