]>
git.saurik.com Git - wxWidgets.git/blob - src/common/imagfill.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: FloodFill for wxImage
4 // Author: Julian Smart
6 // Copyright: (c) Julian Smart
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,
71 with explicit permission to use this for wxWidgets granted by Andrew Empson
72 (no copyright claimed)
75 int width
= image
->GetWidth();
76 int height
= image
->GetHeight();
78 //Draw using a pen made from the current brush colour
79 //Potentially allows us to use patterned flood fills in future code
80 wxColour fillColour
= fillBrush
.GetColour();
81 unsigned char r
= fillColour
.Red();
82 unsigned char g
= fillColour
.Green();
83 unsigned char b
= fillColour
.Blue();
86 if (style
== wxFLOOD_SURFACE
)
88 //if wxFLOOD_SURFACE, if fill colour is same as required, we don't do anything
89 if ( image
->GetRed(x
,y
) != r
90 || image
->GetGreen(x
,y
) != g
91 || image
->GetBlue (x
,y
) != b
)
93 //prepare memory for queue
94 //queue save, start, read
95 size_t *qs
, *qst
, *qr
;
97 //queue size (physical)
98 long qSz
= height
* width
* 2;
99 qst
= new size_t [qSz
];
101 //temporary x and y locations
104 for (int i
=0; i
< qSz
; i
++)
114 image
->SetRGB(xt
,yt
,r
,g
,b
);
119 //Add new members to queue
120 //Above current pixel
121 if(MatchPixel(image
,xt
,yt
-1,width
,height
,testColour
))
127 image
->SetRGB(xt
,yt
-1,r
,g
,b
);
129 //Loop back to beginning of queue
130 if(qs
>=(qst
+qSz
)) qs
=qst
;
133 //Below current pixel
134 if(MatchPixel(image
,xt
,yt
+1,width
,height
,testColour
))
140 image
->SetRGB(xt
,yt
+1,r
,g
,b
);
141 if(qs
>=(qst
+qSz
)) qs
=qst
;
144 //Left of current pixel
145 if(MatchPixel(image
,xt
-1,yt
,width
,height
,testColour
))
151 image
->SetRGB(xt
-1,yt
,r
,g
,b
);
152 if(qs
>=(qst
+qSz
)) qs
=qst
;
155 //Right of current pixel
156 if(MatchPixel(image
,xt
+1,yt
,width
,height
,testColour
))
162 image
->SetRGB(xt
+1,yt
,r
,g
,b
);
163 if(qs
>=(qst
+qSz
)) qs
=qst
;
166 //Retrieve current queue member
169 //Loop back to the beginning
170 if(qr
>=(qst
+qSz
)) qr
=qst
;
174 //Go Back to beginning of loop
182 //style is wxFLOOD_BORDER
183 // fill up to testColor border - if already testColour don't do anything
184 if ( image
->GetRed(x
,y
) != testColour
.Red()
185 || image
->GetGreen(x
,y
) != testColour
.Green()
186 || image
->GetBlue(x
,y
) != testColour
.Blue() )
188 //prepare memory for queue
189 //queue save, start, read
190 size_t *qs
, *qst
, *qr
;
192 //queue size (physical)
193 long qSz
= height
* width
* 2;
194 qst
= new size_t [qSz
];
196 //temporary x and y locations
199 for (int i
=0; i
< qSz
; i
++)
209 image
->SetRGB(xt
,yt
,r
,g
,b
);
214 //Add new members to queue
215 //Above current pixel
216 if(!MatchBoundaryPixel(image
,xt
,yt
-1,width
,height
,fillColour
,testColour
))
222 image
->SetRGB(xt
,yt
-1,r
,g
,b
);
224 //Loop back to beginning of queue
225 if(qs
>=(qst
+qSz
)) qs
=qst
;
228 //Below current pixel
229 if(!MatchBoundaryPixel(image
,xt
,yt
+1,width
,height
,fillColour
,testColour
))
235 image
->SetRGB(xt
,yt
+1,r
,g
,b
);
236 if(qs
>=(qst
+qSz
)) qs
=qst
;
239 //Left of current pixel
240 if(!MatchBoundaryPixel(image
,xt
-1,yt
,width
,height
,fillColour
,testColour
))
246 image
->SetRGB(xt
-1,yt
,r
,g
,b
);
247 if(qs
>=(qst
+qSz
)) qs
=qst
;
250 //Right of current pixel
251 if(!MatchBoundaryPixel(image
,xt
+1,yt
,width
,height
,fillColour
,testColour
))
257 image
->SetRGB(xt
+1,yt
,r
,g
,b
);
258 if(qs
>=(qst
+qSz
)) qs
=qst
;
261 //Retrieve current queue member
264 //Loop back to the beginning
265 if(qr
>=(qst
+qSz
)) qr
=qst
;
269 //Go Back to beginning of loop
279 bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
280 const wxColour
& col
, int style
)
282 if (dc
->GetBrush().GetStyle() == wxTRANSPARENT
)
287 dc
->GetSize(&width
, &height
);
289 //it would be nice to fail if we don't get a sensible size...
290 wxCHECK_MSG(width
>= 1 && height
>= 1, false,
291 wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC"));
293 //this is much faster than doing the individual pixels
295 wxBitmap
bitmap(width
, height
);
296 memdc
.SelectObject(bitmap
);
297 memdc
.Blit(0, 0, width
, height
, dc
, 0, 0);
298 memdc
.SelectObject(wxNullBitmap
);
300 wxImage image
= bitmap
.ConvertToImage();
301 wxImageFloodFill(&image
, x
,y
, dc
->GetBrush(), col
, style
,
302 dc
->GetLogicalFunction());
303 bitmap
= wxBitmap(image
);
304 memdc
.SelectObject(bitmap
);
305 dc
->Blit(0, 0, width
, height
, &memdc
, 0, 0);
306 memdc
.SelectObject(wxNullBitmap
);
311 #endif // wxUSE_IMAGE