]>
git.saurik.com Git - wxWidgets.git/blob - src/common/imagfill.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     FloodFill for wxImage 
   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 */ 
  72     int width 
= image
->GetWidth(); 
  73     int height 
= image
->GetHeight(); 
  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(); 
  83     if (style 
== wxFLOOD_SURFACE
) 
  85        //if wxFLOOD_SURFACE, if fill colour is same as required, we don't do anything 
  86        if (     image
->GetRed(x
,y
)   != r
 
  87              || image
->GetGreen(x
,y
) != g
 
  88              || image
->GetBlue (x
,y
) != b   
) 
  90         //prepare memory for queue 
  91         //queue save, start, read 
  92         size_t *qs
, *qst
, *qr
; 
  94         //queue size (physical) 
  95         long qSz
= height 
* width 
* 2; 
  96         qst 
= new size_t [qSz
]; 
  98         //temporary x and y locations 
 101         for (int i
=0; i 
< qSz
; i
++) 
 111         image
->SetRGB(xt
,yt
,r
,g
,b
); 
 116             //Add new members to queue 
 117             //Above current pixel 
 118             if(MatchPixel(image
,xt
,yt
-1,width
,height
,testColour
)) 
 124                 image
->SetRGB(xt
,yt
-1,r
,g
,b
); 
 126                 //Loop back to beginning of queue 
 127                 if(qs
>=(qst
+qSz
)) qs
=qst
; 
 130             //Below current pixel 
 131             if(MatchPixel(image
,xt
,yt
+1,width
,height
,testColour
)) 
 137                 image
->SetRGB(xt
,yt
+1,r
,g
,b
); 
 138                 if(qs
>=(qst
+qSz
)) qs
=qst
; 
 141             //Left of current pixel 
 142             if(MatchPixel(image
,xt
-1,yt
,width
,height
,testColour
)) 
 148                 image
->SetRGB(xt
-1,yt
,r
,g
,b
); 
 149                 if(qs
>=(qst
+qSz
)) qs
=qst
; 
 152             //Right of current pixel 
 153             if(MatchPixel(image
,xt
+1,yt
,width
,height
,testColour
)) 
 159                 image
->SetRGB(xt
+1,yt
,r
,g
,b
); 
 160                 if(qs
>=(qst
+qSz
)) qs
=qst
; 
 163             //Retrieve current queue member 
 166             //Loop back to the beginning 
 167             if(qr
>=(qst
+qSz
)) qr
=qst
; 
 171         //Go Back to beginning of loop 
 179     //style is wxFLOOD_BORDER 
 180     // fill up to testColor border - if already testColour don't do anything 
 181     if (  image
->GetRed(x
,y
)   != testColour
.Red() 
 182           || image
->GetGreen(x
,y
) != testColour
.Green() 
 183           || image
->GetBlue(x
,y
)  != testColour
.Blue() ) 
 185         //prepare memory for queue 
 186         //queue save, start, read 
 187         size_t *qs
, *qst
, *qr
; 
 189         //queue size (physical) 
 190         long qSz
= height 
* width 
* 2; 
 191         qst 
= new size_t [qSz
]; 
 193         //temporary x and y locations 
 196         for (int i
=0; i 
< qSz
; i
++) 
 206         image
->SetRGB(xt
,yt
,r
,g
,b
); 
 211             //Add new members to queue 
 212             //Above current pixel 
 213             if(!MatchBoundaryPixel(image
,xt
,yt
-1,width
,height
,fillColour
,testColour
)) 
 219                 image
->SetRGB(xt
,yt
-1,r
,g
,b
); 
 221                 //Loop back to beginning of queue 
 222                 if(qs
>=(qst
+qSz
)) qs
=qst
; 
 225             //Below current pixel 
 226             if(!MatchBoundaryPixel(image
,xt
,yt
+1,width
,height
,fillColour
,testColour
)) 
 232                 image
->SetRGB(xt
,yt
+1,r
,g
,b
); 
 233                 if(qs
>=(qst
+qSz
)) qs
=qst
; 
 236             //Left of current pixel 
 237             if(!MatchBoundaryPixel(image
,xt
-1,yt
,width
,height
,fillColour
,testColour
)) 
 243                 image
->SetRGB(xt
-1,yt
,r
,g
,b
); 
 244                 if(qs
>=(qst
+qSz
)) qs
=qst
; 
 247             //Right of current pixel 
 248             if(!MatchBoundaryPixel(image
,xt
+1,yt
,width
,height
,fillColour
,testColour
)) 
 254                 image
->SetRGB(xt
+1,yt
,r
,g
,b
); 
 255                 if(qs
>=(qst
+qSz
)) qs
=qst
; 
 258             //Retrieve current queue member 
 261             //Loop back to the beginning 
 262             if(qr
>=(qst
+qSz
)) qr
=qst
; 
 266         //Go Back to beginning of loop 
 276 bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
, 
 277                    const wxColour
& col
, int style
) 
 279     if (dc
->GetBrush().GetStyle() == wxTRANSPARENT
) 
 284     dc
->GetSize(&width
, &height
); 
 286     //it would be nice to fail if we don't get a sensible size... 
 287     wxCHECK_MSG(width 
>= 1 && height 
>= 1, false, 
 288                 wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC")); 
 290     //this is much faster than doing the individual pixels 
 292     wxBitmap 
bitmap(width
, height
); 
 293     memdc
.SelectObject(bitmap
); 
 294     memdc
.Blit(0, 0, width
, height
, dc
, 0, 0); 
 295     memdc
.SelectObject(wxNullBitmap
); 
 297     wxImage image 
= bitmap
.ConvertToImage(); 
 298     wxImageFloodFill(&image
, x
,y
, dc
->GetBrush(), col
, style
, 
 299                      dc
->GetLogicalFunction()); 
 300     bitmap 
= wxBitmap(image
); 
 301     memdc
.SelectObject(bitmap
); 
 302     dc
->Blit(0, 0, width
, height
, &memdc
, 0, 0); 
 303     memdc
.SelectObject(wxNullBitmap
); 
 308 #endif // wxUSE_IMAGE