]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/src/pseudodc.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/pseudodc.cpp 
   3 // Purpose:     Implementation of the wxPseudoDC Class 
   8 // Copyright:   (c) wxWidgets team 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 //include "wx/wxprec.h" 
  17 #include "wx/wxPython/wxPython.h" 
  18 #include "wx/wxPython/pseudodc.h" 
  20 // wxList based class definitions 
  21 #include <wx/listimpl.cpp> 
  22 WX_DEFINE_LIST(pdcOpList
); 
  23 WX_DEFINE_LIST(pdcObjectList
); 
  25 //---------------------------------------------------------------------------- 
  26 // Helper functions used for drawing greyed out versions of objects 
  27 //---------------------------------------------------------------------------- 
  28 wxColour 
&MakeColourGrey(const wxColour 
&c
) 
  31     rval
.Set(byte((230-c
.Red())*0.7+c
.Red()), 
  32              byte((230-c
.Green())*0.7+c
.Green()), 
  33              byte((230-c
.Blue())*0.7+c
.Blue())); 
  36 wxBrush 
&GetGreyBrush(wxBrush 
&brush
) 
  41         c 
= MakeColourGrey(brush
.GetColour()); 
  46 wxPen 
&GetGreyPen(wxPen 
&pen
) 
  51         c 
= MakeColourGrey(pen
.GetColour()); 
  56 void GreyOutImage(wxImage 
&img
) 
  58     unsigned char *data 
= img
.GetData(); 
  60     unsigned char mr
,mg
,mb
; 
  62     int len 
= img
.GetHeight()*img
.GetWidth()*3; 
  65         mr 
= img
.GetMaskRed(); 
  66         mg 
= img
.GetMaskGreen(); 
  67         mb 
= img
.GetMaskBlue(); 
  72         r
=data
[i
]; g
=data
[i
+1]; b
=data
[i
+2]; 
  74             r
!=mr 
|| g
!=mg 
|| b
!=mb
) 
  80             r 
= (unsigned char)((230.0-r
)*0.7+r
); 
  81             g 
= (unsigned char)((230.0-g
)*0.7+g
); 
  82             b 
= (unsigned char)((230.0-b
)*0.7+b
); 
  83             data
[i
]=r
; data
[i
+1]=g
; data
[i
+2]=b
; 
  88 wxIcon 
&GetGreyIcon(wxIcon 
&icon
) 
  91     bmp
.CopyFromIcon(icon
); 
  92     wxImage img 
= bmp
.ConvertToImage(); 
  94     wxBitmap 
bmp2(img
,32); 
  96     rval
.CopyFromBitmap(bmp2
); 
 100 wxBitmap 
&GetGreyBitmap(wxBitmap 
&bmp
) 
 102     wxImage img 
= bmp
.ConvertToImage(); 
 104     static wxBitmap 
rval(img
,32); 
 108 // ============================================================================ 
 109 // various pdcOp class implementation methods 
 110 // ============================================================================ 
 112 // ---------------------------------------------------------------------------- 
 113 // pdcDrawPolyPolygonOp constructor 
 114 // ---------------------------------------------------------------------------- 
 115 pdcDrawPolyPolygonOp::pdcDrawPolyPolygonOp(int n
, int count
[], wxPoint points
[], 
 116                  wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)  
 118     m_n
=n
; m_xoffset
=xoffset
; m_yoffset
=yoffset
; m_fillStyle
=fillStyle
; 
 122         m_count 
= new int[n
]; 
 123         for(int i
=0; i
<n
; i
++)  
 130             m_points 
= new wxPoint
[total_n
]; 
 131             for(int j
=0; j
<total_n
; j
++) 
 132                 m_points
[j
] = points
[j
]; 
 144 // ---------------------------------------------------------------------------- 
 145 // pdcDrawPolyPolygonOp destructor 
 146 // ---------------------------------------------------------------------------- 
 147 pdcDrawPolyPolygonOp::~pdcDrawPolyPolygonOp() 
 149     if (m_points
) delete m_points
; 
 150     if (m_count
) delete m_count
; 
 155 // ---------------------------------------------------------------------------- 
 156 // pdcDrawLinesOp constructor 
 157 // ---------------------------------------------------------------------------- 
 158 pdcDrawLinesOp::pdcDrawLinesOp(int n
, wxPoint points
[], 
 159              wxCoord xoffset
, wxCoord yoffset
) 
 161     m_n
