]> git.saurik.com Git - wxWidgets.git/blame - src/common/imagfill.cpp
Further fixes to references
[wxWidgets.git] / src / common / imagfill.cpp
CommitLineData
7011cf13
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: imagfill.cpp
3// Purpose: FloodFill for wxImage
e3fed5c4 4// Author:
7011cf13 5// RCS-ID: $Id$
e3fed5c4 6// Copyright:
7011cf13
JS
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
7011cf13
JS
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
3a0a5ada
VS
18#include "wx/defs.h"
19
20#if wxUSE_IMAGE && !defined(__WXMSW__)
21// we have no use for this code in wxMSW...
7011cf13
JS
22
23#include "wx/image.h"
0fc5dbf5
VZ
24
25#ifndef WX_PRECOMP
26 #include "wx/brush.h"
3a0a5ada
VS
27 #include "wx/dc.h"
28 #include "wx/dcmemory.h"
0fc5dbf5 29#endif
7011cf13
JS
30
31// DoFloodFill
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)
35
3a0a5ada 36static LINKAGEMODE bool MatchPixel(wxImage *img, int x, int y, int w, int h, const wxColour& c)
7011cf13 37{
e3fed5c4 38 if ((x<0)||(x>=w)||(y<0)||(y>=h)) return FALSE;
7011cf13 39
3a0a5ada
VS
40 unsigned char r = img->GetRed(x,y);
41 unsigned char g = img->GetGreen(x,y);
42 unsigned char b = img->GetBlue(x,y);
7011cf13
JS
43 return c.Red() == r && c.Green() == g && c.Blue() == b ;
44}
45
3a0a5ada 46static LINKAGEMODE bool MatchBoundaryPixel(wxImage *img, int x, int y, int w, int h, const wxColour & fill, const wxColour& bound)
7011cf13
JS
47{
48 if ((x<0)||(x>=w)||(y<0)||(y>=h)) return TRUE;
49
3a0a5ada
VS
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 )
54 return TRUE;
55 if ( bound.Red() == r && bound.Green() == g && bound.Blue() == b )
56 return TRUE;
57 return FALSE;
7011cf13
JS
58}
59
60
3a0a5ada
VS
61static LINKAGEMODE
62void wxImageFloodFill(wxImage *image,
63 wxCoord x, wxCoord y, const wxBrush & fillBrush,
64 const wxColour& testColour, int style,
65 int LogicalFunction)
7011cf13
JS
66{
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
3a0a5ada
VS
72 int width = image->GetWidth();
73 int height = image->GetHeight();
7011cf13
JS
74
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();
81
82 //initial test :
83 if (style == wxFLOOD_SURFACE)
84 {
85 //if wxFLOOD_SURFACE, if fill colour is same as required, we don't do anything
3a0a5ada
VS
86 if ( image->GetRed(x,y) != r
87 || image->GetGreen(x,y) != g
88 || image->GetBlue (x,y) != b )
7011cf13
JS
89 {
90 //prepare memory for queue
91 //queue save, start, read
92 size_t *qs, *qst, *qr;
93
94 //queue size (physical)
95 long qSz= height * width * 2;
96 qst = new size_t [qSz];
97
98 //temporary x and y locations
99 int xt, yt;
100
101 for (int i=0; i < qSz; i++)
102 qst[i] = 0;
103
104 // start queue
105 qs=qr=qst;
106 *qs=xt=x;
107 qs++;
108 *qs=yt=y;
109 qs++;
110
3a0a5ada 111 image->SetRGB(xt,yt,r,g,b);
7011cf13
JS
112
113 //Main queue loop
114 while(qr!=qs)
115 {
116 //Add new members to queue
117 //Above current pixel
3a0a5ada 118 if(MatchPixel(image,xt,yt-1,width,height,testColour))
7011cf13
JS
119 {
120 *qs=xt;
121 qs++;
122 *qs=yt-1;
123 qs++;
3a0a5ada 124 image->SetRGB(xt,yt-1,r,g,b);
7011cf13
JS
125
126 //Loop back to beginning of queue
127 if(qs>=(qst+qSz)) qs=qst;
128 }
129
130 //Below current pixel
3a0a5ada 131 if(MatchPixel(image,xt,yt+1,width,height,testColour))
7011cf13
JS
132 {
133 *qs=xt;
134 qs++;
135 *qs=yt+1;
136 qs++;
3a0a5ada 137 image->SetRGB(xt,yt+1,r,g,b);
7011cf13
JS
138 if(qs>=(qst+qSz)) qs=qst;
139 }
140
141 //Left of current pixel
3a0a5ada 142 if(MatchPixel(image,xt-1,yt,width,height,testColour))
7011cf13
JS
143 {
144 *qs=xt-1;
145 qs++;
146 *qs=yt;
147 qs++;
3a0a5ada 148 image->SetRGB(xt-1,yt,r,g,b);
7011cf13
JS
149 if(qs>=(qst+qSz)) qs=qst;
150 }
151
152 //Right of current pixel
3a0a5ada 153 if(MatchPixel(image,xt+1,yt,width,height,testColour))
7011cf13
JS
154 {
155 *qs=xt+1;
156 qs++;
157 *qs=yt;
158 qs++;
3a0a5ada 159 image->SetRGB(xt+1,yt,r,g,b);
7011cf13
JS
160 if(qs>=(qst+qSz)) qs=qst;
161 }
162
163 //Retrieve current queue member
164 qr+=2;
165
166 //Loop back to the beginning
167 if(qr>=(qst+qSz)) qr=qst;
168 xt=*qr;
169 yt=*(qr+1);
170
171 //Go Back to beginning of loop
172 }
173
3a0a5ada 174 delete[] qst;
7011cf13
JS
175 }
176 }
177 else
178 {
179 //style is wxFLOOD_BORDER
180 // fill up to testColor border - if already testColour don't do anything
3a0a5ada
VS
181 if ( image->GetRed(x,y) != testColour.Red()
182 || image->GetGreen(x,y) != testColour.Green()
183 || image->GetBlue(x,y) != testColour.Blue() )
184 {
7011cf13
JS
185 //prepare memory for queue
186 //queue save, start, read
187 size_t *qs, *qst, *qr;
188
189 //queue size (physical)
190 long qSz= height * width * 2;
191 qst = new size_t [qSz];
192
193 //temporary x and y locations
194 int xt, yt;
195
196 for (int i=0; i < qSz; i++)
197 qst[i] = 0;
198
199 // start queue
200 qs=qr=qst;
201 *qs=xt=x;
202 qs++;
203 *qs=yt=y;
204 qs++;
205
3a0a5ada 206 image->SetRGB(xt,yt,r,g,b);
7011cf13
JS
207
208 //Main queue loop
3a0a5ada 209 while (qr!=qs)
7011cf13
JS
210 {
211 //Add new members to queue
212 //Above current pixel
3a0a5ada 213 if(!MatchBoundaryPixel(image,xt,yt-1,width,height,fillColour,testColour))
7011cf13
JS
214 {
215 *qs=xt;
216 qs++;
217 *qs=yt-1;
218 qs++;
3a0a5ada 219 image->SetRGB(xt,yt-1,r,g,b);
7011cf13
JS
220
221 //Loop back to beginning of queue
222 if(qs>=(qst+qSz)) qs=qst;
223 }
224
225 //Below current pixel
3a0a5ada 226 if(!MatchBoundaryPixel(image,xt,yt+1,width,height,fillColour,testColour))
7011cf13
JS
227 {
228 *qs=xt;
229 qs++;
230 *qs=yt+1;
231 qs++;
3a0a5ada 232 image->SetRGB(xt,yt+1,r,g,b);
7011cf13
JS
233 if(qs>=(qst+qSz)) qs=qst;
234 }
235
236 //Left of current pixel
3a0a5ada 237 if(!MatchBoundaryPixel(image,xt-1,yt,width,height,fillColour,testColour))
7011cf13
JS
238 {
239 *qs=xt-1;
240 qs++;
241 *qs=yt;
242 qs++;
3a0a5ada 243 image->SetRGB(xt-1,yt,r,g,b);
7011cf13
JS
244 if(qs>=(qst+qSz)) qs=qst;
245 }
246
247 //Right of current pixel
3a0a5ada 248 if(!MatchBoundaryPixel(image,xt+1,yt,width,height,fillColour,testColour))
7011cf13
JS
249 {
250 *qs=xt+1;
251 qs++;
252 *qs=yt;
253 qs++;
3a0a5ada 254 image->SetRGB(xt+1,yt,r,g,b);
7011cf13
JS
255 if(qs>=(qst+qSz)) qs=qst;
256 }
257
258 //Retrieve current queue member
259 qr+=2;
260
261 //Loop back to the beginning
262 if(qr>=(qst+qSz)) qr=qst;
263 xt=*qr;
264 yt=*(qr+1);
265
266 //Go Back to beginning of loop
267 }
268
3a0a5ada 269 delete[] qst;
7011cf13
JS
270 }
271 }
272 //all done,
273}
274
3a0a5ada
VS
275
276void wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
277 const wxColour& col, int style)
278{
279 if (dc->GetBrush().GetStyle() == wxTRANSPARENT)
280 return;
281
282 int height = 0;
283 int width = 0;
284 dc->GetSize(&width, &height);
285
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"));
288
289 //this is much faster than doing the individual pixels
290 wxMemoryDC memdc;
291 wxBitmap bitmap(width, height);
292 memdc.SelectObject(bitmap);
293 memdc.Blit(0, 0, width, height, dc, 0, 0);
294 memdc.SelectObject(wxNullBitmap);
295
296 wxImage image = bitmap.ConvertToImage();
297 wxImageFloodFill(&image, x,y, dc->GetBrush(), col, style,
298 dc->GetLogicalFunction());
299 bitmap = wxBitmap(image);
300 memdc.SelectObject(bitmap);
301 dc->Blit(0, 0, width, height, &memdc, 0, 0);
302 memdc.SelectObject(wxNullBitmap);
303}
304
7011cf13
JS
305#endif // wxUSE_IMAGE
306