2 // System.Drawing.Region.cs
5 // Miguel de Icaza (miguel@ximian.com)
6 // Jordi Mas i Hernandez (jordi@ximian.com)
8 // Copyright (C) 2003 Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2004,2006 Novell, Inc. http://www.novell.com
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System
.Drawing
.Drawing2D
;
32 using System
.Runtime
.InteropServices
;
33 using System
.Security
.Permissions
;
35 namespace System
.Drawing
40 public sealed class Region
: MarshalByRefObject
, IDisposable
42 private IntPtr nativeRegion
= IntPtr
.Zero
;
46 Status status
= GDIPlus
.GdipCreateRegion (out nativeRegion
);
47 GDIPlus
.CheckStatus (status
);
50 internal Region(IntPtr native
)
52 nativeRegion
= native
;
55 public Region (GraphicsPath path
)
58 throw new ArgumentNullException ("path");
59 Status status
= GDIPlus
.GdipCreateRegionPath (path
.NativeObject
, out nativeRegion
);
60 GDIPlus
.CheckStatus (status
);
63 public Region (Rectangle rect
)
65 Status status
= GDIPlus
.GdipCreateRegionRectI (ref rect
, out nativeRegion
);
66 GDIPlus
.CheckStatus (status
);
69 public Region (RectangleF rect
)
71 Status status
= GDIPlus
.GdipCreateRegionRect (ref rect
, out nativeRegion
);
72 GDIPlus
.CheckStatus (status
);
75 public Region (RegionData rgnData
)
78 throw new ArgumentNullException ("rgnData");
79 // a NullReferenceException can be throw for rgnData.Data.Length (if rgnData.Data is null) just like MS
80 if (rgnData
.Data
.Length
== 0)
81 throw new ArgumentException ("rgnData");
82 Status status
= GDIPlus
.GdipCreateRegionRgnData (rgnData
.Data
, rgnData
.Data
.Length
, out nativeRegion
);
83 GDIPlus
.CheckStatus (status
);
90 public void Union (GraphicsPath path
)
93 throw new ArgumentNullException ("path");
94 Status status
= GDIPlus
.GdipCombineRegionPath (nativeRegion
, path
.NativeObject
, CombineMode
.Union
);
95 GDIPlus
.CheckStatus (status
);
99 public void Union (Rectangle rect
)
101 Status status
= GDIPlus
.GdipCombineRegionRectI (nativeRegion
, ref rect
, CombineMode
.Union
);
102 GDIPlus
.CheckStatus (status
);
105 public void Union (RectangleF rect
)
107 Status status
= GDIPlus
.GdipCombineRegionRect (nativeRegion
, ref rect
, CombineMode
.Union
);
108 GDIPlus
.CheckStatus (status
);
111 public void Union (Region region
)
114 throw new ArgumentNullException ("region");
115 Status status
= GDIPlus
.GdipCombineRegionRegion (nativeRegion
, region
.NativeObject
, CombineMode
.Union
);
116 GDIPlus
.CheckStatus (status
);
123 public void Intersect (GraphicsPath path
)
126 throw new ArgumentNullException ("path");
127 Status status
= GDIPlus
.GdipCombineRegionPath (nativeRegion
, path
.NativeObject
, CombineMode
.Intersect
);
128 GDIPlus
.CheckStatus (status
);
131 public void Intersect (Rectangle rect
)
133 Status status
= GDIPlus
.GdipCombineRegionRectI (nativeRegion
, ref rect
, CombineMode
.Intersect
);
134 GDIPlus
.CheckStatus (status
);
137 public void Intersect (RectangleF rect
)
139 Status status
= GDIPlus
.GdipCombineRegionRect (nativeRegion
, ref rect
, CombineMode
.Intersect
);
140 GDIPlus
.CheckStatus (status
);
143 public void Intersect (Region region
)
146 throw new ArgumentNullException ("region");
147 Status status
= GDIPlus
.GdipCombineRegionRegion (nativeRegion
, region
.NativeObject
, CombineMode
.Intersect
);
148 GDIPlus
.CheckStatus (status
);
154 public void Complement (GraphicsPath path
)
157 throw new ArgumentNullException ("path");
158 Status status
= GDIPlus
.GdipCombineRegionPath (nativeRegion
, path
.NativeObject
, CombineMode
.Complement
);
159 GDIPlus
.CheckStatus (status
);
162 public void Complement (Rectangle rect
)
164 Status status
= GDIPlus
.GdipCombineRegionRectI (nativeRegion
, ref rect
, CombineMode
.Complement
);
165 GDIPlus
.CheckStatus (status
);
168 public void Complement (RectangleF rect
)
170 Status status
= GDIPlus
.GdipCombineRegionRect (nativeRegion
, ref rect
, CombineMode
.Complement
);
171 GDIPlus
.CheckStatus (status
);
174 public void Complement (Region region
)
177 throw new ArgumentNullException ("region");
178 Status status
= GDIPlus
.GdipCombineRegionRegion (nativeRegion
, region
.NativeObject
, CombineMode
.Complement
);
179 GDIPlus
.CheckStatus (status
);
185 public void Exclude (GraphicsPath path
)
188 throw new ArgumentNullException ("path");
189 Status status
= GDIPlus
.GdipCombineRegionPath (nativeRegion
, path
.NativeObject
, CombineMode
.Exclude
);
190 GDIPlus
.CheckStatus (status
);
193 public void Exclude (Rectangle rect
)
195 Status status
= GDIPlus
.GdipCombineRegionRectI (nativeRegion
, ref rect
, CombineMode
.Exclude
);
196 GDIPlus
.CheckStatus (status
);
199 public void Exclude (RectangleF rect
)
201 Status status
= GDIPlus
.GdipCombineRegionRect (nativeRegion
, ref rect
, CombineMode
.Exclude
);
202 GDIPlus
.CheckStatus (status
);
205 public void Exclude (Region region
)
208 throw new ArgumentNullException ("region");
209 Status status
= GDIPlus
.GdipCombineRegionRegion (nativeRegion
, region
.NativeObject
, CombineMode
.Exclude
);
210 GDIPlus
.CheckStatus (status
);
216 public void Xor (GraphicsPath path
)
219 throw new ArgumentNullException ("path");
220 Status status
= GDIPlus
.GdipCombineRegionPath (nativeRegion
, path
.NativeObject
, CombineMode
.Xor
);
221 GDIPlus
.CheckStatus (status
);
224 public void Xor (Rectangle rect
)
226 Status status
= GDIPlus
.GdipCombineRegionRectI (nativeRegion
, ref rect
, CombineMode
.Xor
);
227 GDIPlus
.CheckStatus (status
);
230 public void Xor (RectangleF rect
)
232 Status status
= GDIPlus
.GdipCombineRegionRect (nativeRegion
, ref rect
, CombineMode
.Xor
);
233 GDIPlus
.CheckStatus (status
);
236 public void Xor (Region region
)
239 throw new ArgumentNullException ("region");
240 Status status
= GDIPlus
.GdipCombineRegionRegion (nativeRegion
, region
.NativeObject
, CombineMode
.Xor
);
241 GDIPlus
.CheckStatus (status
);
247 public RectangleF
GetBounds (Graphics g
)
250 throw new ArgumentNullException ("g");
252 RectangleF rect
= new Rectangle();
254 Status status
= GDIPlus
.GdipGetRegionBounds (nativeRegion
, g
.NativeObject
, ref rect
);
255 GDIPlus
.CheckStatus (status
);
263 public void Translate (int dx
, int dy
)
265 Status status
= GDIPlus
.GdipTranslateRegionI (nativeRegion
, dx
, dy
);
266 GDIPlus
.CheckStatus (status
);
269 public void Translate (float dx
, float dy
)
271 Status status
= GDIPlus
.GdipTranslateRegion (nativeRegion
, dx
, dy
);
272 GDIPlus
.CheckStatus (status
);
278 public bool IsVisible (int x
, int y
, Graphics g
)
280 IntPtr ptr
= (g
== null) ? IntPtr
.Zero
: g
.NativeObject
;
283 Status status
= GDIPlus
.GdipIsVisibleRegionPointI (nativeRegion
, x
, y
, ptr
, out result
);
284 GDIPlus
.CheckStatus (status
);
289 public bool IsVisible (int x
, int y
, int width
, int height
)
293 Status status
= GDIPlus
.GdipIsVisibleRegionRectI (nativeRegion
, x
, y
,
294 width
, height
, IntPtr
.Zero
, out result
);
296 GDIPlus
.CheckStatus (status
);
301 public bool IsVisible (int x
, int y
, int width
, int height
, Graphics g
)
303 IntPtr ptr
= (g
== null) ? IntPtr
.Zero
: g
.NativeObject
;
306 Status status
= GDIPlus
.GdipIsVisibleRegionRectI (nativeRegion
, x
, y
,
307 width
, height
, ptr
, out result
);
309 GDIPlus
.CheckStatus (status
);
314 public bool IsVisible (Point point
)
318 Status status
= GDIPlus
.GdipIsVisibleRegionPointI (nativeRegion
, point
.X
, point
.Y
,
319 IntPtr
.Zero
, out result
);
321 GDIPlus
.CheckStatus (status
);
326 public bool IsVisible (PointF point
)
330 Status status
= GDIPlus
.GdipIsVisibleRegionPoint (nativeRegion
, point
.X
, point
.Y
,
331 IntPtr
.Zero
, out result
);
333 GDIPlus
.CheckStatus (status
);
338 public bool IsVisible (Point point
, Graphics g
)
340 IntPtr ptr
= (g
== null) ? IntPtr
.Zero
: g
.NativeObject
;
343 Status status
= GDIPlus
.GdipIsVisibleRegionPointI (nativeRegion
, point
.X
, point
.Y
,
346 GDIPlus
.CheckStatus (status
);
351 public bool IsVisible (PointF point
, Graphics g
)
353 IntPtr ptr
= (g
== null) ? IntPtr
.Zero
: g
.NativeObject
;
356 Status status
= GDIPlus
.GdipIsVisibleRegionPoint (nativeRegion
, point
.X
, point
.Y
,
359 GDIPlus
.CheckStatus (status
);
364 public bool IsVisible (Rectangle rect
)
368 Status status
= GDIPlus
.GdipIsVisibleRegionRectI (nativeRegion
, rect
.X
, rect
.Y
,
369 rect
.Width
, rect
.Height
, IntPtr
.Zero
, out result
);
371 GDIPlus
.CheckStatus (status
);
376 public bool IsVisible (RectangleF rect
)
380 Status status
= GDIPlus
.GdipIsVisibleRegionRect (nativeRegion
, rect
.X
, rect
.Y
,
381 rect
.Width
, rect
.Height
, IntPtr
.Zero
, out result
);
383 GDIPlus
.CheckStatus (status
);
388 public bool IsVisible (Rectangle rect
, Graphics g
)
390 IntPtr ptr
= (g
== null) ? IntPtr
.Zero
: g
.NativeObject
;
393 Status status
= GDIPlus
.GdipIsVisibleRegionRectI (nativeRegion
, rect
.X
, rect
.Y
,
394 rect
.Width
, rect
.Height
, ptr
, out result
);
396 GDIPlus
.CheckStatus (status
);
401 public bool IsVisible (RectangleF rect
, Graphics g
)
403 IntPtr ptr
= (g
== null) ? IntPtr
.Zero
: g
.NativeObject
;
406 Status status
= GDIPlus
.GdipIsVisibleRegionRect (nativeRegion
, rect
.X
, rect
.Y
,
407 rect
.Width
, rect
.Height
, ptr
, out result
);
409 GDIPlus
.CheckStatus (status
);
414 public bool IsVisible (float x
, float y
)
418 Status status
= GDIPlus
.GdipIsVisibleRegionPoint (nativeRegion
, x
, y
, IntPtr
.Zero
, out result
);
419 GDIPlus
.CheckStatus (status
);
424 public bool IsVisible (float x
, float y
, Graphics g
)
426 IntPtr ptr
= (g
== null) ? IntPtr
.Zero
: g
.NativeObject
;
429 Status status
= GDIPlus
.GdipIsVisibleRegionPoint (nativeRegion
, x
, y
, ptr
, out result
);
430 GDIPlus
.CheckStatus (status
);
435 public bool IsVisible (float x
, float y
, float width
, float height
)
439 Status status
= GDIPlus
.GdipIsVisibleRegionRect (nativeRegion
, x
, y
, width
, height
, IntPtr
.Zero
, out result
);
440 GDIPlus
.CheckStatus (status
);
445 public bool IsVisible (float x
, float y
, float width
, float height
, Graphics g
)
447 IntPtr ptr
= (g
== null) ? IntPtr
.Zero
: g
.NativeObject
;
450 Status status
= GDIPlus
.GdipIsVisibleRegionRect (nativeRegion
, x
, y
, width
, height
, ptr
, out result
);
451 GDIPlus
.CheckStatus (status
);
461 public bool IsEmpty(Graphics g
)
464 throw new ArgumentNullException ("g");
468 Status status
= GDIPlus
.GdipIsEmptyRegion (nativeRegion
, g
.NativeObject
, out result
);
469 GDIPlus
.CheckStatus (status
);
474 public bool IsInfinite(Graphics g
)
477 throw new ArgumentNullException ("g");
481 Status status
= GDIPlus
.GdipIsInfiniteRegion (nativeRegion
, g
.NativeObject
, out result
);
482 GDIPlus
.CheckStatus (status
);
487 public void MakeEmpty()
489 Status status
= GDIPlus
.GdipSetEmpty (nativeRegion
);
490 GDIPlus
.CheckStatus (status
);
493 public void MakeInfinite()
495 Status status
= GDIPlus
.GdipSetInfinite (nativeRegion
);
496 GDIPlus
.CheckStatus (status
);
499 public bool Equals(Region region
, Graphics g
)
502 throw new ArgumentNullException ("region");
504 throw new ArgumentNullException ("g");
508 Status status
= GDIPlus
.GdipIsEqualRegion (nativeRegion
, region
.NativeObject
,
509 g
.NativeObject
, out result
);
511 GDIPlus
.CheckStatus (status
);
516 [SecurityPermission (SecurityAction
.Demand
, UnmanagedCode
= true)]
517 public static Region
FromHrgn (IntPtr hrgn
)
519 if (hrgn
== IntPtr
.Zero
)
520 throw new ArgumentException ("hrgn");
523 Status status
= GDIPlus
.GdipCreateRegionHrgn (hrgn
, out handle
);
524 GDIPlus
.CheckStatus (status
);
526 return new Region (handle
);
530 public IntPtr
GetHrgn (Graphics g
)
532 // Our WindowsForms implementation uses null to avoid
533 // creating a Graphics context when not needed
535 // this is MS behaviour
537 throw new ArgumentNullException ("g");
539 // this is an hack for MWF (libgdiplus would reject that)
543 IntPtr handle
= IntPtr
.Zero
;
544 Status status
= GDIPlus
.GdipGetRegionHRgn (nativeRegion
, g
.NativeObject
, ref handle
);
545 GDIPlus
.CheckStatus (status
);
550 public RegionData
GetRegionData()
554 Status status
= GDIPlus
.GdipGetRegionDataSize (nativeRegion
, out size
);
555 GDIPlus
.CheckStatus (status
);
557 byte[] buff
= new byte [size
];
559 status
= GDIPlus
.GdipGetRegionData (nativeRegion
, buff
, size
, out filled
);
560 GDIPlus
.CheckStatus (status
);
562 RegionData rgndata
= new RegionData();
569 public RectangleF
[] GetRegionScans(Matrix matrix
)
572 throw new ArgumentNullException ("matrix");
576 Status status
= GDIPlus
.GdipGetRegionScansCount (nativeRegion
, out cnt
, matrix
.NativeObject
);
577 GDIPlus
.CheckStatus (status
);
580 return new RectangleF
[0];
582 RectangleF
[] rects
= new RectangleF
[cnt
];
583 int size
= Marshal
.SizeOf (rects
[0]);
585 IntPtr dest
= Marshal
.AllocHGlobal (size
* cnt
);
587 status
= GDIPlus
.GdipGetRegionScans (nativeRegion
, dest
, out cnt
, matrix
.NativeObject
);
588 GDIPlus
.CheckStatus (status
);
591 // note: Marshal.FreeHGlobal is called from GDIPlus.FromUnManagedMemoryToRectangles
592 GDIPlus
.FromUnManagedMemoryToRectangles (dest
, rects
);
597 public void Transform(Matrix matrix
)
600 throw new ArgumentNullException ("matrix");
602 Status status
= GDIPlus
.GdipTransformRegion (nativeRegion
, matrix
.NativeObject
);
603 GDIPlus
.CheckStatus (status
);
606 public Region
Clone()
610 Status status
= GDIPlus
.GdipCloneRegion (nativeRegion
, out cloned
);
611 GDIPlus
.CheckStatus (status
);
613 return new Region (cloned
);
616 public void Dispose ()
619 System
.GC
.SuppressFinalize (this);
622 private void DisposeHandle ()
624 if (nativeRegion
!= IntPtr
.Zero
) {
625 GDIPlus
.GdipDeleteRegion (nativeRegion
);
626 nativeRegion
= IntPtr
.Zero
;
635 internal IntPtr NativeObject
641 nativeRegion
= value;
645 // why is this a instance method ? and not static ?
646 [SecurityPermission (SecurityAction
.Demand
, UnmanagedCode
= true)]
647 public void ReleaseHrgn (IntPtr regionHandle
)
649 if (regionHandle
== IntPtr
.Zero
)
650 throw new ArgumentNullException ("regionHandle");
652 Status status
= Status
.Ok
;
653 if (GDIPlus
.RunningOnUnix ()) {
654 // for libgdiplus HRGN == GpRegion*
655 status
= GDIPlus
.GdipDeleteRegion (regionHandle
);
657 // ... but on Windows HRGN are (old) GDI objects
658 if (!GDIPlus
.DeleteObject (regionHandle
))
659 status
= Status
.InvalidParameter
;
661 GDIPlus
.CheckStatus (status
);