]>
git.saurik.com Git - wxWidgets.git/blob - src/common/imagfill.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/imagfill.cpp
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"
18 #if wxUSE_IMAGE && !defined(__WXMSW__)
19 // we have no use for this code in wxMSW...
24 #include "wx/dcmemory.h"
30 // Fills with the colour extracted from fillBrush, starting at x,y until either
31 // a color different from the start pixel is reached (wxFLOOD_SURFACE)
32 // or fill color is reached (wxFLOOD_BORDER)
34 static bool LINKAGEMODE
MatchPixel(wxImage
*img
, int x
, int y
, int w
, int h
, const wxColour
& c
)
36 if ((x
<0)||(x
>=w
)||(y
<0)||(y
>=h
)) return false;
38 unsigned char r
= img
->GetRed(x
,y
);
39 unsigned char g
= img
->GetGreen(x
,y
);
40 unsigned char b
= img
->GetBlue(x
,y
);
41 return c
.Red() == r
&& c
.Green() == g
&& c
.Blue() == b
;
44 static bool LINKAGEMODE
MatchBoundaryPixel(wxImage
*img
, int x
, int y
, int w
, int h
, const wxColour
& fill
, const wxColour
& bound
)
46 if ((x
<0)||(x
>=w
)||(y
<0)||(y
>=h
)) return true;
48 unsigned char r
= img
->GetRed(x
,y
);
49 unsigned char g
= img
->GetGreen(x
,y
);
50 unsigned char b
= img
->GetBlue(x
,y
);
51 if ( fill
.Red() == r
&& fill
.Green() == g
&& fill
.Blue() == b
)
53 if ( bound
.Red() == r
&& bound
.Green() == g
&& bound
.Blue() == b
)
59 static void LINKAGEMODE
60 wxImageFloodFill(wxImage
*image
,
61 wxCoord x
, wxCoord y
, const wxBrush
& fillBrush
,
62 const wxColour
& testColour
, int style
,
63 int WXUNUSED(LogicalFunction
))
65 /* A diamond flood-fill using a circular queue system.
66 Each pixel surrounding the current pixel is added to
67 the queue if it meets the criteria, then is retrieved in
68 its turn. Code originally based on http://www.drawit.co.nz/Developers.htm,
69 with explicit permission to use this for wxWidgets granted by Andrew Empson
70 (no copyright claimed)
73 int width
= image
->GetWidth();
74 int height
= image
->GetHeight();
76 //Draw using a pen made from the current brush colour
77 //Potentially allows us to use patterned flood fills in future code
78 wxColour fillColour
= fillBrush
.GetColour();
79 unsigned char r
= fillColour
.Red();
80 unsigned char g
= fillColour
.Green();
81 unsigned char b
= fillColour
.Blue();
84 if (style
== wxFLOOD_SURFACE
)
86 //if wxFLOOD_SURFACE, if fill colour is same as required, we don't do anything
87 if ( image
->GetRed(x
,y
) != r
88 || image
->GetGreen(x
,y
) != g
89 || image
->GetBlue (x
,y
) != b
)
91 //prepare memory for queue
92 //queue save, start, read
93 size_t *qs
, *qst
, *qr
;
95 //queue size (physical)
96 long qSz
= height
* width
* 2;
97 qst
= new size_t [qSz
];
99 //temporary x and y locations
102 for (int i
=0; i
< qSz
; i
++)
112 image
->SetRGB(xt
,yt
,r
,g
,b
);
117 //Add new members to queue
118 //Above current pixel
119 if(MatchPixel(image
,xt
,yt
-1,width
,height
,testColour
))
125 image
->SetRGB(xt
,yt
-1,r
,g
,b
);
127 //Loop back to beginning of queue
128 if(qs
>=(qst
+qSz
)) qs
=qst
;
131 //Below current pixel
132 if(MatchPixel(image
,xt
,yt
+1,width
,height
,testColour
))
138 image
->SetRGB(xt
,yt
+1,r
,g
,b
);
139 if(qs
>=(qst
+qSz
)) qs
=qst
;
142 //Left of current pixel
143 if(MatchPixel(image
,xt
-1,yt
,width
,height
,testColour
))
149 image
->SetRGB(xt
-1,yt
,r
,g
,b
);
150 if(qs
>=(qst
+qSz
)) qs
=qst
;
153 //Right of current pixel
154 if(MatchPixel(image
,xt
+1,yt
,width
,height
,testColour
))
160 image
->SetRGB(xt
+1,yt
,r
,g
,b
);
161 if(qs
>=(qst
+qSz
)) qs
=qst
;
164 //Retrieve current queue member
167 //Loop back to the beginning
168 if(qr
>=(qst
+qSz
)) qr
=qst
;
172 //Go Back to beginning of loop
180 //style is wxFLOOD_BORDER
181 // fill up to testColor border - if already testColour don't do anything
182 if ( image
->GetRed(x
,y
) != testColour
.Red()
183 || image
->GetGreen(x
,y
) != testColour
.Green()
184 || image
->GetBlue(x
,y
) != testColour
.Blue() )
186 //prepare memory for queue
187 //queue save, start, read
188 size_t *qs
, *qst
, *qr
;
190 //queue size (physical)
191 long qSz
= height
* width
* 2;
192 qst
= new size_t [qSz
];
194 //temporary x and y locations
197 for (int i
=0; i
< qSz
; i
++)
207 image
->SetRGB(xt
,yt
,r
,g
,b
);
212 //Add new members to queue
213 //Above current pixel
214 if(!MatchBoundaryPixel(image
,xt
,yt
-1,width
,height
,fillColour
,testColour
))
220 image
->SetRGB(xt
,yt
-1,r
,g
,b
);
222 //Loop back to beginning of queue
223 if(qs
>=(qst
+qSz
)) qs
=qst
;
226 //Below current pixel
227 if(!MatchBoundaryPixel(image
,xt
,yt
+1,width
,height
,fillColour
,testColour
))
233 image
->SetRGB(xt
,yt
+1,r
,g
,b
);
234 if(qs
>=(qst
+qSz
)) qs
=qst
;
237 //Left of current pixel
238 if(!MatchBoundaryPixel(image
,xt
-1,yt
,width
,height
,fillColour
,testColour
))
244 image
->SetRGB(xt
-1,yt
,r
,g
,b
);
245 if(qs
>=(qst
+qSz
)) qs
=qst
;
248 //Right of current pixel
249 if(!MatchBoundaryPixel(image
,xt
+1,yt
,width
,height
,fillColour
,testColour
))
255 image
->SetRGB(xt
+1,yt
,r
,g
,b
);
256 if(qs
>=(qst
+qSz
)) qs
=qst
;
259 //Retrieve current queue member
262 //Loop back to the beginning
263 if(qr
>=(qst
+qSz
)) qr
=qst
;
267 //Go Back to beginning of loop
277 bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
278 const wxColour
& col
, int style
)
280 if (dc
->GetBrush().GetStyle() == wxTRANSPARENT
)
285 dc
->GetSize(&width
, &height
);
287 //it would be nice to fail if we don't get a sensible size...
288 wxCHECK_MSG(width
>= 1 && height
>= 1, false,
289 wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC"));
291 //this is much faster than doing the individual pixels
293 wxBitmap
bitmap(width
, height
);
294 memdc
.SelectObject(bitmap
);
295 memdc
.Blit(0, 0, width
, height
, dc
, 0, 0);
296 memdc
.SelectObject(wxNullBitmap
);
298 wxImage image
= bitmap
.ConvertToImage();
299 wxImageFloodFill(&image
, x
,y
, dc
->GetBrush(), col
, style
,
300 dc
->GetLogicalFunction());
301 bitmap
= wxBitmap(image
);
302 memdc
.SelectObject(bitmap
);
303 dc
->Blit(0, 0, width
, height
, &memdc
, 0, 0);
304 memdc
.SelectObject(wxNullBitmap
);
309 #endif // wxUSE_IMAGE