| 1 | ///////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: common/pseudodc.cpp |
| 3 | // Purpose: Implementation of the wxPseudoDC Class |
| 4 | // Author: Paul Lanier |
| 5 | // Modified by: |
| 6 | // Created: 05/25/06 |
| 7 | // RCS-ID: $Id$ |
| 8 | // Copyright: (c) wxWidgets team |
| 9 | // Licence: wxWindows licence |
| 10 | ///////////////////////////////////////////////////////////////////////////// |
| 11 | |
| 12 | // For compilers that support precompilation, includes "wx.h". |
| 13 | //include "wx/wxprec.h" |
| 14 | |
| 15 | #undef DEBUG |
| 16 | #include <Python.h> |
| 17 | #include "wx/wxPython/wxPython.h" |
| 18 | #include "wx/wxPython/pseudodc.h" |
| 19 | |
| 20 | // wxList based class definitions |
| 21 | #include <wx/listimpl.cpp> |
| 22 | WX_DEFINE_LIST(pdcOpList); |
| 23 | WX_DEFINE_LIST(pdcObjectList); |
| 24 | |
| 25 | //---------------------------------------------------------------------------- |
| 26 | // Helper functions used for drawing greyed out versions of objects |
| 27 | //---------------------------------------------------------------------------- |
| 28 | wxColour &MakeColourGrey(const wxColour &c) |
| 29 | { |
| 30 | static wxColour rval; |
| 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())); |
| 34 | return rval; |
| 35 | } |
| 36 | wxBrush &GetGreyBrush(wxBrush &brush) |
| 37 | { |
| 38 | static wxBrush b; |
| 39 | wxColour c; |
| 40 | b = brush; |
| 41 | c = MakeColourGrey(brush.GetColour()); |
| 42 | b.SetColour(c); |
| 43 | return b; |
| 44 | } |
| 45 | |
| 46 | wxPen &GetGreyPen(wxPen &pen) |
| 47 | { |
| 48 | static wxPen p; |
| 49 | wxColour c; |
| 50 | p = pen; |
| 51 | c = MakeColourGrey(pen.GetColour()); |
| 52 | p.SetColour(c); |
| 53 | return p; |
| 54 | } |
| 55 | |
| 56 | void GreyOutImage(wxImage &img) |
| 57 | { |
| 58 | unsigned char *data = img.GetData(); |
| 59 | unsigned char r,g,b; |
| 60 | unsigned char mr,mg,mb; |
| 61 | int i, tst; |
| 62 | int len = img.GetHeight()*img.GetWidth()*3; |
| 63 | if (img.HasMask()) |
| 64 | { |
| 65 | mr = img.GetMaskRed(); |
| 66 | mg = img.GetMaskGreen(); |
| 67 | mb = img.GetMaskBlue(); |
| 68 | } |
| 69 | tst=0; |
| 70 | for (i=0;i<len;i+=3) |
| 71 | { |
| 72 | r=data[i]; g=data[i+1]; b=data[i+2]; |
| 73 | if (!img.HasMask() || |
| 74 | r!=mr || g!=mg || b!=mb) |
| 75 | { |
| 76 | if (!tst) |
| 77 | { |
| 78 | tst=1; |
| 79 | } |
| 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; |
| 84 | } |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | wxIcon &GetGreyIcon(wxIcon &icon) |
| 89 | { |
| 90 | wxBitmap bmp; |
| 91 | bmp.CopyFromIcon(icon); |
| 92 | wxImage img = bmp.ConvertToImage(); |
| 93 | GreyOutImage(img); |
| 94 | wxBitmap bmp2(img,32); |
| 95 | static wxIcon rval; |
| 96 | rval.CopyFromBitmap(bmp2); |
| 97 | return rval; |
| 98 | } |
| 99 | |
| 100 | wxBitmap &GetGreyBitmap(wxBitmap &bmp) |
| 101 | { |
| 102 | wxImage img = bmp.ConvertToImage(); |
| 103 | GreyOutImage(img); |
| 104 | static wxBitmap rval(img,32); |
| 105 | return rval; |
| 106 | } |
| 107 | |
| 108 | // ============================================================================ |
| 109 | // various pdcOp class implementation methods |
| 110 | // ============================================================================ |
| 111 | |
| 112 | // ---------------------------------------------------------------------------- |
| 113 | // pdcDrawPolyPolygonOp constructor |
| 114 | // ---------------------------------------------------------------------------- |
| 115 | pdcDrawPolyPolygonOp::pdcDrawPolyPolygonOp(int n, int count[], wxPoint points[], |
| 116 | wxCoord xoffset, wxCoord yoffset, int fillStyle) |
| 117 | { |
| 118 | m_n=n; m_xoffset=xoffset; m_yoffset=yoffset; m_fillStyle=fillStyle; |
| 119 | int total_n=0; |
| 120 | if (n) |
| 121 | { |
| 122 | m_count = new int[n]; |
| 123 | for(int i=0; i<n; i++) |
| 124 | { |
| 125 | total_n+=count[i]; |
| 126 | m_count[i]=count[i]; |
| 127 | } |
| 128 | if (total_n) |
| 129 | { |
| 130 | m_points = new wxPoint[total_n]; |
| 131 | for(int j=0; j<total_n; j++) |
| 132 | m_points[j] = points[j]; |
| 133 | } |
| 134 | else m_points=NULL; |
| 135 | } |
| 136 | else |
| 137 | { |
| 138 | m_points=NULL; |
| 139 | m_count=NULL; |
| 140 | } |
| 141 | m_totaln = total_n; |
| 142 | } |
| 143 | |
| 144 | // ---------------------------------------------------------------------------- |
| 145 | // pdcDrawPolyPolygonOp destructor |
| 146 | // ---------------------------------------------------------------------------- |
| 147 | pdcDrawPolyPolygonOp::~pdcDrawPolyPolygonOp() |
| 148 | { |
| 149 | if (m_points) delete m_points; |
| 150 | if (m_count) delete m_count; |
| 151 | m_points=NULL; |
| 152 | m_count=NULL; |
| 153 | } |
| 154 | |
| 155 | // ---------------------------------------------------------------------------- |
| 156 | // pdcDrawLinesOp constructor |
| 157 | // ---------------------------------------------------------------------------- |
| 158 | pdcDrawLinesOp::pdcDrawLinesOp(int n, wxPoint points[], |
| 159 | wxCoord xoffset, wxCoord yoffset) |
| 160 | { |
| 161 | m_n=n; m_xoffset=xoffset; m_yoffset=yoffset; |
| 162 | if (n) |
| 163 | { |
| 164 | m_points = new wxPoint[n]; |
| 165 | for (int i=0; i<n; i++) |
| 166 | m_points[i] = points[i]; |
| 167 | } |
| 168 | else m_points=NULL; |
| 169 | } |
| 170 | |
| 171 | // ---------------------------------------------------------------------------- |
| 172 | // pdcDrawLinesOp destructor |
| 173 | // ---------------------------------------------------------------------------- |
| 174 | pdcDrawLinesOp::~pdcDrawLinesOp() |
| 175 | { |
| 176 | if (m_points) delete m_points; |
| 177 | m_points=NULL; |
| 178 | } |
| 179 | |
| 180 | // ---------------------------------------------------------------------------- |
| 181 | // pdcDrawPolygonOp constructor |
| 182 | // ---------------------------------------------------------------------------- |
| 183 | pdcDrawPolygonOp::pdcDrawPolygonOp(int n, wxPoint points[], |
| 184 | wxCoord xoffset, wxCoord yoffset, int fillStyle) |
| 185 | { |
| 186 | m_n=n; m_xoffset=xoffset; m_yoffset=yoffset; m_fillStyle=fillStyle; |
| 187 | if (n) |
| 188 | { |
| 189 | m_points = new wxPoint[n]; |
| 190 | for (int i=0; i<n; i++) |
| 191 | m_points[i] = points[i]; |
| 192 | } |
| 193 | else m_points=NULL; |
| 194 | } |
| 195 | |
| 196 | // ---------------------------------------------------------------------------- |
| 197 | // pdcDrawPolygonOp destructor |
| 198 | // ---------------------------------------------------------------------------- |
| 199 | pdcDrawPolygonOp::~pdcDrawPolygonOp() |
| 200 | { |
| 201 | if (m_points) delete m_points; |
| 202 | m_points=NULL; |
| 203 | } |
| 204 | |
| 205 | #if wxUSE_SPLINES |
| 206 | // ---------------------------------------------------------------------------- |
| 207 | // pdcDrawSplineOp constructor |
| 208 | // ---------------------------------------------------------------------------- |
| 209 | pdcDrawSplineOp::pdcDrawSplineOp(int n, wxPoint points[]) |
| 210 | { |
| 211 | m_n=n; |
| 212 | if (n) |
| 213 | { |
| 214 | m_points = new wxPoint[n]; |
| 215 | for(int i=0; i<n; i++) |
| 216 | m_points[i] = points[i]; |
| 217 | } |
| 218 | else m_points=NULL; |
| 219 | } |
| 220 | |
| 221 | // ---------------------------------------------------------------------------- |
| 222 | // pdcDrawSplineOp destructor |
| 223 | // ---------------------------------------------------------------------------- |
| 224 | pdcDrawSplineOp::~pdcDrawSplineOp() |
| 225 | { |
| 226 | if (m_points) delete m_points; |
| 227 | m_points=NULL; |
| 228 | } |
| 229 | #endif // wxUSE_SPLINES |
| 230 | |
| 231 | // ============================================================================ |
| 232 | // pdcObject implementation |
| 233 | // ============================================================================ |
| 234 | // ---------------------------------------------------------------------------- |
| 235 | // DrawToDC - play back the op list to the DC |
| 236 | // ---------------------------------------------------------------------------- |
| 237 | void pdcObject::DrawToDC(wxDC *dc) |
| 238 | { |
| 239 | pdcOpList::Node *node = m_oplist.GetFirst(); |
| 240 | while(node) |
| 241 | { |
| 242 | node->GetData()->DrawToDC(dc, m_greyedout); |
| 243 | node = node->GetNext(); |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | // ---------------------------------------------------------------------------- |
| 248 | // Translate - translate all the operations by some dx,dy |
| 249 | // ---------------------------------------------------------------------------- |
| 250 | void pdcObject::Translate(wxCoord dx, wxCoord dy) |
| 251 | { |
| 252 | pdcOpList::Node *node = m_oplist.GetFirst(); |
| 253 | while(node) |
| 254 | { |
| 255 | node->GetData()->Translate(dx,dy); |
| 256 | node = node->GetNext(); |
| 257 | } |
| 258 | if (m_bounded) |
| 259 | { |
| 260 | m_bounds.x += dx; |
| 261 | m_bounds.y += dy; |
| 262 | } |
| 263 | } |
| 264 | |
| 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) |
| 270 | { |
| 271 | m_greyedout=greyout; |
| 272 | if (greyout) |
| 273 | { |
| 274 | pdcOpList::Node *node = m_oplist.GetFirst(); |
| 275 | pdcOp *obj; |
| 276 | while(node) |
| 277 | { |
| 278 | |
| 279 | obj = node->GetData(); |
| 280 | obj->CacheGrey(); |
| 281 | node = node->GetNext(); |
| 282 | } |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | // ============================================================================ |
| 287 | // wxPseudoDC implementation |
| 288 | // ============================================================================ |
| 289 | |
| 290 | // ---------------------------------------------------------------------------- |
| 291 | // Destructor |
| 292 | // ---------------------------------------------------------------------------- |
| 293 | wxPseudoDC::~wxPseudoDC() |
| 294 | { |
| 295 | // delete all the nodes in the list |
| 296 | RemoveAll(); |
| 297 | |
| 298 | } |
| 299 | |
| 300 | // ---------------------------------------------------------------------------- |
| 301 | // ClearAll - remove all nodes from list |
| 302 | // ---------------------------------------------------------------------------- |
| 303 | void wxPseudoDC::RemoveAll(void) |
| 304 | { |
| 305 | m_objectlist.Clear(); |
| 306 | m_currId = -1; |
| 307 | m_lastObjNode = NULL; |
| 308 | } |
| 309 | |
| 310 | // ---------------------------------------------------------------------------- |
| 311 | // GetLen - return the number of operations in the current op list |
| 312 | // ---------------------------------------------------------------------------- |
| 313 | int wxPseudoDC::GetLen(void) |
| 314 | { |
| 315 | pdcObjectList::Node *pt = m_objectlist.GetFirst(); |
| 316 | int len=0; |
| 317 | while (pt) |
| 318 | { |
| 319 | len += pt->GetData()->GetLen(); |
| 320 | pt = pt->GetNext(); |
| 321 | } |
| 322 | return len; |
| 323 | } |
| 324 | |
| 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 |
| 328 | // return NULL. |
| 329 | // ---------------------------------------------------------------------------- |
| 330 | pdcObjectList::Node *wxPseudoDC::FindObjNode(int id, bool create) |
| 331 | { |
| 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(); |
| 337 | while (pt) |
| 338 | { |
| 339 | if (pt->GetData()->GetId() == id) |
| 340 | { |
| 341 | |
| 342 | // cache this node for future operations |
| 343 | m_lastObjNode = pt; |
| 344 | return pt; |
| 345 | } |
| 346 | pt = pt->GetNext(); |
| 347 | } |
| 348 | // if create then create and return a new node |
| 349 | if (create) |
| 350 | { |
| 351 | // cache this node for future operations |
| 352 | m_lastObjNode = m_objectlist.Append(new pdcObject(id)); |
| 353 | return m_lastObjNode; |
| 354 | } |
| 355 | // otherwise just return NULL |
| 356 | return NULL; |
| 357 | } |
| 358 | |
| 359 | // ---------------------------------------------------------------------------- |
| 360 | // AddToList - Add a node to the list at the end (preserve draw order) |
| 361 | // ---------------------------------------------------------------------------- |
| 362 | void wxPseudoDC::AddToList(pdcOp *newOp) |
| 363 | { |
| 364 | pdcObjectList::Node *pt = FindObjNode(m_currId, true); |
| 365 | pt->GetData()->AddOp(newOp); |
| 366 | } |
| 367 | |
| 368 | // ---------------------------------------------------------------------------- |
| 369 | // ClearID - remove all the operations associated with a single ID |
| 370 | // ---------------------------------------------------------------------------- |
| 371 | void wxPseudoDC::ClearId(int id) |
| 372 | { |
| 373 | pdcObjectList::Node *pt = FindObjNode(id); |
| 374 | if (pt) pt->GetData()->Clear(); |
| 375 | } |
| 376 | |
| 377 | // ---------------------------------------------------------------------------- |
| 378 | // RemoveID - Remove the object node (and all operations) associated with an id |
| 379 | // ---------------------------------------------------------------------------- |
| 380 | void wxPseudoDC::RemoveId(int id) |
| 381 | { |
| 382 | pdcObjectList::Node *pt = FindObjNode(id); |
| 383 | if (pt) |
| 384 | { |
| 385 | if (m_lastObjNode == pt) |
| 386 | m_lastObjNode = NULL; |
| 387 | m_objectlist.DeleteNode(pt); |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | // ---------------------------------------------------------------------------- |
| 392 | // SetIdBounds - Set the bounding rect for a given id |
| 393 | // ---------------------------------------------------------------------------- |
| 394 | void wxPseudoDC::SetIdBounds(int id, wxRect& rect) |
| 395 | { |
| 396 | pdcObjectList::Node *pt = FindObjNode(id, true); |
| 397 | pt->GetData()->SetBounds(rect); |
| 398 | } |
| 399 | |
| 400 | // ---------------------------------------------------------------------------- |
| 401 | // GetIdBounds - Get the bounding rect for a given id |
| 402 | // ---------------------------------------------------------------------------- |
| 403 | void wxPseudoDC::GetIdBounds(int id, wxRect& rect) |
| 404 | { |
| 405 | pdcObjectList::Node *pt = FindObjNode(id); |
| 406 | if (pt && pt->GetData()->IsBounded()) |
| 407 | rect = pt->GetData()->GetBounds(); |
| 408 | else |
| 409 | rect.x = rect.y = rect.width = rect.height = 0; |
| 410 | } |
| 411 | |
| 412 | // ---------------------------------------------------------------------------- |
| 413 | // TranslateId - Translate all the operations of a single id |
| 414 | // ---------------------------------------------------------------------------- |
| 415 | void wxPseudoDC::TranslateId(int id, wxCoord dx, wxCoord dy) |
| 416 | { |
| 417 | pdcObjectList::Node *pt = FindObjNode(id); |
| 418 | if (pt) pt->GetData()->Translate(dx,dy); |
| 419 | } |
| 420 | |
| 421 | // ---------------------------------------------------------------------------- |
| 422 | // DrawIdToDC - Draw a specific id to the dc passed in |
| 423 | // ---------------------------------------------------------------------------- |
| 424 | void wxPseudoDC::DrawIdToDC(int id, wxDC *dc) |
| 425 | { |
| 426 | pdcObjectList::Node *pt = FindObjNode(id); |
| 427 | if (pt) pt->GetData()->DrawToDC(dc); |
| 428 | } |
| 429 | |
| 430 | // ---------------------------------------------------------------------------- |
| 431 | // SetIdGreyedOut - Set the greyedout member of id |
| 432 | // ---------------------------------------------------------------------------- |
| 433 | void wxPseudoDC::SetIdGreyedOut(int id, bool greyout) |
| 434 | { |
| 435 | pdcObjectList::Node *pt = FindObjNode(id); |
| 436 | if (pt) pt->GetData()->SetGreyedOut(greyout); |
| 437 | } |
| 438 | |
| 439 | // ---------------------------------------------------------------------------- |
| 440 | // GetIdGreyedOut - Get the greyedout member of id |
| 441 | // ---------------------------------------------------------------------------- |
| 442 | bool wxPseudoDC::GetIdGreyedOut(int id) |
| 443 | { |
| 444 | pdcObjectList::Node *pt = FindObjNode(id); |
| 445 | if (pt) return pt->GetData()->GetGreyedOut(); |
| 446 | else return false; |
| 447 | } |
| 448 | |
| 449 | // ---------------------------------------------------------------------------- |
| 450 | // FindObjectsByBBox - Return a list of all the ids whose bounding boxes |
| 451 | // contain (x,y) |
| 452 | // ---------------------------------------------------------------------------- |
| 453 | PyObject *wxPseudoDC::FindObjectsByBBox(wxCoord x, wxCoord y) |
| 454 | { |
| 455 | //wxPyBlock_t blocked = wxPyBeginBlockThreads(); |
| 456 | pdcObjectList::Node *pt = m_objectlist.GetFirst(); |
| 457 | pdcObject *obj; |
| 458 | PyObject* pyList = NULL; |
| 459 | pyList = PyList_New(0); |
| 460 | wxRect r; |
| 461 | while (pt) |
| 462 | { |
| 463 | obj = pt->GetData(); |
| 464 | r = obj->GetBounds(); |
| 465 | if (obj->IsBounded() && r.Contains(x,y)) |
| 466 | { |
| 467 | PyObject* pyObj = PyInt_FromLong((long)obj->GetId()); |
| 468 | PyList_Insert(pyList, 0, pyObj); |
| 469 | Py_DECREF(pyObj); |
| 470 | } |
| 471 | pt = pt->GetNext(); |
| 472 | } |
| 473 | //wxPyEndBlockThreads(blocked); |
| 474 | return pyList; |
| 475 | } |
| 476 | |
| 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) |
| 482 | { |
| 483 | //wxPyBlock_t blocked = wxPyBeginBlockThreads(); |
| 484 | pdcObjectList::Node *pt = m_objectlist.GetFirst(); |
| 485 | pdcObject *obj; |
| 486 | PyObject* pyList = NULL; |
| 487 | pyList = PyList_New(0); |
| 488 | wxBrush bgbrush(bg); |
| 489 | wxPen bgpen(bg); |
| 490 | // special case radius = 0 |
| 491 | if (radius == 0) |
| 492 | { |
| 493 | wxBitmap bmp(4,4,24); |
| 494 | wxMemoryDC memdc; |
| 495 | wxColor pix; |
| 496 | wxRect viewrect(x-2,y-2,4,4); |
| 497 | // setup the memdc for rendering |
| 498 | memdc.SelectObject(bmp); |
| 499 | memdc.SetBackground(bgbrush); |
| 500 | memdc.Clear(); |
| 501 | memdc.SetDeviceOrigin(2-x,2-y); |
| 502 | while (pt) |
| 503 | { |
| 504 | obj = pt->GetData(); |
| 505 | if (obj->IsBounded() && obj->GetBounds().Contains(x,y)) |
| 506 | { |
| 507 | // start clean |
| 508 | memdc.SetBrush(bgbrush); |
| 509 | memdc.SetPen(bgpen); |
| 510 | memdc.DrawRectangle(viewrect); |
| 511 | // draw the object |
| 512 | obj->DrawToDC(&memdc); |
| 513 | memdc.GetPixel(x,y,&pix); |
| 514 | // clear and update rgn2 |
| 515 | if (pix != bg) |
| 516 | { |
| 517 | PyObject* pyObj = PyInt_FromLong((long)obj->GetId()); |
| 518 | PyList_Insert(pyList, 0, pyObj); |
| 519 | Py_DECREF(pyObj); |
| 520 | } |
| 521 | } |
| 522 | pt = pt->GetNext(); |
| 523 | } |
| 524 | memdc.SelectObject(wxNullBitmap); |
| 525 | } |
| 526 | else |
| 527 | { |
| 528 | wxRect viewrect(x-radius,y-radius,2*radius,2*radius); |
| 529 | wxBitmap maskbmp(2*radius,2*radius,24); |
| 530 | wxMemoryDC maskdc; |
| 531 | // create bitmap with circle for masking |
| 532 | maskdc.SelectObject(maskbmp); |
| 533 | maskdc.SetBackground(*wxBLACK_BRUSH); |
| 534 | maskdc.Clear(); |
| 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); |
| 540 | wxMemoryDC memdc; |
| 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 |
| 545 | wxRegion rgn2; |
| 546 | while (pt) |
| 547 | { |
| 548 | obj = pt->GetData(); |
| 549 | if (obj->IsBounded() && viewrect.Intersects(obj->GetBounds())) |
| 550 | { |
| 551 | // start clean |
| 552 | //memdc.Clear(); |
| 553 | memdc.SetBrush(bgbrush); |
| 554 | memdc.SetPen(bgpen); |
| 555 | memdc.DrawRectangle(viewrect); |
| 556 | // draw the object |
| 557 | obj->DrawToDC(&memdc); |
| 558 | // remove background color |
| 559 | memdc.SetLogicalFunction(wxXOR); |
| 560 | memdc.SetBrush(bgbrush); |
| 561 | memdc.SetPen(bgpen); |
| 562 | memdc.DrawRectangle(viewrect); |
| 563 | memdc.SetLogicalFunction(wxCOPY); |
| 564 | // AND with circle bitmap |
| 565 | memdc.Blit(x-radius,y-radius,2*radius,2*radius,&maskdc,0,0,wxAND); |
| 566 | // clear and update rgn2 |
| 567 | memdc.SelectObject(wxNullBitmap); |
| 568 | rgn2.Clear(); |
| 569 | rgn2.Union(bmp, *wxBLACK); |
| 570 | //rgn2.Intersect(rgn); |
| 571 | memdc.SelectObject(bmp); |
| 572 | if (!rgn2.IsEmpty()) |
| 573 | { |
| 574 | PyObject* pyObj = PyInt_FromLong((long)obj->GetId()); |
| 575 | PyList_Insert(pyList, 0, pyObj); |
| 576 | Py_DECREF(pyObj); |
| 577 | } |
| 578 | } |
| 579 | pt = pt->GetNext(); |
| 580 | } |
| 581 | maskdc.SelectObject(wxNullBitmap); |
| 582 | memdc.SelectObject(wxNullBitmap); |
| 583 | } |
| 584 | //wxPyEndBlockThreads(blocked); |
| 585 | return pyList; |
| 586 | } |
| 587 | |
| 588 | // ---------------------------------------------------------------------------- |
| 589 | // DrawToDCClipped - play back the op list to the DC but clip any objects |
| 590 | // known to be not in rect. This is a coarse level of |
| 591 | // clipping to speed things up when lots of objects are off |
| 592 | // screen and doesn't affect the dc level clipping |
| 593 | // ---------------------------------------------------------------------------- |
| 594 | void wxPseudoDC::DrawToDCClipped(wxDC *dc, const wxRect& rect) |
| 595 | { |
| 596 | pdcObjectList::Node *pt = m_objectlist.GetFirst(); |
| 597 | pdcObject *obj; |
| 598 | while (pt) |
| 599 | { |
| 600 | obj = pt->GetData(); |
| 601 | if (!obj->IsBounded() || rect.Intersects(obj->GetBounds())) |
| 602 | obj->DrawToDC(dc); |
| 603 | pt = pt->GetNext(); |
| 604 | } |
| 605 | } |
| 606 | void wxPseudoDC::DrawToDCClippedRgn(wxDC *dc, const wxRegion& region) |
| 607 | { |
| 608 | pdcObjectList::Node *pt = m_objectlist.GetFirst(); |
| 609 | pdcObject *obj; |
| 610 | while (pt) |
| 611 | { |
| 612 | obj = pt->GetData(); |
| 613 | if (!obj->IsBounded() || |
| 614 | (region.Contains(obj->GetBounds()) != wxOutRegion)) |
| 615 | obj->DrawToDC(dc); |
| 616 | pt = pt->GetNext(); |
| 617 | } |
| 618 | } |
| 619 | |
| 620 | // ---------------------------------------------------------------------------- |
| 621 | // DrawToDC - play back the op list to the DC |
| 622 | // ---------------------------------------------------------------------------- |
| 623 | void wxPseudoDC::DrawToDC(wxDC *dc) |
| 624 | { |
| 625 | pdcObjectList::Node *pt = m_objectlist.GetFirst(); |
| 626 | while (pt) |
| 627 | { |
| 628 | pt->GetData()->DrawToDC(dc); |
| 629 | pt = pt->GetNext(); |
| 630 | } |
| 631 | } |
| 632 | |