=n
; m_xoffset
=xoffset
; m_yoffset
=yoffset
; 
 164         m_points 
= new wxPoint
[n
]; 
 165         for (int i
=0; i
<n
; i
++) 
 166             m_points
[i
] = points
[i
]; 
 171 // ---------------------------------------------------------------------------- 
 172 // pdcDrawLinesOp destructor 
 173 // ---------------------------------------------------------------------------- 
 174 pdcDrawLinesOp::~pdcDrawLinesOp() 
 176     if (m_points
) delete m_points
; 
 180 // ---------------------------------------------------------------------------- 
 181 // pdcDrawPolygonOp constructor 
 182 // ---------------------------------------------------------------------------- 
 183 pdcDrawPolygonOp::pdcDrawPolygonOp(int n
, wxPoint points
[], 
 184              wxCoord xoffset
, wxCoord yoffset
, int fillStyle
) 
 186     m_n
=n
; m_xoffset
=xoffset
; m_yoffset
=yoffset
; m_fillStyle
=fillStyle
; 
 189         m_points 
= new wxPoint
[n
]; 
 190         for (int i
=0; i
<n
; i
++) 
 191             m_points
[i
] = points
[i
]; 
 196 // ---------------------------------------------------------------------------- 
 197 // pdcDrawPolygonOp destructor 
 198 // ---------------------------------------------------------------------------- 
 199 pdcDrawPolygonOp::~pdcDrawPolygonOp() 
 201     if (m_points
) delete m_points
; 
 206 // ---------------------------------------------------------------------------- 
 207 // pdcDrawSplineOp constructor 
 208 // ---------------------------------------------------------------------------- 
 209 pdcDrawSplineOp::pdcDrawSplineOp(int n
, wxPoint points
[]) 
 214         m_points 
= new wxPoint
[n
]; 
 215         for(int i
=0; i
<n
; i
++) 
 216             m_points
[i
] = points
[i
]; 
 221 // ---------------------------------------------------------------------------- 
 222 // pdcDrawSplineOp destructor 
 223 // ---------------------------------------------------------------------------- 
 224 pdcDrawSplineOp::~pdcDrawSplineOp() 
 226     if (m_points
) delete m_points
; 
 229 #endif // wxUSE_SPLINES 
 231 // ============================================================================ 
 232 // pdcObject implementation 
 233 // ============================================================================ 
 234 // ---------------------------------------------------------------------------- 
 235 // DrawToDC - play back the op list to the DC  
 236 // ---------------------------------------------------------------------------- 
 237 void pdcObject::DrawToDC(wxDC 
*dc
) 
 239     pdcOpList::Node 
*node 
= m_oplist
.GetFirst();  
 242         node
->GetData()->DrawToDC(dc
, m_greyedout
); 
 243         node 
= node
->GetNext(); 
 247 // ---------------------------------------------------------------------------- 
 248 // Translate - translate all the operations by some dx,dy 
 249 // ---------------------------------------------------------------------------- 
 250 void pdcObject::Translate(wxCoord dx
, wxCoord dy
) 
 252     pdcOpList::Node 
*node 
= m_oplist
.GetFirst();  
 255         node
->GetData()->Translate(dx
,dy
); 
 256         node 
= node
->GetNext(); 
 265 // ---------------------------------------------------------------------------- 
 266 // SetGreyedOut - set the greyout member and cache grey versions of everything 
 267 // if greyout is true 
 268 // ---------------------------------------------------------------------------- 
 269 void pdcObject::SetGreyedOut(bool greyout
)  
 274                 pdcOpList::Node 
*node 
= m_oplist
.GetFirst();  
 279                         obj 
= node
->GetData(); 
 281                         node 
