]>
git.saurik.com Git - wxWidgets.git/blob - src/common/imagfill.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: FloodFill for wxImage
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
20 #if wxUSE_IMAGE && !defined(__WXMSW__)
21 // we have no use for this code in wxMSW...
28 #include "wx/dcmemory.h"
32 // Fills with the colour extracted from fillBrush, starting at x,y until either
33 // a color different from the start pixel is reached (wxFLOOD_SURFACE)
34 // or fill color is reached (wxFLOOD_BORDER)
36 static bool LINKAGEMODE
MatchPixel(wxImage
*img
, int x
, int y
, int w
, int h
, const wxColour
& c
)
38 if ((x
<0)||(x
>=w
)||(y
<0)||(y
>=h
)) return FALSE
;
40 unsigned char r
= img
->GetRed(x
,y
);
41 unsigned char g
= img
->GetGreen(x
,y
);
42 unsigned char b
= img
->GetBlue(x
,y
);
43 return c
.Red() == r
&& c
.Green() == g
&& c
.Blue() == b
;
46 static bool LINKAGEMODE
MatchBoundaryPixel(wxImage
*img
, int x
, int y
, int w
, int h
, const wxColour
& fill
, const wxColour
& bound
)
48 if ((x
<0)||(x
>=w
)||(y
<0)||(y
>=h
)) return TRUE
;
50 unsigned char r
= img
->GetRed(x
,y
);
51 unsigned char g
= img
->GetGreen(x
,y
);
52 unsigned char b
= img
->GetBlue(x
,y
);
53 if ( fill
.Red() == r
&& fill
.Green() == g
&& fill
.Blue() == b
)
55 if ( bound
.Red() == r
&& bound
.Green() == g
&& bound
.Blue() == b
)
61 static void LINKAGEMODE
62 wxImageFloodFill(wxImage
*image
,
63 wxCoord x
, wxCoord y
, const wxBrush
& fillBrush
,
64 const wxColour
& testColour
, int style
,
67 /* A diamond flood-fill using a circular queue system.
68 Each pixel surrounding the current pixel is added to
69 the queue if it meets the criteria, then is retrieved in
70 its turn. Code originally based on http://www.drawit.co.nz/Developers.htm */
72 int width
= image
->GetWidth();
73 int height
= image
->GetHeight();
75 //Draw using a pen made from the current brush colour
76 //Potentially allows us to use patterned flood fills in future code
77 wxColour fillColour
= fillBrush
.GetColour();
78 unsigned char r
= fillColour
.Red();
79 unsigned char g
= fillColour
.Green();
80 unsigned char b
= fillColour
.Blue();
83 if (style
== wxFLOOD_SURFACE
)
85 //if wxFLOOD_SURFACE, if fill colour is same as required, we don't do anything
86 if ( image
->GetRed(x
,y
) != r
87 || image
->GetGreen(x
,y
) != g
88 || image
->GetBlue (x
,y
) != b
)
90 //prepare memory for queue
91 //queue save, start, read
92 size_t *qs
, *qst
, *qr
;
94 //queue size (physical)
95 long qSz
= height
* width
* 2;
96 qst
= new size_t [qSz
];
98 //temporary x and y locations
101 for (int i
=0; i
< qSz
; i
++)
111 image
->SetRGB(xt
,yt
,r
,g
,b
);
116 //Add new members to queue
117 //Above current pixel
118 if(MatchPixel(image
,xt
,yt
-1,width
,height
,testColour
))
124 image
->SetRGB(xt
,yt
-1,r
,g
,b
);
126 //Loop back to beginning of queue
127 if(qs
>=(qst
+qSz
)) qs
=qst
;
130 //Below current pixel
131 if(MatchPixel(image
,xt
,yt
+1,width
,height
,testColour
))
137 image
->SetRGB(xt
,yt
+1,r
,g
,b
);
138 if(qs
>=(qst
+qSz
)) qs
=qst
;
141 //Left of current pixel
142 if(MatchPixel(image
,xt
-1,yt
,width
,height
,testColour
))
148 image
->SetRGB(xt
-1,yt
,r
,g
,b
);
149 if(qs
>=(qst
+qSz
)) qs
=qst
;
152 //Right of current pixel
153 if(MatchPixel(image
,xt
+1,yt
,width
,height
,testColour
))
159 image
->SetRGB(xt
+1,yt
,r
,g
,b
);
160 if(qs
>=(qst
+qSz
)) qs
=qst
;
163 //Retrieve current queue member
166 //Loop back to the beginning
167 if(qr
>=(qst
+qSz
)) qr
=qst
;
171 //Go Back to beginning of loop
179 //style is wxFLOOD_BORDER
180 // fill up to testColor border - if already testColour don't do anything
181 if ( image
->GetRed(x
,y
) != testColour
.Red()
182 || image
->GetGreen(x
,y
) != testColour
.Green()
183 || image
->GetBlue(x
,y
) != testColour
.Blue() )
185 //prepare memory for queue
186 //queue save, start, read
187 size_t *qs
, *qst
, *qr
;
189 //queue size (physical)
190 long qSz
= height
* width
* 2;
191 qst
= new size_t [qSz
];
193 //temporary x and y locations
196 for (int i
=0; i
< qSz
; i
++)
206 image
->SetRGB(xt
,yt
,r
,g
,b
);
211 //Add new members to queue
212 //Above current pixel
213 if(!MatchBoundaryPixel(image
,xt
,yt
-1,width
,height
,fillColour
,testColour
))
219 image
->SetRGB(xt
,yt
-1,r
,g
,b
);
221 //Loop back to beginning of queue
222 if(qs
>=(qst
+qSz
)) qs
=qst
;
225 //Below current pixel
226 if(!MatchBoundaryPixel(image
,xt
,yt
+1,width
,height
,fillColour
,testColour
))
232 image
->SetRGB(xt
,yt
+1,r
,g
,b
);
233 if(qs
>=(qst
+qSz
)) qs
=qst
;
236 //Left of current pixel
237 if(!MatchBoundaryPixel(image
,xt
-1,yt
,width
,height
,fillColour
,testColour
))
243 image
->SetRGB(xt
-1,yt
,r
,g
,b
);
244 if(qs
>=(qst
+qSz
)) qs
=qst
;
247 //Right of current pixel
248 if(!MatchBoundaryPixel(image
,xt
+1,yt
,width
,height
,fillColour
,testColour
))
254 image
->SetRGB(xt
+1,yt
,r
,g
,b
);
255 if(qs
>=(qst
+qSz
)) qs
=qst
;
258 //Retrieve current queue member
261 //Loop back to the beginning
262 if(qr
>=(qst
+qSz
)) qr
=qst
;
266 //Go Back to beginning of loop
276 bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
277 const wxColour
& col
, int style
)
279 if (dc
->GetBrush().GetStyle() == wxTRANSPARENT
)
284 dc
->GetSize(&width
, &height
);
286 //it would be nice to fail if we don't get a sensible size...
287 wxCHECK_RET(width
>= 1 && height
>= 1, wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC"));
289 if (width
<= 1 || height
<= 1)
292 //this is much faster than doing the individual pixels
294 wxBitmap
bitmap(width
, height
);
295 memdc
.SelectObject(bitmap
);
296 memdc
.Blit(0, 0, width
, height
, dc
, 0, 0);
297 memdc
.SelectObject(wxNullBitmap
);
299 wxImage image
= bitmap
.ConvertToImage();
300 wxImageFloodFill(&image
, x
,y
, dc
->GetBrush(), col
, style
,
301 dc
->GetLogicalFunction());
302 bitmap
= wxBitmap(image
);
303 memdc
.SelectObject(bitmap
);
304 dc
->Blit(0, 0, width
, height
, &memdc
, 0, 0);
305 memdc
.SelectObject(wxNullBitmap
);
310 #endif // wxUSE_IMAGE