1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Drawing.Drawing2D;
6 using System.Drawing.Internal;
7 using System.Runtime.InteropServices;
8 
9 namespace System.Drawing
10 {
11     /// <summary>
12     /// Encapsulates a GDI+ drawing surface.
13     /// </summary>
14     public sealed partial class Graphics : MarshalByRefObject, IDisposable, IDeviceContext
15     {
16         public void SetClip(Graphics g) => SetClip(g, CombineMode.Replace);
17 
SetClip(Graphics g, CombineMode combineMode)18         public void SetClip(Graphics g, CombineMode combineMode)
19         {
20             if (g == null)
21             {
22                 throw new ArgumentNullException(nameof(g));
23             }
24 
25             int status = SafeNativeMethods.Gdip.GdipSetClipGraphics(new HandleRef(this, NativeGraphics), new HandleRef(g, g.NativeGraphics), combineMode);
26             SafeNativeMethods.Gdip.CheckStatus(status);
27         }
28 
29         public void SetClip(Rectangle rect) => SetClip(rect, CombineMode.Replace);
30 
SetClip(Rectangle rect, CombineMode combineMode)31         public void SetClip(Rectangle rect, CombineMode combineMode)
32         {
33             int status = SafeNativeMethods.Gdip.GdipSetClipRectI(new HandleRef(this, NativeGraphics), rect.X, rect.Y,
34                                                   rect.Width, rect.Height, combineMode);
35             SafeNativeMethods.Gdip.CheckStatus(status);
36         }
37 
38         public void SetClip(RectangleF rect) => SetClip(rect, CombineMode.Replace);
39 
SetClip(RectangleF rect, CombineMode combineMode)40         public void SetClip(RectangleF rect, CombineMode combineMode)
41         {
42             int status = SafeNativeMethods.Gdip.GdipSetClipRect(new HandleRef(this, NativeGraphics), rect.X, rect.Y,
43                                                  rect.Width, rect.Height, combineMode);
44             SafeNativeMethods.Gdip.CheckStatus(status);
45         }
46 
47         public void SetClip(GraphicsPath path) => SetClip(path, CombineMode.Replace);
48 
SetClip(GraphicsPath path, CombineMode combineMode)49         public void SetClip(GraphicsPath path, CombineMode combineMode)
50         {
51             if (path == null)
52             {
53                 throw new ArgumentNullException(nameof(path));
54             }
55 
56             int status = SafeNativeMethods.Gdip.GdipSetClipPath(new HandleRef(this, NativeGraphics), new HandleRef(path, path.nativePath), combineMode);
57             SafeNativeMethods.Gdip.CheckStatus(status);
58         }
59 
SetClip(Region region, CombineMode combineMode)60         public void SetClip(Region region, CombineMode combineMode)
61         {
62             if (region == null)
63             {
64                 throw new ArgumentNullException(nameof(region));
65             }
66 
67             int status = SafeNativeMethods.Gdip.GdipSetClipRegion(new HandleRef(this, NativeGraphics), new HandleRef(region, region._nativeRegion), combineMode);
68             SafeNativeMethods.Gdip.CheckStatus(status);
69         }
70 
IntersectClip(Rectangle rect)71         public void IntersectClip(Rectangle rect)
72         {
73             int status = SafeNativeMethods.Gdip.GdipSetClipRectI(new HandleRef(this, NativeGraphics), rect.X, rect.Y,
74                                                   rect.Width, rect.Height, CombineMode.Intersect);
75             SafeNativeMethods.Gdip.CheckStatus(status);
76         }
77 
IntersectClip(RectangleF rect)78         public void IntersectClip(RectangleF rect)
79         {
80             int status = SafeNativeMethods.Gdip.GdipSetClipRect(new HandleRef(this, NativeGraphics), rect.X, rect.Y,
81                                                  rect.Width, rect.Height, CombineMode.Intersect);
82             SafeNativeMethods.Gdip.CheckStatus(status);
83         }
84 
IntersectClip(Region region)85         public void IntersectClip(Region region)
86         {
87             if (region == null)
88             {
89                 throw new ArgumentNullException(nameof(region));
90             }
91 
92             int status = SafeNativeMethods.Gdip.GdipSetClipRegion(new HandleRef(this, NativeGraphics), new HandleRef(region, region._nativeRegion),
93                                                    CombineMode.Intersect);
94             SafeNativeMethods.Gdip.CheckStatus(status);
95         }
96 
ExcludeClip(Rectangle rect)97         public void ExcludeClip(Rectangle rect)
98         {
99             int status = SafeNativeMethods.Gdip.GdipSetClipRectI(new HandleRef(this, NativeGraphics), rect.X, rect.Y,
100                                                   rect.Width, rect.Height, CombineMode.Exclude);
101             SafeNativeMethods.Gdip.CheckStatus(status);
102         }
103 
ExcludeClip(Region region)104         public void ExcludeClip(Region region)
105         {
106             if (region == null)
107             {
108                 throw new ArgumentNullException(nameof(region));
109             }
110 
111             int status = SafeNativeMethods.Gdip.GdipSetClipRegion(new HandleRef(this, NativeGraphics),
112                                                    new HandleRef(region, region._nativeRegion),
113                                                    CombineMode.Exclude);
114             SafeNativeMethods.Gdip.CheckStatus(status);
115         }
116 
ResetClip()117         public void ResetClip()
118         {
119             int status = SafeNativeMethods.Gdip.GdipResetClip(new HandleRef(this, NativeGraphics));
120             SafeNativeMethods.Gdip.CheckStatus(status);
121         }
122 
TranslateClip(float dx, float dy)123         public void TranslateClip(float dx, float dy)
124         {
125             int status = SafeNativeMethods.Gdip.GdipTranslateClip(new HandleRef(this, NativeGraphics), dx, dy);
126             SafeNativeMethods.Gdip.CheckStatus(status);
127         }
128 
TranslateClip(int dx, int dy)129         public void TranslateClip(int dx, int dy)
130         {
131             int status = SafeNativeMethods.Gdip.GdipTranslateClip(new HandleRef(this, NativeGraphics), dx, dy);
132             SafeNativeMethods.Gdip.CheckStatus(status);
133         }
134 
135         public Region Clip
136         {
137             get
138             {
139                 var region = new Region();
140                 int status = SafeNativeMethods.Gdip.GdipGetClip(new HandleRef(this, NativeGraphics), new HandleRef(region, region._nativeRegion));
141                 SafeNativeMethods.Gdip.CheckStatus(status);
142 
143                 return region;
144             }
145             set => SetClip(value, CombineMode.Replace);
146         }
147 
148         public RectangleF ClipBounds
149         {
150             get
151             {
152                 var rect = new GPRECTF();
153                 int status = SafeNativeMethods.Gdip.GdipGetClipBounds(new HandleRef(this, NativeGraphics), ref rect);
154                 SafeNativeMethods.Gdip.CheckStatus(status);
155 
156                 return rect.ToRectangleF();
157             }
158         }
159 
160         public bool IsClipEmpty
161         {
162             get
163             {
164                 int isEmpty;
165                 int status = SafeNativeMethods.Gdip.GdipIsClipEmpty(new HandleRef(this, NativeGraphics), out isEmpty);
166                 SafeNativeMethods.Gdip.CheckStatus(status);
167 
168                 return isEmpty != 0;
169             }
170         }
171 
172         public bool IsVisibleClipEmpty
173         {
174             get
175             {
176                 int isEmpty;
177                 int status = SafeNativeMethods.Gdip.GdipIsVisibleClipEmpty(new HandleRef(this, NativeGraphics), out isEmpty);
178                 SafeNativeMethods.Gdip.CheckStatus(status);
179 
180                 return isEmpty != 0;
181             }
182         }
183 
184 
IsVisible(int x, int y)185         public bool IsVisible(int x, int y) => IsVisible(new Point(x, y));
186 
IsVisible(Point point)187         public bool IsVisible(Point point)
188         {
189             int isVisible;
190             int status = SafeNativeMethods.Gdip.GdipIsVisiblePointI(new HandleRef(this, NativeGraphics), point.X, point.Y, out isVisible);
191             SafeNativeMethods.Gdip.CheckStatus(status);
192 
193             return isVisible != 0;
194         }
195 
IsVisible(float x, float y)196         public bool IsVisible(float x, float y) => IsVisible(new PointF(x, y));
197 
IsVisible(PointF point)198         public bool IsVisible(PointF point)
199         {
200             int isVisible;
201             int status = SafeNativeMethods.Gdip.GdipIsVisiblePoint(new HandleRef(this, NativeGraphics), point.X, point.Y, out isVisible);
202             SafeNativeMethods.Gdip.CheckStatus(status);
203 
204             return isVisible != 0;
205         }
206 
IsVisible(int x, int y, int width, int height)207         public bool IsVisible(int x, int y, int width, int height)
208         {
209             return IsVisible(new Rectangle(x, y, width, height));
210         }
211 
IsVisible(Rectangle rect)212         public bool IsVisible(Rectangle rect)
213         {
214             int isVisible;
215             int status = SafeNativeMethods.Gdip.GdipIsVisibleRectI(new HandleRef(this, NativeGraphics), rect.X, rect.Y,
216                                                     rect.Width, rect.Height, out isVisible);
217             SafeNativeMethods.Gdip.CheckStatus(status);
218 
219             return isVisible != 0;
220         }
221 
IsVisible(float x, float y, float width, float height)222         public bool IsVisible(float x, float y, float width, float height)
223         {
224             return IsVisible(new RectangleF(x, y, width, height));
225         }
226 
IsVisible(RectangleF rect)227         public bool IsVisible(RectangleF rect)
228         {
229             int isVisible;
230             int status = SafeNativeMethods.Gdip.GdipIsVisibleRect(new HandleRef(this, NativeGraphics), rect.X, rect.Y,
231                                                    rect.Width, rect.Height, out isVisible);
232             SafeNativeMethods.Gdip.CheckStatus(status);
233 
234             return isVisible != 0;
235         }
236 
237         /// <summary>
238         /// Gets or sets the world transform for this <see cref='Graphics'/>.
239         /// </summary>
240         public Matrix Transform
241         {
242             get
243             {
244                 var matrix = new Matrix();
245                 int status = SafeNativeMethods.Gdip.GdipGetWorldTransform(new HandleRef(this, NativeGraphics),
246                                                            new HandleRef(matrix, matrix.nativeMatrix));
247                 SafeNativeMethods.Gdip.CheckStatus(status);
248 
249                 return matrix;
250             }
251             set
252             {
253                 int status = SafeNativeMethods.Gdip.GdipSetWorldTransform(new HandleRef(this, NativeGraphics),
254                                                            new HandleRef(value, value.nativeMatrix));
255                 SafeNativeMethods.Gdip.CheckStatus(status);
256             }
257         }
258 
259         /// <summary>
260         /// Resets the world transform to identity.
261         /// </summary>
ResetTransform()262         public void ResetTransform()
263         {
264             int status = SafeNativeMethods.Gdip.GdipResetWorldTransform(new HandleRef(this, NativeGraphics));
265             SafeNativeMethods.Gdip.CheckStatus(status);
266         }
267 
268         /// <summary>
269         /// Multiplies the <see cref='Matrix'/> that represents the world transform and <paramref name="matrix"/>.
270         /// </summary>
271         public void MultiplyTransform(Matrix matrix) => MultiplyTransform(matrix, MatrixOrder.Prepend);
272 
273         /// <summary>
274         /// Multiplies the <see cref='Matrix'/> that represents the world transform and <paramref name="matrix"/>.
275         /// </summary>
MultiplyTransform(Matrix matrix, MatrixOrder order)276         public void MultiplyTransform(Matrix matrix, MatrixOrder order)
277         {
278             if (matrix == null)
279             {
280                 throw new ArgumentNullException(nameof(matrix));
281             }
282 
283             int status = SafeNativeMethods.Gdip.GdipMultiplyWorldTransform(new HandleRef(this, NativeGraphics),
284                                                             new HandleRef(matrix, matrix.nativeMatrix),
285                                                             order);
286             SafeNativeMethods.Gdip.CheckStatus(status);
287         }
288 
TranslateTransform(float dx, float dy)289         public void TranslateTransform(float dx, float dy) => TranslateTransform(dx, dy, MatrixOrder.Prepend);
290 
TranslateTransform(float dx, float dy, MatrixOrder order)291         public void TranslateTransform(float dx, float dy, MatrixOrder order)
292         {
293             int status = SafeNativeMethods.Gdip.GdipTranslateWorldTransform(new HandleRef(this, NativeGraphics), dx, dy, order);
294             SafeNativeMethods.Gdip.CheckStatus(status);
295         }
296 
ScaleTransform(float sx, float sy)297         public void ScaleTransform(float sx, float sy) => ScaleTransform(sx, sy, MatrixOrder.Prepend);
298 
ScaleTransform(float sx, float sy, MatrixOrder order)299         public void ScaleTransform(float sx, float sy, MatrixOrder order)
300         {
301             int status = SafeNativeMethods.Gdip.GdipScaleWorldTransform(new HandleRef(this, NativeGraphics), sx, sy, order);
302             SafeNativeMethods.Gdip.CheckStatus(status);
303         }
304 
RotateTransform(float angle)305         public void RotateTransform(float angle) => RotateTransform(angle, MatrixOrder.Prepend);
306 
RotateTransform(float angle, MatrixOrder order)307         public void RotateTransform(float angle, MatrixOrder order)
308         {
309             int status = SafeNativeMethods.Gdip.GdipRotateWorldTransform(new HandleRef(this, NativeGraphics), angle, order);
310             SafeNativeMethods.Gdip.CheckStatus(status);
311         }
312     }
313 }
314