Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfloodfill.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS win32 subsystem 00004 * PURPOSE: Flood filling support 00005 * FILE: subsystems/win32/win32k/dib/floodfill.c 00006 * PROGRAMMER: Gregor Schneider, <grschneider AT gmail DOT com> 00007 */ 00008 00009 #include <win32k.h> 00010 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 /* 00015 * This floodfill algorithm is an iterative four neighbors version. It works with an internal stack like data structure. 00016 * The stack is kept in an array, sized for the worst case scenario of having to add all pixels of the surface. 00017 * This avoids having to allocate and free memory blocks all the time. The stack grows from the end of the array towards the start. 00018 * All pixels are checked before being added, against belonging to the fill rule (FLOODFILLBORDER or FLOODFILLSURFACE) 00019 * and the position in respect to the clip region. This guarantees all pixels lying on the stack belong to the filled surface. 00020 * Further optimisations of the algorithm are possible. 00021 */ 00022 00023 /* Floodfil helper structures and functions */ 00024 typedef struct _floodItem 00025 { 00026 ULONG x; 00027 ULONG y; 00028 } FLOODITEM; 00029 00030 typedef struct _floodInfo 00031 { 00032 ULONG floodLen; 00033 FLOODITEM *floodStart; 00034 FLOODITEM *floodData; 00035 } FLOODINFO; 00036 00037 static __inline BOOL initFlood(FLOODINFO *info, RECTL *DstRect) 00038 { 00039 ULONG width = DstRect->right - DstRect->left; 00040 ULONG height = DstRect->bottom - DstRect->top; 00041 info->floodData = ExAllocatePoolWithTag(NonPagedPool, width * height * sizeof(FLOODITEM), TAG_DIB); 00042 if (info->floodData == NULL) 00043 { 00044 return FALSE; 00045 } 00046 info->floodStart = info->floodData + (width * height); 00047 DPRINT("Allocated flood stack from %p to %p\n", info->floodData, info->floodStart); 00048 return TRUE; 00049 } 00050 static __inline VOID finalizeFlood(FLOODINFO *info) 00051 { 00052 ExFreePoolWithTag(info->floodData, TAG_DIB); 00053 } 00054 static __inline VOID addItemFlood(FLOODINFO *info, 00055 ULONG x, 00056 ULONG y, 00057 SURFOBJ *DstSurf, 00058 RECTL *DstRect, 00059 ULONG Color, 00060 BOOL isSurf) 00061 { 00062 if (RECTL_bPointInRect(DstRect,x,y)) 00063 { 00064 if (isSurf == TRUE && 00065 DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) != Color) 00066 { 00067 return; 00068 } 00069 else if (isSurf == FALSE && 00070 DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) == Color) 00071 { 00072 return; 00073 } 00074 info->floodStart--; 00075 info->floodStart->x = x; 00076 info->floodStart->y = y; 00077 info->floodLen++; 00078 } 00079 } 00080 static __inline VOID removeItemFlood(FLOODINFO *info) 00081 { 00082 info->floodStart++; 00083 info->floodLen--; 00084 } 00085 00086 BOOLEAN DIB_XXBPP_FloodFillSolid(SURFOBJ *DstSurf, 00087 BRUSHOBJ *Brush, 00088 RECTL *DstRect, 00089 POINTL *Origin, 00090 ULONG ConvColor, 00091 UINT FillType) 00092 { 00093 ULONG x, y; 00094 ULONG BrushColor; 00095 FLOODINFO flood = {0, NULL, NULL}; 00096 00097 BrushColor = Brush->iSolidColor; 00098 x = Origin->x; 00099 y = Origin->y; 00100 00101 if (FillType == FLOODFILLBORDER) 00102 { 00103 /* Check if the start pixel has the border color */ 00104 if (DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) == ConvColor) 00105 { 00106 return FALSE; 00107 } 00108 00109 if (initFlood(&flood, DstRect) == FALSE) 00110 { 00111 return FALSE; 00112 } 00113 addItemFlood(&flood, x, y, DstSurf, DstRect, ConvColor, FALSE); 00114 while (flood.floodLen != 0) 00115 { 00116 x = flood.floodStart->x; 00117 y = flood.floodStart->y; 00118 removeItemFlood(&flood); 00119 00120 DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor); 00121 if (flood.floodStart - 4 < flood.floodData) 00122 { 00123 DPRINT1("Can't finish flooding!\n"); 00124 finalizeFlood(&flood); 00125 return FALSE; 00126 } 00127 addItemFlood(&flood, x, y + 1, DstSurf, DstRect, ConvColor, FALSE); 00128 addItemFlood(&flood, x, y - 1, DstSurf, DstRect, ConvColor, FALSE); 00129 addItemFlood(&flood, x + 1, y, DstSurf, DstRect, ConvColor, FALSE); 00130 addItemFlood(&flood, x - 1, y, DstSurf, DstRect, ConvColor, FALSE); 00131 } 00132 finalizeFlood(&flood); 00133 } 00134 else if (FillType == FLOODFILLSURFACE) 00135 { 00136 /* Check if the start pixel has the surface color */ 00137 if (DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) != ConvColor) 00138 { 00139 return FALSE; 00140 } 00141 00142 if (initFlood(&flood, DstRect) == FALSE) 00143 { 00144 return FALSE; 00145 } 00146 addItemFlood(&flood, x, y, DstSurf, DstRect, ConvColor, TRUE); 00147 while (flood.floodLen != 0) 00148 { 00149 x = flood.floodStart->x; 00150 y = flood.floodStart->y; 00151 removeItemFlood(&flood); 00152 00153 DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor); 00154 if (flood.floodStart - 4 < flood.floodData) 00155 { 00156 DPRINT1("Can't finish flooding!\n"); 00157 finalizeFlood(&flood); 00158 return FALSE; 00159 } 00160 addItemFlood(&flood, x, y + 1, DstSurf, DstRect, ConvColor, TRUE); 00161 addItemFlood(&flood, x, y - 1, DstSurf, DstRect, ConvColor, TRUE); 00162 addItemFlood(&flood, x + 1, y, DstSurf, DstRect, ConvColor, TRUE); 00163 addItemFlood(&flood, x - 1, y, DstSurf, DstRect, ConvColor, TRUE); 00164 } 00165 finalizeFlood(&flood); 00166 } 00167 else 00168 { 00169 DPRINT1("Unsupported FloodFill type!\n"); 00170 return FALSE; 00171 } 00172 return TRUE; 00173 } Generated on Sat May 26 2012 04:36:59 for ReactOS by
1.7.6.1
|