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.Collections.Generic; 6 using Xunit; 7 8 namespace System.Drawing.Drawing2D.Tests 9 { 10 public class CustomLineCapTests 11 { Ctor_Path_Path_LineCap_Float_TestData()12 public static IEnumerable<object[]> Ctor_Path_Path_LineCap_Float_TestData() 13 { 14 yield return new object[] { new GraphicsPath(), null, LineCap.Flat, 0f, LineCap.Flat }; 15 yield return new object[] { new GraphicsPath(), null, LineCap.Square, 1f, LineCap.Square }; 16 yield return new object[] { new GraphicsPath(), null, LineCap.Round, -1f, LineCap.Round }; 17 yield return new object[] { new GraphicsPath(), null, LineCap.Triangle, float.MaxValue, LineCap.Triangle }; 18 // All of these "anchor" values yield a "Flat" LineCap. 19 yield return new object[] { new GraphicsPath(), null, LineCap.NoAnchor, 0f, LineCap.Flat }; 20 yield return new object[] { new GraphicsPath(), null, LineCap.SquareAnchor, 0f, LineCap.Flat }; 21 yield return new object[] { new GraphicsPath(), null, LineCap.DiamondAnchor, 0f, LineCap.Flat }; 22 yield return new object[] { new GraphicsPath(), null, LineCap.ArrowAnchor, 0f, LineCap.Flat }; 23 24 // Boxy cap 25 GraphicsPath strokePath = new GraphicsPath(); 26 strokePath.AddRectangle(new Rectangle(0, 0, 10, 10)); 27 yield return new object[] { null, strokePath, LineCap.Square, 0f, LineCap.Square }; 28 29 // Hook-shaped cap 30 strokePath = new GraphicsPath(); 31 strokePath.AddLine(new Point(0, 0), new Point(0, 5)); 32 strokePath.AddLine(new Point(0, 5), new Point(5, 1)); 33 strokePath.AddLine(new Point(5, 1), new Point(3, 1)); 34 yield return new object[] { null, strokePath, LineCap.Flat, 0f, LineCap.Flat }; 35 36 // Fill path -- Must intercept the Y-axis. 37 GraphicsPath fillPath = new GraphicsPath(); 38 fillPath.AddLine(new Point(-5, -10), new Point(0, 10)); 39 fillPath.AddLine(new Point(0, 10), new Point(5, -10)); 40 fillPath.AddLine(new Point(5, -10), new Point(-5, -10)); 41 yield return new object[] { fillPath, null, LineCap.Flat, 0f, LineCap.Flat }; 42 } 43 44 [ActiveIssue(20884, TestPlatforms.AnyUnix)] 45 [ConditionalTheory(Helpers.GdiplusIsAvailable)] 46 [MemberData(nameof(Ctor_Path_Path_LineCap_Float_TestData))] Ctor_Path_Path_LineCap_Float(GraphicsPath fillPath, GraphicsPath strokePath, LineCap baseCap, float baseInset, LineCap expectedCap)47 public void Ctor_Path_Path_LineCap_Float(GraphicsPath fillPath, GraphicsPath strokePath, LineCap baseCap, float baseInset, LineCap expectedCap) 48 { 49 using (fillPath) 50 using (strokePath) 51 using (CustomLineCap customLineCap = new CustomLineCap(fillPath, strokePath, baseCap, baseInset)) 52 { 53 Assert.Equal(expectedCap, customLineCap.BaseCap); 54 Assert.Equal(baseInset, customLineCap.BaseInset); 55 Assert.Equal(LineJoin.Miter, customLineCap.StrokeJoin); 56 Assert.Equal(1f, customLineCap.WidthScale); 57 } 58 } 59 60 [ActiveIssue(20884, TestPlatforms.AnyUnix)] 61 [ConditionalTheory(Helpers.GdiplusIsAvailable)] 62 // These values are outside the valid range of the LineCap enum. 63 [InlineData(LineCap.Flat - 1)] 64 [InlineData(LineCap.Custom + 1)] Ctor_InvalidLineCap_ReturnsFlat(LineCap baseCap)65 public void Ctor_InvalidLineCap_ReturnsFlat(LineCap baseCap) 66 { 67 using (GraphicsPath fillPath = new GraphicsPath()) 68 using (GraphicsPath strokePath = new GraphicsPath()) 69 using (CustomLineCap customLineCap = new CustomLineCap(fillPath, strokePath, baseCap, 0f)) 70 { 71 Assert.Equal(LineCap.Flat, customLineCap.BaseCap); 72 } 73 } 74 75 [ActiveIssue(20884, TestPlatforms.AnyUnix)] 76 [ConditionalFact(Helpers.GdiplusIsAvailable)] Ctor_FillPath_Incomplete_ThrowsArgumentException()77 public void Ctor_FillPath_Incomplete_ThrowsArgumentException() 78 { 79 using (GraphicsPath fillPath = new GraphicsPath()) 80 { 81 fillPath.AddLine(new Point(0, -10), new Point(0, 10)); 82 AssertExtensions.Throws<ArgumentException>(null, () => new CustomLineCap(fillPath, null)); 83 } 84 } 85 86 [ActiveIssue(20884, TestPlatforms.AnyUnix)] 87 [ConditionalFact(Helpers.GdiplusIsAvailable)] Ctor_FillPath_DoesNotCrossYAxis_ThrowsNotImplementedException()88 public void Ctor_FillPath_DoesNotCrossYAxis_ThrowsNotImplementedException() 89 { 90 // Closed fillPath, but does not cross the Y-axis. 91 using (GraphicsPath fillPath = new GraphicsPath()) 92 { 93 fillPath.AddLine(new Point(-5, 5), new Point(5, 5)); 94 fillPath.AddLine(new Point(5, 5), new Point(5, 1)); 95 fillPath.AddLine(new Point(5, 1), new Point(-5, 5)); 96 Assert.Throws<NotImplementedException>(() => new CustomLineCap(fillPath, null)); 97 } 98 } 99 100 [ConditionalTheory(Helpers.GdiplusIsAvailable)] 101 [InlineData(LineCap.Square, LineCap.Square)] 102 [InlineData(LineCap.Round, LineCap.Round)] 103 [InlineData(LineCap.Triangle, LineCap.Triangle)] SetThenGetStrokeCaps_Success(LineCap startCap, LineCap endCap)104 public void SetThenGetStrokeCaps_Success(LineCap startCap, LineCap endCap) 105 { 106 using (GraphicsPath strokePath = new GraphicsPath()) 107 using (CustomLineCap customLineCap = new CustomLineCap(null, strokePath)) 108 { 109 customLineCap.SetStrokeCaps(startCap, endCap); 110 customLineCap.GetStrokeCaps(out LineCap retrievedStartCap, out LineCap retrievedEndCap); 111 112 Assert.Equal(startCap, retrievedStartCap); 113 Assert.Equal(endCap, retrievedEndCap); 114 } 115 } 116 117 [ActiveIssue(20884, TestPlatforms.AnyUnix)] 118 [ConditionalTheory(Helpers.GdiplusIsAvailable)] 119 [InlineData(LineCap.SquareAnchor, LineCap.SquareAnchor)] 120 [InlineData(LineCap.Custom, LineCap.Custom)] 121 [InlineData(LineCap.Square, LineCap.Custom)] 122 [InlineData(LineCap.Custom, LineCap.SquareAnchor)] 123 [InlineData(LineCap.Flat - 1, LineCap.Flat)] // Below valid enum range 124 [InlineData(LineCap.Custom + 1, LineCap.Flat)] // Above valid enum range SetStrokeCaps_InvalidLineCap_ThrowsArgumentException(LineCap startCap, LineCap endCap)125 public void SetStrokeCaps_InvalidLineCap_ThrowsArgumentException(LineCap startCap, LineCap endCap) 126 { 127 using (GraphicsPath strokePath = new GraphicsPath()) 128 using (CustomLineCap customLineCap = new CustomLineCap(null, strokePath)) 129 { 130 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.SetStrokeCaps(startCap, endCap)); 131 132 // start and end cap should be unchanged. 133 customLineCap.GetStrokeCaps(out LineCap retrievedStartCap, out LineCap retrievedEndCap); 134 Assert.Equal(LineCap.Flat, retrievedStartCap); 135 Assert.Equal(LineCap.Flat, retrievedEndCap); 136 } 137 } 138 139 [ConditionalTheory(Helpers.GdiplusIsAvailable)] 140 [InlineData(LineJoin.Miter)] // Default value 141 [InlineData(LineJoin.Bevel)] 142 [InlineData(LineJoin.Round)] 143 [InlineData(LineJoin.MiterClipped)] 144 // Invalid (non-enum) values are allowed. Their values are stored and returned unchanged. 145 [InlineData(LineJoin.Miter - 1)] 146 [InlineData(LineJoin.MiterClipped + 1)] StrokeJoin_SetThenGet_Success(LineJoin lineJoin)147 public void StrokeJoin_SetThenGet_Success(LineJoin lineJoin) 148 { 149 using (GraphicsPath strokePath = new GraphicsPath()) 150 using (CustomLineCap customLineCap = new CustomLineCap(null, strokePath)) 151 { 152 customLineCap.StrokeJoin = lineJoin; 153 Assert.Equal(lineJoin, customLineCap.StrokeJoin); 154 } 155 } 156 157 [ConditionalTheory(Helpers.GdiplusIsAvailable)] 158 [InlineData(LineCap.Flat)] // Default value 159 [InlineData(LineCap.Square)] 160 [InlineData(LineCap.Round)] 161 [InlineData(LineCap.Triangle)] BaseCap_SetThenGet_Success(LineCap baseCap)162 public void BaseCap_SetThenGet_Success(LineCap baseCap) 163 { 164 using (GraphicsPath strokePath = new GraphicsPath()) 165 using (CustomLineCap customLineCap = new CustomLineCap(null, strokePath)) 166 { 167 customLineCap.BaseCap = baseCap; 168 Assert.Equal(baseCap, customLineCap.BaseCap); 169 } 170 } 171 172 [InlineData(LineCap.NoAnchor)] 173 [InlineData(LineCap.SquareAnchor)] 174 [InlineData(LineCap.RoundAnchor)] 175 [InlineData(LineCap.DiamondAnchor)] 176 [InlineData(LineCap.Custom)] 177 [InlineData(LineCap.Flat - 1)] 178 [InlineData(LineCap.Custom + 1)] BaseCap_Set_InvalidLineCap_ThrowsArgumentException(LineCap baseCap)179 public void BaseCap_Set_InvalidLineCap_ThrowsArgumentException(LineCap baseCap) 180 { 181 using (GraphicsPath strokePath = new GraphicsPath()) 182 using (CustomLineCap customLineCap = new CustomLineCap(null, strokePath)) 183 { 184 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.BaseCap = baseCap); 185 Assert.Equal(LineCap.Flat, customLineCap.BaseCap); 186 } 187 } 188 189 [ConditionalTheory(Helpers.GdiplusIsAvailable)] 190 [InlineData(0f)] 191 [InlineData(1f)] 192 [InlineData(10f)] 193 [InlineData(10000f)] 194 [InlineData(-1f)] 195 [InlineData(-10f)] 196 [InlineData(-10000f)] 197 [InlineData(float.MaxValue)] 198 [InlineData(float.MinValue)] 199 [InlineData(float.PositiveInfinity)] 200 [InlineData(float.NegativeInfinity)] 201 [InlineData(float.NaN)] BaseInset_SetThenGet_Success(float value)202 public void BaseInset_SetThenGet_Success(float value) 203 { 204 using (GraphicsPath strokePath = new GraphicsPath()) 205 using (CustomLineCap customLineCap = new CustomLineCap(null, strokePath)) 206 { 207 customLineCap.BaseInset = value; 208 Assert.Equal(value, customLineCap.BaseInset); 209 } 210 } 211 212 [ConditionalTheory(Helpers.GdiplusIsAvailable)] 213 [InlineData(0f)] 214 [InlineData(1f)] 215 [InlineData(10f)] 216 [InlineData(10000f)] 217 [InlineData(-1f)] 218 [InlineData(-10f)] 219 [InlineData(-10000f)] 220 [InlineData(float.MaxValue)] 221 [InlineData(float.MinValue)] 222 [InlineData(float.PositiveInfinity)] 223 [InlineData(float.NegativeInfinity)] 224 [InlineData(float.NaN)] WidthScale_SetThenGet_Success(float value)225 public void WidthScale_SetThenGet_Success(float value) 226 { 227 using (GraphicsPath strokePath = new GraphicsPath()) 228 using (CustomLineCap customLineCap = new CustomLineCap(null, strokePath)) 229 { 230 customLineCap.WidthScale = value; 231 Assert.Equal(value, customLineCap.WidthScale); 232 } 233 } 234 235 [ConditionalFact(Helpers.GdiplusIsAvailable)] Disposed_MembersThrow()236 public void Disposed_MembersThrow() 237 { 238 using (GraphicsPath strokePath = new GraphicsPath()) 239 using (CustomLineCap customLineCap = new CustomLineCap(null, strokePath)) 240 { 241 customLineCap.Dispose(); 242 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.StrokeJoin); 243 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.BaseCap); 244 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.BaseInset); 245 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.WidthScale); 246 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.Clone()); 247 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.SetStrokeCaps(LineCap.Flat, LineCap.Flat)); 248 AssertExtensions.Throws<ArgumentException>(null, () => customLineCap.GetStrokeCaps(out LineCap startCap, out LineCap endCap)); 249 } 250 } 251 } 252 } 253