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