= node
->GetNext(); 
 286 // ============================================================================ 
 287 // wxPseudoDC implementation 
 288 // ============================================================================ 
 290 // ---------------------------------------------------------------------------- 
 292 // ---------------------------------------------------------------------------- 
 293 wxPseudoDC::~wxPseudoDC() 
 295     // delete all the nodes in the list 
 300 // ---------------------------------------------------------------------------- 
 301 // ClearAll - remove all nodes from list 
 302 // ---------------------------------------------------------------------------- 
 303 void wxPseudoDC::RemoveAll(void) 
 305     m_objectlist
.Clear(); 
 307         m_lastObjNode 
= NULL
; 
 310 // ---------------------------------------------------------------------------- 
 311 // GetLen - return the number of operations in the current op list 
 312 // ---------------------------------------------------------------------------- 
 313 int wxPseudoDC::GetLen(void) 
 315     pdcObjectList::Node 
*pt 
= m_objectlist
.GetFirst(); 
 319         len 
+= pt
->GetData()->GetLen(); 
 325 // ---------------------------------------------------------------------------- 
 326 // FindObjNode - find and return an object node by id.  If node doesn't exist 
 327 //               and create is true then create one and return it.  Otherwise 
 329 // ---------------------------------------------------------------------------- 
 330 pdcObjectList::Node 
*wxPseudoDC::FindObjNode(int id
, bool create
) 
 332     // see if last operation was for same id 
 333     if (m_lastObjNode 
&& m_lastObjNode
->GetData()->GetId() == id
) 
 334         return m_lastObjNode
; 
 335     // if not then search for it 
 336     pdcObjectList::Node 
*pt 
= m_objectlist
.GetFirst(); 
 339         if (pt
->GetData()->GetId() == id
) 
 342             // cache this node for future operations 
 348     // if create then create and return a new node 
 351         // cache this node for future operations 
 352         m_lastObjNode 
= m_objectlist
.Append(new pdcObject(id
)); 
 353         return m_lastObjNode
; 
 355     // otherwise just return NULL 
 359 // ---------------------------------------------------------------------------- 
 360 // AddToList - Add a node to the list at the end (preserve draw order) 
 361 // ---------------------------------------------------------------------------- 
 362 void wxPseudoDC::AddToList(pdcOp 
*newOp
) 
 364     pdcObjectList::Node 
*pt 
= FindObjNode(m_currId
, true); 
 365     pt
->GetData()->AddOp(newOp
); 
 368 // ---------------------------------------------------------------------------- 
 369 // ClearID - remove all the operations associated with a single ID 
 370 // ---------------------------------------------------------------------------- 
 371 void wxPseudoDC::ClearId(int id
) 
 373     pdcObjectList::Node 
*pt 
= FindObjNode(id
); 
 374     if (pt
) pt
->GetData()->Clear(); 
 377 // ---------------------------------------------------------------------------- 
 378 // RemoveID - Remove the object node (and all operations) associated with an id 
 379 // ---------------------------------------------------------------------------- 
 380 void wxPseudoDC::RemoveId(int id
) 
 382     pdcObjectList::Node 
*pt 
= FindObjNode(id
); 
 385         if (m_lastObjNode 
== pt
) 
 386             m_lastObjNode 
= NULL
; 
 387         m_objectlist
.DeleteNode(pt
); 
 391 // ---------------------------------------------------------------------------- 
 392 // SetIdBounds - Set the bounding rect for a given id 
 393 // ---------------------------------------------------------------------------- 
 394 void wxPseudoDC::SetIdBounds(int id
, wxRect
& rect
) 
 396     pdcObjectList::Node 
*pt 
= FindObjNode(id
, true); 
 397     pt
->GetData()->SetBounds(rect
); 
 400 // ---------------------------------------------------------------------------- 
 401 // GetIdBounds - Get the bounding rect for a given id 
 402 // ---------------------------------------------------------------------------- 
 403 void wxPseudoDC::GetIdBounds(int id
, wxRect
& rect
) 
 405     pdcObjectList::Node 
*pt 
= FindObjNode(id
); 
 406         if (pt 
&& pt
->GetData()->IsBounded()) 
 407                 rect 
= pt
->GetData()->GetBounds(); 
 409                 rect
