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.Runtime.InteropServices; 6 7 namespace System.Drawing.Drawing2D 8 { 9 public partial class CustomLineCap : MarshalByRefObject, ICloneable, IDisposable 10 { 11 #if FINALIZATION_WATCH 12 private string allocationSite = Graphics.GetAllocationStack(); 13 #endif 14 15 // Handle to native line cap object 16 internal SafeCustomLineCapHandle nativeCap = null; 17 18 private bool _disposed = false; 19 20 // For subclass creation CustomLineCap()21 internal CustomLineCap() { } 22 CustomLineCap(GraphicsPath fillPath, GraphicsPath strokePath)23 public CustomLineCap(GraphicsPath fillPath, GraphicsPath strokePath) : this(fillPath, strokePath, LineCap.Flat) { } 24 CustomLineCap(GraphicsPath fillPath, GraphicsPath strokePath, LineCap baseCap)25 public CustomLineCap(GraphicsPath fillPath, GraphicsPath strokePath, LineCap baseCap) : this(fillPath, strokePath, baseCap, 0) { } 26 CustomLineCap(GraphicsPath fillPath, GraphicsPath strokePath, LineCap baseCap, float baseInset)27 public CustomLineCap(GraphicsPath fillPath, GraphicsPath strokePath, LineCap baseCap, float baseInset) 28 { 29 IntPtr nativeLineCap; 30 int status = SafeNativeMethods.Gdip.GdipCreateCustomLineCap( 31 new HandleRef(fillPath, (fillPath == null) ? IntPtr.Zero : fillPath.nativePath), 32 new HandleRef(strokePath, (strokePath == null) ? IntPtr.Zero : strokePath.nativePath), 33 baseCap, baseInset, out nativeLineCap); 34 35 if (status != SafeNativeMethods.Gdip.Ok) 36 throw SafeNativeMethods.Gdip.StatusException(status); 37 38 SetNativeLineCap(nativeLineCap); 39 } 40 41 internal CustomLineCap(IntPtr nativeLineCap) => SetNativeLineCap(nativeLineCap); 42 SetNativeLineCap(IntPtr handle)43 internal void SetNativeLineCap(IntPtr handle) 44 { 45 if (handle == IntPtr.Zero) 46 throw new ArgumentNullException("handle"); 47 48 nativeCap = new SafeCustomLineCapHandle(handle); 49 } 50 Dispose()51 public void Dispose() 52 { 53 Dispose(true); 54 GC.SuppressFinalize(this); 55 } 56 Dispose(bool disposing)57 protected virtual void Dispose(bool disposing) 58 { 59 if (_disposed) 60 return; 61 62 #if FINALIZATION_WATCH 63 if (!disposing && nativeCap != null) 64 Debug.WriteLine("**********************\nDisposed through finalization:\n" + allocationSite); 65 #endif 66 // propagate the explicit dispose call to the child 67 if (disposing && nativeCap != null) 68 { 69 nativeCap.Dispose(); 70 } 71 72 _disposed = true; 73 } 74 ~CustomLineCap()75 ~CustomLineCap() => Dispose(false); 76 Clone()77 public virtual object Clone() 78 { 79 IntPtr clonedCap; 80 int status = SafeNativeMethods.Gdip.GdipCloneCustomLineCap(new HandleRef(this, nativeCap), out clonedCap); 81 82 if (status != SafeNativeMethods.Gdip.Ok) 83 throw SafeNativeMethods.Gdip.StatusException(status); 84 85 return CreateCustomLineCapObject(clonedCap); 86 } 87 SetStrokeCaps(LineCap startCap, LineCap endCap)88 public void SetStrokeCaps(LineCap startCap, LineCap endCap) 89 { 90 int status = SafeNativeMethods.Gdip.GdipSetCustomLineCapStrokeCaps(new HandleRef(this, nativeCap), startCap, endCap); 91 92 if (status != SafeNativeMethods.Gdip.Ok) 93 throw SafeNativeMethods.Gdip.StatusException(status); 94 } 95 GetStrokeCaps(out LineCap startCap, out LineCap endCap)96 public void GetStrokeCaps(out LineCap startCap, out LineCap endCap) 97 { 98 int status = SafeNativeMethods.Gdip.GdipGetCustomLineCapStrokeCaps(new HandleRef(this, nativeCap), out startCap, out endCap); 99 100 if (status != SafeNativeMethods.Gdip.Ok) 101 throw SafeNativeMethods.Gdip.StatusException(status); 102 } 103 104 public LineJoin StrokeJoin 105 { 106 get 107 { 108 int status = SafeNativeMethods.Gdip.GdipGetCustomLineCapStrokeJoin(new HandleRef(this, nativeCap), out LineJoin lineJoin); 109 110 if (status != SafeNativeMethods.Gdip.Ok) 111 throw SafeNativeMethods.Gdip.StatusException(status); 112 113 return lineJoin; 114 } 115 set 116 { 117 int status = SafeNativeMethods.Gdip.GdipSetCustomLineCapStrokeJoin(new HandleRef(this, nativeCap), value); 118 119 if (status != SafeNativeMethods.Gdip.Ok) 120 throw SafeNativeMethods.Gdip.StatusException(status); 121 } 122 } 123 124 public LineCap BaseCap 125 { 126 get 127 { 128 int status = SafeNativeMethods.Gdip.GdipGetCustomLineCapBaseCap(new HandleRef(this, nativeCap), out LineCap baseCap); 129 130 if (status != SafeNativeMethods.Gdip.Ok) 131 throw SafeNativeMethods.Gdip.StatusException(status); 132 133 return baseCap; 134 } 135 set 136 { 137 int status = SafeNativeMethods.Gdip.GdipSetCustomLineCapBaseCap(new HandleRef(this, nativeCap), value); 138 139 if (status != SafeNativeMethods.Gdip.Ok) 140 throw SafeNativeMethods.Gdip.StatusException(status); 141 } 142 } 143 144 public float BaseInset 145 { 146 get 147 { 148 int status = SafeNativeMethods.Gdip.GdipGetCustomLineCapBaseInset(new HandleRef(this, nativeCap), out float inset); 149 150 if (status != SafeNativeMethods.Gdip.Ok) 151 throw SafeNativeMethods.Gdip.StatusException(status); 152 153 return inset; 154 } 155 set 156 { 157 int status = SafeNativeMethods.Gdip.GdipSetCustomLineCapBaseInset(new HandleRef(this, nativeCap), value); 158 159 if (status != SafeNativeMethods.Gdip.Ok) 160 throw SafeNativeMethods.Gdip.StatusException(status); 161 } 162 } 163 164 public float WidthScale 165 { 166 get 167 { 168 int status = SafeNativeMethods.Gdip.GdipGetCustomLineCapWidthScale(new HandleRef(this, nativeCap), out float widthScale); 169 170 if (status != SafeNativeMethods.Gdip.Ok) 171 throw SafeNativeMethods.Gdip.StatusException(status); 172 173 return widthScale; 174 } 175 set 176 { 177 int status = SafeNativeMethods.Gdip.GdipSetCustomLineCapWidthScale(new HandleRef(this, nativeCap), value); 178 179 if (status != SafeNativeMethods.Gdip.Ok) 180 throw SafeNativeMethods.Gdip.StatusException(status); 181 } 182 } 183 } 184 } 185