]> git.saurik.com Git - wxWidgets.git/blob - src/common/imagfill.cpp
f199f0a4e825e46fe36cd5a93d6e83a6ef71107d
[wxWidgets.git] / src / common / imagfill.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: imagfill.cpp
3 // Purpose: FloodFill for wxImage
4 // Author:
5 // RCS-ID: $Id$
6 // Copyright:
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #endif
12
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #include "wx/defs.h"
21
22 #if wxUSE_IMAGE
23
24 #include "wx/image.h"
25
26 // DoFloodFill
27 // Fills with the colour extracted from fillBrush, starting at x,y until either
28 // a color different from the start pixel is reached (wxFLOOD_SURFACE)
29 // or fill color is reached (wxFLOOD_BORDER)
30
31 bool wxImage::MatchPixel(int x, int y, int w, int h, const wxColour & c)
32 {
33 if ((x<0)||(x>=w)||(y<0)||(y>=h)) return false;
34
35 unsigned char r = GetRed(x,y);
36 unsigned char g = GetGreen(x,y);
37 unsigned char b = GetBlue(x,y);
38 return c.Red() == r && c.Green() == g && c.Blue() == b ;
39 }
40
41 bool wxImage::MatchBoundaryPixel(int x, int y, int w, int h, const wxColour & fill, const wxColour & bound)
42 {
43 if ((x<0)||(x>=w)||(y<0)||(y>=h)) return TRUE;
44
45 unsigned char r = GetRed(x,y);
46 unsigned char g = GetGreen(x,y);
47 unsigned char b = GetBlue(x,y);
48 if ( fill.Red() == r && fill.Green() == g && fill.Blue() == b ) return TRUE;
49 if ( bound.Red() == r && bound.Green() == g && bound.Blue() == b ) return TRUE;
50 return FALSE ;
51 }
52
53
54 void wxImage::DoFloodFill (wxCoord x, wxCoord y, const wxBrush & fillBrush,
55 const wxColour& testColour, int style /*=wxFLOOD_SURFACE */,
56 int LogicalFunction /*= wxCOPY, currently unused */)
57 {
58 /* A diamond flood-fill using a circular queue system.
59 Each pixel surrounding the current pixel is added to
60 the queue if it meets the criteria, then is retrieved in
61 its turn. Code originally based on http://www.drawit.co.nz/Developers.htm */
62
63 int width = GetWidth();
64 int height = GetHeight();
65
66 //Draw using a pen made from the current brush colour
67 //Potentially allows us to use patterned flood fills in future code
68 wxColour fillColour = fillBrush.GetColour();
69 unsigned char r = fillColour.Red();
70 unsigned char g = fillColour.Green();
71 unsigned char b = fillColour.Blue();
72
73 //initial test :
74 if (style == wxFLOOD_SURFACE)
75 {
76 //if wxFLOOD_SURFACE, if fill colour is same as required, we don't do anything
77 if ( GetRed(x,y) != r
78 || GetGreen(x,y) != g
79 || GetBlue (x,y) != b )
80 {
81 //prepare memory for queue
82 //queue save, start, read
83 size_t *qs, *qst, *qr;
84
85 //queue size (physical)
86 long qSz= height * width * 2;
87 qst = new size_t [qSz];
88
89 //temporary x and y locations
90 int xt, yt;
91
92 for (int i=0; i < qSz; i++)
93 qst[i] = 0;
94
95 // start queue
96 qs=qr=qst;
97 *qs=xt=x;
98 qs++;
99 *qs=yt=y;
100 qs++;
101
102 SetRGB(xt,yt,r,g,b);
103
104 //Main queue loop
105 while(qr!=qs)
106 {
107 //Add new members to queue
108 //Above current pixel
109 if(MatchPixel(xt,yt-1,width,height,testColour))
110 {
111 *qs=xt;
112 qs++;
113 *qs=yt-1;
114 qs++;
115 SetRGB(xt,yt-1,r,g,b);
116
117 //Loop back to beginning of queue
118 if(qs>=(qst+qSz)) qs=qst;
119 }
120
121 //Below current pixel
122 if(MatchPixel(xt,yt+1,width,height,testColour))
123 {
124 *qs=xt;
125 qs++;
126 *qs=yt+1;
127 qs++;
128 SetRGB(xt,yt+1,r,g,b);
129 if(qs>=(qst+qSz)) qs=qst;
130 }
131
132 //Left of current pixel
133 if(MatchPixel(xt-1,yt,width,height,testColour))
134 {
135 *qs=xt-1;
136 qs++;
137 *qs=yt;
138 qs++;
139 SetRGB(xt-1,yt,r,g,b);
140 if(qs>=(qst+qSz)) qs=qst;
141 }
142
143 //Right of current pixel
144 if(MatchPixel(xt+1,yt,width,height,testColour))
145 {
146 *qs=xt+1;
147 qs++;
148 *qs=yt;
149 qs++;
150 SetRGB(xt+1,yt,r,g,b);
151 if(qs>=(qst+qSz)) qs=qst;
152 }
153
154 //Retrieve current queue member
155 qr+=2;
156
157 //Loop back to the beginning
158 if(qr>=(qst+qSz)) qr=qst;
159 xt=*qr;
160 yt=*(qr+1);
161
162 //Go Back to beginning of loop
163 }
164
165 delete [] qst ;
166 }
167 }
168 else
169 {
170 //style is wxFLOOD_BORDER
171 // fill up to testColor border - if already testColour don't do anything
172 if ( GetRed(x,y) != testColour.Red()
173 || GetGreen(x,y) != testColour.Green()
174 || GetBlue(x,y) != testColour.Blue() )
175 {
176 //prepare memory for queue
177 //queue save, start, read
178 size_t *qs, *qst, *qr;
179
180 //queue size (physical)
181 long qSz= height * width * 2;
182 qst = new size_t [qSz];
183
184 //temporary x and y locations
185 int xt, yt;
186
187 for (int i=0; i < qSz; i++)
188 qst[i] = 0;
189
190 // start queue
191 qs=qr=qst;
192 *qs=xt=x;
193 qs++;
194 *qs=yt=y;
195 qs++;
196
197 SetRGB(xt,yt,r,g,b);
198
199 //Main queue loop
200 while(qr!=qs)
201 {
202 //Add new members to queue
203 //Above current pixel
204 if(!MatchBoundaryPixel(xt,yt-1,width,height,fillColour,testColour))
205 {
206 *qs=xt;
207 qs++;
208 *qs=yt-1;
209 qs++;
210 SetRGB(xt,yt-1,r,g,b);
211
212 //Loop back to beginning of queue
213 if(qs>=(qst+qSz)) qs=qst;
214 }
215
216 //Below current pixel
217 if(!MatchBoundaryPixel(xt,yt+1,width,height,fillColour,testColour))
218 {
219 *qs=xt;
220 qs++;
221 *qs=yt+1;
222 qs++;
223 SetRGB(xt,yt+1,r,g,b);
224 if(qs>=(qst+qSz)) qs=qst;
225 }
226
227 //Left of current pixel
228 if(!MatchBoundaryPixel(xt-1,yt,width,height,fillColour,testColour))
229 {
230 *qs=xt-1;
231 qs++;
232 *qs=yt;
233 qs++;
234 SetRGB(xt-1,yt,r,g,b);
235 if(qs>=(qst+qSz)) qs=qst;
236 }
237
238 //Right of current pixel
239 if(!MatchBoundaryPixel(xt+1,yt,width,height,fillColour,testColour))
240 {
241 *qs=xt+1;
242 qs++;
243 *qs=yt;
244 qs++;
245 SetRGB(xt+1,yt,r,g,b);
246 if(qs>=(qst+qSz)) qs=qst;
247 }
248
249 //Retrieve current queue member
250 qr+=2;
251
252 //Loop back to the beginning
253 if(qr>=(qst+qSz)) qr=qst;
254 xt=*qr;
255 yt=*(qr+1);
256
257 //Go Back to beginning of loop
258 }
259
260 delete [] qst ;
261 }
262 }
263 //all done,
264 }
265
266 #endif // wxUSE_IMAGE
267