.x 
= rect
.y 
= rect
.width 
= rect
.height 
= 0; 
 412 // ---------------------------------------------------------------------------- 
 413 // TranslateId - Translate all the operations of a single id 
 414 // ---------------------------------------------------------------------------- 
 415 void wxPseudoDC::TranslateId(int id
, wxCoord dx
, wxCoord dy
) 
 417     pdcObjectList::Node 
*pt 
= FindObjNode(id
); 
 418     if (pt
) pt
->GetData()->Translate(dx
,dy
); 
 421 // ---------------------------------------------------------------------------- 
 422 // DrawIdToDC - Draw a specific id to the dc passed in 
 423 // ---------------------------------------------------------------------------- 
 424 void wxPseudoDC::DrawIdToDC(int id
, wxDC 
*dc
) 
 426     pdcObjectList::Node 
*pt 
= FindObjNode(id
); 
 427     if (pt
) pt
->GetData()->DrawToDC(dc
); 
 430 // ---------------------------------------------------------------------------- 
 431 // SetIdGreyedOut - Set the greyedout member of id 
 432 // ---------------------------------------------------------------------------- 
 433 void wxPseudoDC::SetIdGreyedOut(int id
, bool greyout
) 
 435     pdcObjectList::Node 
*pt 
= FindObjNode(id
); 
 436     if (pt
) pt
->GetData()->SetGreyedOut(greyout
); 
 439 // ---------------------------------------------------------------------------- 
 440 // GetIdGreyedOut - Get the greyedout member of id 
 441 // ---------------------------------------------------------------------------- 
 442 bool wxPseudoDC::GetIdGreyedOut(int id
) 
 444     pdcObjectList::Node 
*pt 
= FindObjNode(id
); 
 445     if (pt
) return pt
->GetData()->GetGreyedOut(); 
 449 // ---------------------------------------------------------------------------- 
 450 // FindObjectsByBBox - Return a list of all the ids whose bounding boxes 
 452 // ---------------------------------------------------------------------------- 
 453 PyObject 
*wxPseudoDC::FindObjectsByBBox(wxCoord x
, wxCoord y
) 
 455     //wxPyBlock_t blocked = wxPyBeginBlockThreads(); 
 456     pdcObjectList::Node 
*pt 
= m_objectlist
.GetFirst(); 
 458     PyObject
* pyList 
= NULL
; 
 459     pyList 
= PyList_New(0); 
 464         r 
= obj
->GetBounds(); 
 465         if (obj
->IsBounded() && r
.Contains(x
,y
)) 
 467             PyObject
* pyObj 
= PyInt_FromLong((long)obj
->GetId()); 
 468             PyList_Insert(pyList
, 0, pyObj
); 
 473     //wxPyEndBlockThreads(blocked); 
 477 // ---------------------------------------------------------------------------- 
 478 // FindObjects - Return a list of all the ids that draw to (x,y) 
 479 // ---------------------------------------------------------------------------- 
 480 PyObject 
*wxPseudoDC::FindObjects(wxCoord x
, wxCoord y
,  
 481                                   wxCoord radius
, const wxColor
& bg
) 
 483     //wxPyBlock_t blocked = wxPyBeginBlockThreads(); 
 484     pdcObjectList::Node 
*pt 
= m_objectlist
.GetFirst(); 
 486     PyObject
* pyList 
= NULL
; 
 487     pyList 
= PyList_New(0); 
 490     // special case radius = 0 
 493         wxBitmap 
bmp(4,4,24); 
 496         wxRect 
viewrect(x
-2,y
-2,4,4); 
 497         // setup the memdc for rendering 
 498         memdc
.SelectObject(bmp
); 
 499         memdc
.SetBackground(bgbrush
); 
 501         memdc
.SetDeviceOrigin(2-x
,2-y
); 
 505             if (obj
->IsBounded() && obj
->GetBounds().Contains(x
,y
)) 
 508                 memdc
.SetBrush(bgbrush
); 
 510                 memdc
.DrawRectangle(viewrect
); 
 512                 obj
->DrawToDC(&memdc
); 
 513                 memdc
.GetPixel(x
,y
,&pix
); 
 514                 // clear and update rgn2 
 517                     PyObject
* pyObj 
= PyInt_FromLong((long)obj
->GetId()); 
 518                     PyList_Insert(pyList
, 0, pyObj
); 
 524         memdc
