]> git.saurik.com Git - wxWidgets.git/blob - src/os2/region.cpp
bc036241c21e7694eba45121f8bb8da5ab10fed7
[wxWidgets.git] / src / os2 / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // File: region.cpp
3 // Purpose: Region class
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/15/99
7 // RCS-ID: $Id$
8 // Copyright: (c) Davdi Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #include "wx/os2/region.h"
16 #include "wx/gdicmn.h"
17
18 #include "wx/window.h"
19 #include "wx/os2/private.h"
20
21 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
22 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
23
24 //-----------------------------------------------------------------------------
25 // wxRegionRefData implementation
26 //-----------------------------------------------------------------------------
27
28 class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
29 public:
30 wxRegionRefData()
31 {
32 m_hRegion = 0;
33 }
34
35 wxRegionRefData(const wxRegionRefData& rData)
36 {
37 RGNRECT vRgnData;
38 PRECTL pRect = NULL;
39
40 if (::GpiQueryRegionRects( rData.m_hPS // Pres space
41 ,rData.m_hRegion // Handle of region to query
42 ,NULL // Return all RECTs
43 ,&vRgnData // Will contain number or RECTs in region
44 ,NULL // NULL to return number of RECTs
45 ))
46 {
47 pRect = new RECTL[vRgnData.crcReturned];
48 vRgnData.crc = vRgnData.crcReturned;
49 vRgnData.ircStart = 1;
50 if (::GpiQueryRegionRects( rData.m_hPS // Pres space of source
51 ,rData.m_hRegion // Handle of source region
52 ,NULL // Return all RECTs
53 ,&vRgnData // Operations set to return rects
54 ,pRect // Will contain the actual RECTS
55 ))
56 {
57 m_hRegion = ::GpiCreateRegion( rData.m_hPS
58 ,vRgnData.crcReturned
59 ,pRect
60 );
61 m_hPS = rData.m_hPS;
62 }
63 delete [] pRect;
64 }
65 }
66
67 ~wxRegionRefData()
68 {
69 ::GpiDestroyRegion(m_hPS, m_hRegion);
70 }
71
72 HRGN m_hRegion;
73 HPS m_hPS;
74 };
75
76 #define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion)
77
78 //-----------------------------------------------------------------------------
79 // wxRegion
80 //-----------------------------------------------------------------------------
81
82 /*!
83 * Create an empty region.
84 */
85 wxRegion::wxRegion()
86 {
87 m_refData = new wxRegionRefData;
88 } // end of wxRegion::wxRegion
89
90 wxRegion::wxRegion(
91 WXHRGN hRegion
92 )
93 {
94 m_refData = new wxRegionRefData;
95 M_REGION = (HRGN) hRegion;
96 } // end of wxRegion::wxRegion
97
98 wxRegion::wxRegion(
99 wxCoord x
100 , wxCoord y
101 , wxCoord vWidth
102 , wxCoord vHeight
103 )
104 {
105 RECTL vRect;
106 SIZEL vSize = {0, 0};
107 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
108 HDC hDC = ::DevOpenDC( vHabmain
109 ,OD_MEMORY
110 ,"*"
111 ,5L
112 ,(PDEVOPENDATA)&vDop
113 ,NULLHANDLE
114 );
115
116
117 vRect.xLeft = x;
118 vRect.xRight = x + vWidth;
119 vRect.yBottom = y;
120 vRect.yTop = y + vHeight;
121
122 m_refData = new wxRegionRefData;
123
124 //
125 // Need a PS to create a Region
126 //
127 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
128 ,hDC
129 ,&vSize
130 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
131 );
132 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
133 ,1
134 ,&vRect
135 );
136 } // end of wxRegion::wxRegion
137
138 wxRegion::wxRegion(
139 const wxPoint& rTopLeft
140 , const wxPoint& rBottomRight
141 )
142 {
143 RECTL vRect;
144 SIZEL vSize = {0, 0};
145 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
146 HDC hDC = ::DevOpenDC( vHabmain
147 ,OD_MEMORY
148 ,"*"
149 ,5L
150 ,(PDEVOPENDATA)&vDop
151 ,NULLHANDLE
152 );
153
154 vRect.xLeft = rTopLeft.x;
155 vRect.xRight = rBottomRight.x;
156 vRect.yBottom = rBottomRight.y;
157 vRect.yTop = rTopLeft.y;
158
159 m_refData = new wxRegionRefData;
160
161 //
162 // Need a PS to create a Region
163 //
164 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
165 ,hDC
166 ,&vSize
167 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
168 );
169 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
170 ,1
171 ,&vRect
172 );
173 } // end of wxRegion::wxRegion
174
175 wxRegion::wxRegion(
176 const wxRect& rRect
177 )
178 {
179 RECTL vRect;
180 SIZEL vSize = {0, 0};
181 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
182 HDC hDC = ::DevOpenDC( vHabmain
183 ,OD_MEMORY
184 ,"*"
185 ,5L
186 ,(PDEVOPENDATA)&vDop
187 ,NULLHANDLE
188 );
189
190
191 vRect.xLeft = rRect.x;
192 vRect.xRight = rRect.x + rRect.width;
193 vRect.yBottom = rRect.y;
194 vRect.yTop = rRect.y + rRect.height;
195
196 m_refData = new wxRegionRefData;
197
198 //
199 // Need a PS to create a Region
200 //
201 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain
202 ,hDC
203 ,&vSize
204 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC
205 );
206 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
207 ,1
208 ,&vRect
209 );
210 } // end of wxRegion::wxRegion
211
212 //
213 // Destroy the region.
214 //
215 wxRegion::~wxRegion()
216 {
217 } // end of wxRegion::~wxRegion
218
219 //-----------------------------------------------------------------------------
220 //# Modify region
221 //-----------------------------------------------------------------------------
222
223 //
224 // Clear current region
225 //
226 void wxRegion::Clear()
227 {
228 UnRef();
229 } // end of wxRegion::Clear
230
231 //
232 // Combine rectangle (x, y, w, h) with this.
233 //
234 bool wxRegion::Combine(
235 wxCoord x
236 , wxCoord y
237 , wxCoord vWidth
238 , wxCoord vHeight
239 , wxRegionOp eOp
240 )
241 {
242 //
243 // Don't change shared data
244 //
245 if (!m_refData)
246 {
247 m_refData = new wxRegionRefData();
248 }
249 else if (m_refData->GetRefCount() > 1)
250 {
251 wxRegionRefData* pRef = (wxRegionRefData*)m_refData;
252
253 UnRef();
254 m_refData = new wxRegionRefData(*pRef);
255 }
256
257 //
258 // If ref count is 1, that means it's 'ours' anyway so no action.
259 //
260 RECTL vRect;
261
262 vRect.xLeft = x;
263 vRect.xRight = x + vWidth;
264 vRect.yBottom = y;
265 vRect.yTop = y + vHeight;
266
267 HRGN hRgn = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
268 ,1
269 ,&vRect
270 );
271 LONG lMode = 0L;
272
273 switch (eOp)
274 {
275 case wxRGN_AND:
276 lMode = CRGN_AND;
277 break;
278
279 case wxRGN_OR:
280 lMode = CRGN_OR;
281 break;
282
283 case wxRGN_XOR:
284 lMode = CRGN_XOR;
285 break;
286
287 case wxRGN_DIFF:
288 lMode = CRGN_DIFF;
289 break;
290
291 case wxRGN_COPY:
292 default:
293 lMode = CRGN_COPY;
294 break;
295 }
296 bool bSuccess = ::GpiCombineRegion( ((wxRegionRefData*)m_refData)->m_hPS
297 ,M_REGION
298 ,M_REGION
299 ,hRgn
300 ,lMode
301 );
302 ::GpiDestroyRegion ( ((wxRegionRefData*)m_refData)->m_hPS
303 ,hRgn
304 );
305
306 return bSuccess;
307 } // end of wxRegion::Combine
308
309 //
310 // Union region with this.
311 //
312 bool wxRegion::Combine(
313 const wxRegion& rRegion
314 , wxRegionOp eOp
315 )
316 {
317 if (rRegion.Empty())
318 return FALSE;
319
320 //
321 // Don't change shared data
322 //
323 if (!m_refData)
324 {
325 m_refData = new wxRegionRefData();
326 }
327 else if (m_refData->GetRefCount() > 1)
328 {
329 wxRegionRefData* pRef = (wxRegionRefData*)m_refData;
330
331 UnRef();
332 m_refData = new wxRegionRefData(*pRef);
333 }
334
335 LONG lMode = 0;
336
337 switch (eOp)
338 {
339 case wxRGN_AND:
340 lMode = CRGN_AND;
341 break;
342
343 case wxRGN_OR:
344 lMode = CRGN_OR;
345 break;
346
347 case wxRGN_XOR:
348 lMode = CRGN_XOR;
349 break;
350
351 case wxRGN_DIFF:
352 lMode = CRGN_DIFF;
353 break;
354
355 case wxRGN_COPY:
356 default:
357 lMode = CRGN_COPY;
358 break;
359 }
360 return (::GpiCombineRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
361 ,M_REGION
362 ,M_REGION
363 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion
364 ,lMode
365 ) != RGN_ERROR);
366 } // end of wxRegion::Combine
367
368 bool wxRegion::Combine(
369 const wxRect& rRect
370 , wxRegionOp eOp
371 )
372 {
373 return Combine( rRect.GetLeft()
374 ,rRect.GetTop()
375 ,rRect.GetWidth()
376 ,rRect.GetHeight()
377 ,eOp
378 );
379 } // end of wxRegion::Combine
380
381 //-----------------------------------------------------------------------------
382 //# Information on region
383 //-----------------------------------------------------------------------------
384
385 //
386 // Outer bounds of region
387 //
388 void wxRegion::GetBox(
389 wxCoord& x
390 , wxCoord& y
391 , wxCoord& vWidth
392 , wxCoord& vHeight
393 ) const
394 {
395 if (m_refData)
396 {
397 RECTL vRect;
398
399 ::GpiQueryRegionBox( ((wxRegionRefData*)m_refData)->m_hPS
400 ,M_REGION
401 ,&vRect
402 );
403 x = vRect.xLeft;
404 y = vRect.yTop;
405 vWidth = vRect.xRight - vRect.xLeft;
406 vHeight = vRect.yTop - vRect.yBottom;
407 }
408 else
409 {
410 x = y = vWidth = vHeight = 0L;
411 }
412 } // end of wxRegion::GetBox
413
414 wxRect wxRegion::GetBox() const
415 {
416 wxCoord x, y, w, h;
417 GetBox(x, y, w, h);
418 return wxRect(x, y, w, h);
419 }
420
421 //
422 // Is region empty?
423 //
424 bool wxRegion::Empty() const
425 {
426 wxCoord x;
427 wxCoord y;
428 wxCoord vWidth;
429 wxCoord vHeight;
430
431 if (M_REGION == 0)
432 return TRUE;
433
434 GetBox( x
435 ,y
436 ,vWidth
437 ,vHeight
438 );
439 return ((vWidth == 0) && (vHeight == 0));
440 } // end of wxRegion::Empty
441
442 //-----------------------------------------------------------------------------
443 // Tests
444 //-----------------------------------------------------------------------------
445
446 //
447 // Does the region contain the point (x,y)?
448 wxRegionContain wxRegion::Contains(
449 wxCoord x
450 , wxCoord y
451 ) const
452 {
453 bool bOK = FALSE;
454 POINTL vPoint;
455
456 vPoint.x = x;
457 vPoint.y = y;
458
459 if (!m_refData)
460 return wxOutRegion;
461
462 LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS
463 ,M_REGION
464 ,&vPoint
465 );
466 if (lInside == PRGN_INSIDE)
467 return wxInRegion;
468 return wxOutRegion;
469 } // end of wxRegion::Contains
470
471 //
472 // Does the region contain the point pt?
473 //
474 wxRegionContain wxRegion::Contains(
475 const wxPoint& rPoint
476 ) const
477 {
478 POINTL vPoint = { rPoint.x, rPoint.y };
479
480 if (!m_refData)
481 return wxOutRegion;
482
483 LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS
484 ,M_REGION
485 ,&vPoint
486 );
487 if (lInside == PRGN_INSIDE)
488 return wxInRegion;
489 else
490 return wxOutRegion;
491 } // end of wxRegion::Contains
492
493 //
494 // Does the region contain the rectangle (x, y, w, h)?
495 //
496 wxRegionContain wxRegion::Contains(
497 wxCoord x
498 , wxCoord y
499 , wxCoord vWidth
500 , wxCoord vHeight
501 ) const
502 {
503 RECTL vRect;
504
505 if (!m_refData)
506 return wxOutRegion;
507
508 vRect.xLeft = x;
509 vRect.yTop = y;
510 vRect.xRight = x + vWidth;
511 vRect.yBottom = y + vHeight;
512
513 if (PRGN_INSIDE == ::GpiRectInRegion( ((wxRegionRefData*)m_refData)->m_hPS
514 ,M_REGION
515 ,&vRect
516 ))
517 return wxInRegion;
518 else
519 return wxOutRegion;
520 } // end of wxRegion::Contains
521
522 //
523 // Does the region contain the rectangle rect
524 //
525 wxRegionContain wxRegion::Contains(
526 const wxRect& rRect
527 ) const
528 {
529 if (!m_refData)
530 return wxOutRegion;
531
532 wxCoord x;
533 wxCoord y;
534 wxCoord vWidth;
535 wxCoord vHeight;
536
537 x = rRect.x;
538 y = rRect.y;
539 vWidth = rRect.GetWidth();
540 vHeight = rRect.GetHeight();
541 return Contains( x
542 ,y
543 ,vWidth
544 ,vHeight
545 );
546 } // end of wxRegion::Contains
547
548 //
549 // Get internal region handle
550 //
551 WXHRGN wxRegion::GetHRGN() const
552 {
553 if (!m_refData)
554 return (WXHRGN) 0;
555 return (WXHRGN) M_REGION;
556 }
557
558 //
559 // Set a new PS, this means we have to recreate the old region in the new
560 // PS
561 //
562 void wxRegion::SetPS(
563 HPS hPS
564 )
565 {
566 RGNRECT vRgnData;
567 PRECTL pRect = NULL;
568
569 if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
570 ,((wxRegionRefData*)m_refData)->m_hRegion
571 ,NULL
572 ,&vRgnData
573 ,NULL
574 ))
575 {
576 pRect = new RECTL[vRgnData.crcReturned];
577 vRgnData.crc = vRgnData.crcReturned;
578 vRgnData.ircStart = 1;
579 if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
580 ,((wxRegionRefData*)m_refData)->m_hRegion
581 ,NULL
582 ,&vRgnData
583 ,pRect
584 ))
585 {
586 //
587 // First destroy the region out of the old PS
588 // and then create it in the new and set the new to current
589 //
590 ::GpiDestroyRegion( ((wxRegionRefData*)m_refData)->m_hPS
591 ,M_REGION
592 );
593 ((wxRegionRefData*)m_refData)->m_hRegion = ::GpiCreateRegion( hPS
594 ,vRgnData.crcReturned
595 ,pRect
596 );
597 ((wxRegionRefData*)m_refData)->m_hPS = hPS;
598 }
599 delete [] pRect;
600 }
601 } // end of wxRegion::SetPS
602
603 ///////////////////////////////////////////////////////////////////////////////
604 // //
605 // wxRegionIterator //
606 // //
607 ///////////////////////////////////////////////////////////////////////////////
608
609 //
610 // Initialize empty iterator
611 //
612 wxRegionIterator::wxRegionIterator()
613 : m_lCurrent(0)
614 , m_lNumRects(0)
615 , m_pRects(NULL)
616 {
617 } // end of wxRegionIterator::wxRegionIterator
618
619 wxRegionIterator::~wxRegionIterator()
620 {
621 if (m_pRects)
622 delete[] m_pRects;
623 } // end of wxRegionIterator::~wxRegionIterator
624
625 //
626 // Initialize iterator for region
627 //
628 wxRegionIterator::wxRegionIterator(
629 const wxRegion& rRegion
630 )
631 {
632 m_pRects = NULL;
633 Reset(rRegion);
634 } // end of wxRegionIterator::wxRegionIterator
635
636 //
637 // Reset iterator for a new /e region.
638 //
639 void wxRegionIterator::Reset(
640 const wxRegion& rRegion
641 )
642 {
643 m_lCurrent = 0;
644 m_vRegion = rRegion;
645
646 if (m_pRects)
647 delete[] m_pRects;
648
649 m_pRects = NULL;
650
651 if (m_vRegion.Empty())
652 m_lNumRects = 0;
653 else
654 {
655 RGNRECT vRgnData;
656 PRECTL pRect;
657
658 if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS // Pres space
659 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of region to query
660 ,NULL // Return all RECTs
661 ,&vRgnData // Will contain number or RECTs in region
662 ,NULL // NULL to return number of RECTs
663 ))
664 {
665 pRect = new RECTL[vRgnData.crcReturned];
666 m_pRects = new wxRect[vRgnData.crcReturned];
667 vRgnData.crc = vRgnData.crcReturned;
668 m_lNumRects = vRgnData.crcReturned;
669 vRgnData.ircStart = 1;
670 if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS // Pres space of source
671 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of source region
672 ,NULL // Return all RECTs
673 ,&vRgnData // Operations set to return rects
674 ,pRect // Will contain the actual RECTS
675 ))
676 {
677 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
678 ,vRgnData.crcReturned
679 ,pRect
680 );
681 for( LONG i = 0; i < m_lNumRects; i++)
682 {
683 m_pRects[i].x = pRect[i].xLeft;
684 m_pRects[i].width = pRect[i].xRight - pRect[i].xLeft;
685 m_pRects[i].y = pRect[i].yBottom;
686 m_pRects[i].height = pRect[i].yTop - pRect[i].yBottom;
687 }
688 ((wxRegionRefData*)m_refData)->m_hPS = ((wxRegionRefData*)rRegion.m_refData)->m_hPS;
689 }
690 }
691 }
692 } // end of wxRegionIterator::Reset
693
694 //
695 // Increment iterator. The rectangle returned is the one after the
696 // incrementation.
697 //
698 void wxRegionIterator::operator++ ()
699 {
700 if (m_lCurrent < m_lNumRects)
701 ++m_lCurrent;
702 } // end of wxRegionIterator::operator ++
703
704 //
705 // Increment iterator. The rectangle returned is the one before the
706 // incrementation.
707 //
708 void wxRegionIterator::operator++ (int)
709 {
710 if (m_lCurrent < m_lNumRects)
711 ++m_lCurrent;
712 } // end of wxRegionIterator::operator++
713
714 wxCoord wxRegionIterator::GetX() const
715 {
716 if (m_lCurrent < m_lNumRects)
717 return m_pRects[m_lCurrent].x;
718 return 0L;
719 } // end of wxRegionIterator::GetX
720
721 wxCoord wxRegionIterator::GetY() const
722 {
723 if (m_lCurrent < m_lNumRects)
724 return m_pRects[m_lCurrent].y;
725 return 0L;
726 } // end of wxRegionIterator::GetY
727
728 wxCoord wxRegionIterator::GetW() const
729 {
730 if (m_lCurrent < m_lNumRects)
731 return m_pRects[m_lCurrent].width ;
732 return 0L;
733 } // end of wxRegionIterator::GetW
734
735 wxCoord wxRegionIterator::GetH() const
736 {
737 if (m_lCurrent < m_lNumRects)
738 return m_pRects[m_lCurrent].height;
739 return 0L;
740 } // end of wxRegionIterator::GetH
741