.SelectObject(wxNullBitmap
); 
 528         wxRect 
viewrect(x
-radius
,y
-radius
,2*radius
,2*radius
); 
 529         wxBitmap 
maskbmp(2*radius
,2*radius
,24); 
 531         // create bitmap with circle for masking 
 532         maskdc
.SelectObject(maskbmp
); 
 533         maskdc
.SetBackground(*wxBLACK_BRUSH
); 
 535         maskdc
.SetBrush(*wxWHITE_BRUSH
); 
 536         maskdc
.SetPen(*wxWHITE_PEN
); 
 537         maskdc
.DrawCircle(radius
,radius
,radius
); 
 538         // now setup a memdc for rendering our object 
 539         wxBitmap 
bmp(2*radius
,2*radius
,24); 
 541         memdc
.SelectObject(bmp
); 
 542         // set the origin so (x,y) is in the bmp center 
 543         memdc
.SetDeviceOrigin(radius
-x
,radius
-y
); 
 544         // a region will be used to see if the result is empty 
 549             if (obj
->IsBounded() && viewrect
.Intersects(obj
->GetBounds())) 
 553                 memdc
.SetBrush(bgbrush
); 
 555                 memdc
.DrawRectangle(viewrect
); 
 557                 obj
->DrawToDC(&memdc
); 
 558                 // remove background color 
 559                 memdc
.SetLogicalFunction(wxXOR
); 
 560                 memdc
.SetBrush(bgbrush
); 
 562                 memdc
.DrawRectangle(viewrect
); 
 563                 memdc
.SetLogicalFunction(wxCOPY
); 
 565                 // wxAND is not supported on wxMac, but it doesn't seem to 
 566                 // hurt anything to use wxCOPY instead... 
 567                 memdc
.Blit(x
-radius
,y
-radius
,2*radius
,2*radius
,&maskdc
,0,0,wxCOPY
); 
 569                 // AND with circle bitmap 
 570                 memdc
.Blit(x
-radius
,y
-radius
,2*radius
,2*radius
,&maskdc
,0,0,wxAND
); 
 572                 // clear and update rgn2 
 573                 memdc
.SelectObject(wxNullBitmap
); 
 575                 rgn2
.Union(bmp
, *wxBLACK
); 
 576                 //rgn2.Intersect(rgn); 
 577                 memdc
.SelectObject(bmp
); 
 580                     PyObject
* pyObj 
= PyInt_FromLong((long)obj
->GetId()); 
 581                     PyList_Insert(pyList
, 0, pyObj
); 
 587         maskdc
.SelectObject(wxNullBitmap
); 
 588         memdc
.SelectObject(wxNullBitmap
); 
 590     //wxPyEndBlockThreads(blocked); 
 594 // ---------------------------------------------------------------------------- 
 595 // DrawToDCClipped - play back the op list to the DC but clip any objects 
 596 //                   known to be not in rect.  This is a coarse level of  
 597 //                   clipping to speed things up when lots of objects are off  
 598 //                   screen and doesn't affect the dc level clipping 
 599 // ---------------------------------------------------------------------------- 
 600 void wxPseudoDC::DrawToDCClipped(wxDC 
*dc
, const wxRect
& rect
) 
 602     pdcObjectList::Node 
*pt 
= m_objectlist
.GetFirst(); 
 607         if (!obj
->IsBounded() || rect
.Intersects(obj
->GetBounds())) 
 612 void wxPseudoDC::DrawToDCClippedRgn(wxDC 
*dc
, const wxRegion
& region
) 
 614     pdcObjectList::Node 
*pt 
= m_objectlist
.GetFirst(); 
 619         if (!obj
->IsBounded() ||  
 620                     (region
.Contains(obj
->GetBounds()) != wxOutRegion
)) 
 626 // ---------------------------------------------------------------------------- 
 627 // DrawToDC - play back the op list to the DC  
 628 // ---------------------------------------------------------------------------- 
 629 void wxPseudoDC::DrawToDC(wxDC 
*dc
) 
 631     pdcObjectList::Node 
*pt 
= m_objectlist
.GetFirst(); 
 634         pt
->GetData()->DrawToDC(dc
);