|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Drawing.Drawing2D;
using System.Globalization;
namespace System.Drawing.Tests;
public class PenTests
{
public static IEnumerable<object[]> Ctor_Brush_TestData()
{
yield return new object[] { new SolidBrush(Color.Red), PenType.SolidColor };
yield return new object[] { new HatchBrush(HatchStyle.BackwardDiagonal, Color.Red), PenType.HatchFill };
yield return new object[] { new LinearGradientBrush(new Point(0, 0), new Point(0, 2), Color.Purple, Color.Plum), PenType.LinearGradient };
yield return new object[] { new TextureBrush(new Bitmap(1, 1)), PenType.TextureFill };
yield return new object[] { new PathGradientBrush([new(1, 2), new(2, 3)]), PenType.PathGradient };
}
[Theory]
[MemberData(nameof(Ctor_Brush_TestData))]
public void Ctor_Brush<T>(T brush, PenType penType) where T : Brush
{
using (brush)
using (Pen pen = new(brush))
{
VerifyPen<T>(pen, penType, expectedWidth: 1);
}
}
public static IEnumerable<object[]> Ctor_Brush_Width_TestData()
{
foreach (object[] data in Ctor_Brush_TestData())
{
yield return new object[] { data[0], 10, data[1] };
}
// Issue on Non-English Windows with brush width < 1. See https://github.com/dotnet/runtime/issues/60480
if (Environment.OSVersion.Platform != PlatformID.Win32NT || CultureInfo.InstalledUICulture.TwoLetterISOLanguageName == "en")
{
yield return new object[] { new SolidBrush(Color.Red), 0, PenType.SolidColor };
// GDI+ No longer allows negative pen width values (Windows PR6441324)
// yield return new object[] { new SolidBrush(Color.Red), -1, PenType.SolidColor };
// yield return new object[] { new SolidBrush(Color.Red), float.NegativeInfinity, PenType.SolidColor };
}
yield return new object[] { new SolidBrush(Color.Red), float.PositiveInfinity, PenType.SolidColor };
yield return new object[] { new SolidBrush(Color.Red), float.NaN, PenType.SolidColor };
yield return new object[] { new SolidBrush(Color.Red), float.MaxValue, PenType.SolidColor };
}
[Theory]
[MemberData(nameof(Ctor_Brush_Width_TestData))]
public void Ctor_Brush_Width<T>(T brush, float width, PenType expectedPenType) where T : Brush
{
using (brush)
using (Pen pen = new(brush, width))
{
VerifyPen<T>(pen, expectedPenType, width);
}
}
[Fact]
public void Ctor_Brush_MakesClone()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
brush.Color = Color.Blue;
Assert.Equal(Color.FromArgb(Color.Red.ToArgb()), pen.Color);
Assert.Equal(pen.Color, Assert.IsType<SolidBrush>(pen.Brush).Color);
}
[Fact]
public void Ctor_NullBrush_ThrowsArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("brush", () => new Pen(null));
AssertExtensions.Throws<ArgumentNullException>("brush", () => new Pen(null, 0));
}
[Fact]
public void Ctor_DisposedBrush_ThrowsArgumentException()
{
SolidBrush brush = new(Color.Red);
brush.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => new Pen(brush));
AssertExtensions.Throws<ArgumentException>(null, () => new Pen(brush, 10));
}
[Fact]
public void Ctor_Color()
{
using Pen pen = new(Color.Red);
VerifyPen<SolidBrush>(pen, PenType.SolidColor, 1);
Assert.Equal(Color.Red, pen.Color);
}
[Theory]
// GDI+ No longer allows negative pen width values (Windows PR6441324)
// [InlineData(-1)]
// [InlineData(float.NegativeInfinity)]
[InlineData(0)]
[InlineData(1)]
[InlineData(float.PositiveInfinity)]
[InlineData(float.NaN)]
public void Ctor_Color_Width(float width)
{
using Pen pen = new(Color.Red, width);
VerifyPen<SolidBrush>(pen, PenType.SolidColor, width);
Assert.Equal(Color.Red, pen.Color);
}
[Theory]
[InlineData(PenAlignment.Center)]
[InlineData(PenAlignment.Inset)]
[InlineData(PenAlignment.Left)]
[InlineData(PenAlignment.Outset)]
[InlineData(PenAlignment.Right)]
public void Alignment_SetValid_GetReturnsExpected(PenAlignment alignment)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.Alignment = alignment;
Assert.Equal(alignment, pen.Alignment);
}
[Theory]
[InlineData(PenAlignment.Center - 1)]
[InlineData(PenAlignment.Right + 1)]
public void Alignment_SetInvalid_ThrowsInvalidEnumArgumentException(PenAlignment alignment)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.ThrowsAny<ArgumentException>(() => pen.Alignment = alignment);
}
[Fact]
public void Alignment_GetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.Alignment);
AssertExtensions.Throws<ArgumentException>(null, () => pen.Alignment = PenAlignment.Center);
}
[Theory]
[MemberData(nameof(Ctor_Brush_TestData))]
public void Brush_SetValid_GetReturnsExpected<T>(T brush, PenType penType) where T : Brush
{
using Pen pen = new(Color.Red);
pen.Brush = brush;
Assert.IsType<T>(pen.Brush);
Assert.Equal(penType, pen.PenType);
}
[Fact]
public void Brush_SetCustomBrush_ThrowsArgumentException()
{
using Pen pen = new(Color.Red);
AssertExtensions.Throws<ArgumentException>(null, () => pen.Brush = new SubBrush());
}
public class SubBrush : Brush
{
public override object Clone() => this;
}
[Fact]
public void Brush_SetNullBrush_ThrowsArgumentNullException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentNullException>("value", () => pen.Brush = null);
}
[Fact]
public void Brush_SetDisposedBrush_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
brush.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.Brush = brush);
}
[Fact]
public void Brush_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.Brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.Brush = brush);
}
public static IEnumerable<object[]> Clone_TestData()
{
using SolidBrush brush = new(Color.Red);
yield return new object[] { new Pen(brush) };
}
[Theory]
[MemberData(nameof(Clone_TestData))]
public void Clone_Invoke_ReturnsExpected(Pen pen)
{
using (pen)
{
Pen clone = Assert.IsType<Pen>(pen.Clone());
Assert.NotSame(pen, clone);
Assert.Equal(pen.Color, clone.Color);
Assert.Equal(((SolidBrush)pen.Brush).Color, ((SolidBrush)clone.Brush).Color);
Assert.Equal(pen.DashOffset, clone.DashOffset);
Assert.Equal(pen.DashStyle, clone.DashStyle);
Assert.Equal(pen.EndCap, clone.EndCap);
Assert.Equal(pen.StartCap, clone.StartCap);
Assert.Equal(pen.Width, clone.Width);
}
}
[Fact]
public void Clone_Disposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, pen.Clone);
}
[Fact]
public void Color_SolidBrush_ReturnsExpected()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.Equal(Color.FromArgb(Color.Red.ToArgb()), pen.Color);
}
[Fact]
public void Color_HatchBrush_ThrowsArgumentException()
{
using HatchBrush brush = new(HatchStyle.BackwardDiagonal, Color.Red);
using Pen pen = new(brush);
ValidateInitialPenColorState(pen);
}
[Fact]
public void Color_LinearGradientBrush_ThrowsArgumentException()
{
using LinearGradientBrush brush = new(Point.Empty, new Point(1, 2), Color.Blue, Color.Red);
using Pen pen = new(brush);
ValidateInitialPenColorState(pen);
}
private static void ValidateInitialPenColorState(Pen pen)
{
AssertExtensions.Throws<ArgumentException>(null, () => pen.Color);
}
[Theory]
[MemberData(nameof(Ctor_Brush_TestData))]
public void Color_Set_GetReturnsExpected(Brush brush, PenType penType)
{
_ = penType;
using (brush)
using (Pen pen = new(brush))
{
pen.Color = Color.Red;
Assert.Equal(Color.Red, pen.Color);
pen.Color = Color.Red;
Assert.Equal(Color.Red, pen.Color);
}
}
[Fact]
public void Color_GetSetWhenDisposedWithoutBrush_Success()
{
Pen pen = new(Color.Red);
pen.Dispose();
Assert.Equal(Color.Red, pen.Color);
pen.Color = Color.Red;
Assert.Equal(Color.Red, pen.Color);
AssertExtensions.Throws<ArgumentException>(null, () => pen.Color = Color.Black);
}
[Fact]
public void Color_GetSetWhenDisposedWithBrush_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.Color);
AssertExtensions.Throws<ArgumentException>(null, () => pen.Color = Color.Red);
}
[Theory]
[InlineData(new float[] { 0, 0 })]
[InlineData(new float[] { 1, 1 })]
[InlineData(new float[] { float.NaN, 0 })]
public void CompoundArray_SetValidPattern_GetReturnsExpected(float[] compoundArray)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.CompoundArray = compoundArray;
Assert.Equal(compoundArray, pen.CompoundArray);
// CompoundArray should be a clone of the original.
compoundArray[0] = 10;
Assert.NotEqual(compoundArray, pen.CompoundArray);
}
[Fact]
public void CompoundArray_SetNullPattern_ThrowsArgumentNullException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.Throws<ArgumentNullException>(() => pen.CompoundArray = null);
}
[Fact]
public void CompoundArray_SetEmptyPattern_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CompoundArray = []);
}
[Theory]
[InlineData(new float[] { -1, 0 })]
[InlineData(new float[] { float.NegativeInfinity, 0 })]
[InlineData(new float[] { float.PositiveInfinity, 0 })]
[InlineData(new float[] { float.MaxValue, 0 })]
[InlineData(new float[] { 1024, 0 })]
[InlineData(new float[] { 2, 2 })]
[InlineData(new float[] { 1 })]
[InlineData(new float[] { 1, 2, 3 })]
public void CompoundArray_SetInvalidPattern_ThrowsArgumentException(float[] compoundArray)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CompoundArray = compoundArray);
}
[Fact]
public void CompoundArray_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.CompoundArray);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CompoundArray = [1]);
}
[Fact]
public void CustomEndCap_SetValid_GetReturnsExpected()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using GraphicsPath fillPath = new();
using GraphicsPath strokePath = new();
using CustomLineCap lineCap = new(fillPath, strokePath);
lineCap.BaseInset = 100;
pen.CustomEndCap = lineCap;
Assert.Equal(100, pen.CustomEndCap.BaseInset);
// The CustomLineCap should be cloned.
lineCap.BaseInset = 10;
Assert.Equal(100, pen.CustomEndCap.BaseInset);
}
[Fact]
public void CustomEndCap_SetNull_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomEndCap = null);
}
[Fact]
public void CustomEndCap_SetDisposedLineCap_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using GraphicsPath fillPath = new();
using GraphicsPath strokePath = new();
CustomLineCap lineCap = new(fillPath, strokePath);
lineCap.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomEndCap = lineCap);
}
[Fact]
public void CustomEndCap_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using GraphicsPath fillPath = new();
using GraphicsPath strokePath = new();
using CustomLineCap lineCap = new(fillPath, strokePath);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomEndCap);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomEndCap = lineCap);
}
[Fact]
public void CustomStartCap_SetValid_GetReturnsExpected()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using GraphicsPath fillPath = new();
using GraphicsPath strokePath = new();
using CustomLineCap lineCap = new(fillPath, strokePath);
lineCap.BaseInset = 100;
pen.CustomStartCap = lineCap;
Assert.Equal(100, pen.CustomStartCap.BaseInset);
// The CustomLineCap should be cloned.
lineCap.BaseInset = 10;
Assert.Equal(100, pen.CustomStartCap.BaseInset);
}
[Fact]
public void CustomStartCap_SetNull_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomStartCap = null);
}
[Fact]
public void CustomStartCap_SetDisposedLineCap_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using GraphicsPath fillPath = new();
using GraphicsPath strokePath = new();
CustomLineCap lineCap = new(fillPath, strokePath);
lineCap.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomStartCap = lineCap);
}
[Fact]
public void CustomStartCap_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using GraphicsPath fillPath = new();
using GraphicsPath strokePath = new();
using CustomLineCap lineCap = new(fillPath, strokePath);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomStartCap);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomStartCap = lineCap);
}
[Theory]
[InlineData(DashCap.Flat)]
[InlineData(DashCap.Round)]
[InlineData(DashCap.Triangle)]
public void DashCap_SetValid_GetReturnsExpected(DashCap dashCap)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.DashCap = dashCap;
Assert.Equal(dashCap, pen.DashCap);
}
[Theory]
[InlineData(DashCap.Flat - 1)]
[InlineData(DashCap.Round - 1)]
[InlineData(DashCap.Triangle + 1)]
public void DashCap_SetInvalid_ThrowsInvalidEnumArgumentException(DashCap dashCap)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.ThrowsAny<ArgumentException>(() => pen.DashCap = dashCap);
}
[Fact]
public void DashCap_GetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashCap);
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashCap = DashCap.Triangle);
}
[Theory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(10)]
[InlineData(float.NegativeInfinity)]
[InlineData(float.PositiveInfinity)]
[InlineData(float.NaN)]
public void DashOffset_Set_GetReturnsExpected(float dashOffset)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.DashOffset = dashOffset;
Assert.Equal(dashOffset, pen.DashOffset);
}
[Fact]
public void DashOffset_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashOffset);
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashOffset = 10);
}
[Theory]
[InlineData(new float[] { 1 })]
[InlineData(new float[] { 1, 1 })]
[InlineData(new float[] { float.MaxValue, float.NaN, float.PositiveInfinity })]
[InlineData(new float[] { float.MaxValue, float.NaN })]
public void DashPattern_SetValidPattern_GetReturnsExpected(float[] pattern)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.DashPattern = pattern;
Assert.Equal(pattern, pen.DashPattern);
Assert.Equal(DashStyle.Custom, pen.DashStyle);
// DashPattern should be a clone of the original.
pattern[0] = 10;
Assert.NotEqual(pattern, pen.DashPattern);
}
[Fact]
public void DashPattern_SetNullPattern_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashPattern = null);
}
[Fact]
public void DashPattern_SetEmptyPattern_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashPattern = []);
}
[Theory]
[InlineData(new float[] { -1 })]
[InlineData(new float[] { 0 })]
[InlineData(new float[] { 1, -1 })]
[InlineData(new float[] { float.NegativeInfinity })]
public void DashPattern_SetInvalidPattern_ThrowsArgumentException(float[] pattern)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashPattern = pattern);
}
[Fact]
public void DashPattern_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashPattern);
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashPattern = [1]);
}
[Theory]
[InlineData(DashStyle.Dash, new float[] { 3, 1 })]
[InlineData(DashStyle.DashDot, new float[] { 3, 1, 1, 1 })]
[InlineData(DashStyle.DashDotDot, new float[] { 3, 1, 1, 1, 1, 1 })]
[InlineData(DashStyle.Dot, new float[] { 1, 1 })]
[InlineData(DashStyle.Solid, null)]
[InlineData(DashStyle.Custom, new float[] { 1 })]
public void DashStyle_SetValid_GetReturnsExpected(DashStyle dashStyle, float[]? expectedDashPattern)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.DashStyle = dashStyle;
Assert.Equal(dashStyle, pen.DashStyle);
if (expectedDashPattern is null)
{
Assert.Throws<InvalidOperationException>(() => pen.DashPattern);
}
else
{
Assert.Equal(expectedDashPattern, pen.DashPattern);
}
}
[Fact]
public void DashStyle_SetCustomWithDashCount_DoeNotChangePattern()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.DashStyle = DashStyle.Dash;
pen.DashStyle = DashStyle.Custom;
Assert.Equal(DashStyle.Custom, pen.DashStyle);
Assert.Equal([3, 1], pen.DashPattern);
}
[Theory]
[InlineData(DashStyle.Solid - 1)]
[InlineData(DashStyle.Custom + 1)]
public void DashStyle_SetInvalid_ThrowsInvalidEnumArgumentException(DashStyle dashStyle)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.ThrowsAny<ArgumentException>(() => pen.DashStyle = dashStyle);
}
[Fact]
public void DashStyle_GetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashStyle);
AssertExtensions.Throws<ArgumentException>(null, () => pen.DashStyle = DashStyle.Dash);
}
public static IEnumerable<object[]> LineCap_Valid_TestData()
{
yield return new object[] { LineCap.Flat };
yield return new object[] { LineCap.Square };
yield return new object[] { LineCap.Round };
yield return new object[] { LineCap.Triangle };
yield return new object[] { LineCap.NoAnchor };
yield return new object[] { LineCap.SquareAnchor };
yield return new object[] { LineCap.RoundAnchor };
yield return new object[] { LineCap.DiamondAnchor };
yield return new object[] { LineCap.ArrowAnchor };
yield return new object[] { LineCap.AnchorMask };
yield return new object[] { LineCap.Custom };
}
[Theory]
[MemberData(nameof(LineCap_Valid_TestData))]
public void EndCap_SetValid_GetReturnsExpected(LineCap lineCap)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.EndCap = lineCap;
Assert.Equal(lineCap, pen.EndCap);
}
public static IEnumerable<object[]> LineCap_Invalid_TestData()
{
yield return new object[] { LineCap.Flat - 1 };
yield return new object[] { LineCap.Triangle + 1 };
yield return new object[] { LineCap.ArrowAnchor + 1 };
yield return new object[] { LineCap.AnchorMask + 1 };
yield return new object[] { LineCap.Custom + 1 };
}
[Theory]
[MemberData(nameof(LineCap_Invalid_TestData))]
public void EndCap_SetInvalid_ThrowsInvalidEnumArgumentException(LineCap lineCap)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.ThrowsAny<ArgumentException>(() => pen.EndCap = lineCap);
}
[Fact]
public void EndCap_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.EndCap);
AssertExtensions.Throws<ArgumentException>(null, () => pen.EndCap = LineCap.ArrowAnchor);
}
[Theory]
[InlineData(LineJoin.Bevel)]
[InlineData(LineJoin.Miter)]
[InlineData(LineJoin.MiterClipped)]
[InlineData(LineJoin.Round)]
public void LineJoin_SetValid_GetReturnsExpected(LineJoin lineJoin)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.LineJoin = lineJoin;
Assert.Equal(lineJoin, pen.LineJoin);
}
[Theory]
[InlineData(LineJoin.Miter - 1)]
[InlineData(LineJoin.MiterClipped + 1)]
public void LineJoin_SetInvalid_ThrowsInvalidEnumArgumentException(LineJoin lineJoin)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.ThrowsAny<ArgumentException>(() => pen.LineJoin = lineJoin);
}
[Fact]
public void LineJoin_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.LineJoin);
AssertExtensions.Throws<ArgumentException>(null, () => pen.LineJoin = LineJoin.Miter);
}
[Theory]
[InlineData(-1, 1)]
[InlineData(0, 1)]
[InlineData(10, 10)]
[InlineData(float.NegativeInfinity, 1)]
[InlineData(float.PositiveInfinity, float.PositiveInfinity)]
[InlineData(float.NaN, float.NaN)]
public void MiterLimit_Set_GetReturnsExpected(float miterLimit, float expectedMiterLimit)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.MiterLimit = miterLimit;
Assert.Equal(expectedMiterLimit, pen.MiterLimit);
}
[Fact]
public void MiterLimit_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.MiterLimit);
AssertExtensions.Throws<ArgumentException>(null, () => pen.MiterLimit = 10);
}
public static IEnumerable<object[]> MultiplyTransform_TestData()
{
yield return new object[] { new Matrix(), new Matrix(1, 2, 3, 4, 5, 6), MatrixOrder.Prepend };
yield return new object[] { new Matrix(), new Matrix(1, 2, 3, 4, 5, 6), MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), new Matrix(2, 3, 4, 5, 6, 7), MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), new Matrix(2, 3, 4, 5, 6, 7), MatrixOrder.Append };
}
[Theory]
[MemberData(nameof(MultiplyTransform_TestData))]
public void MultiplyTransform_Matrix_SetsTransformToExpected(Matrix originalTransform, Matrix matrix, MatrixOrder matrixOrder)
{
try
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using Matrix expected = originalTransform.Clone();
expected.Multiply(matrix, matrixOrder);
pen.Transform = originalTransform;
if (matrixOrder == MatrixOrder.Prepend)
{
Pen clone = (Pen)pen.Clone();
clone.MultiplyTransform(matrix);
Assert.Equal(expected, clone.Transform);
}
pen.MultiplyTransform(matrix, matrixOrder);
Assert.Equal(expected, pen.Transform);
}
finally
{
originalTransform.Dispose();
matrix.Dispose();
}
}
[Fact]
public void MultiplyTransform_NullMatrix_ThrowsArgumentNullException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.Throws<ArgumentNullException>(() => pen.MultiplyTransform(null));
Assert.Throws<ArgumentNullException>(() => pen.MultiplyTransform(null, MatrixOrder.Prepend));
}
[Fact]
public void MultiplyTransform_NotInvertibleMatrix_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using Matrix matrix = new(123, 24, 82, 16, 47, 30);
AssertExtensions.Throws<ArgumentException>(null, () => pen.MultiplyTransform(matrix));
AssertExtensions.Throws<ArgumentException>(null, () => pen.MultiplyTransform(matrix, MatrixOrder.Prepend));
}
[Fact]
public void MultiplyTransform_DisposedMatrix_Nop()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using Matrix transform = new(1, 2, 3, 4, 5, 6);
pen.Transform = transform;
Matrix matrix = new();
matrix.Dispose();
pen.MultiplyTransform(matrix);
pen.MultiplyTransform(matrix, MatrixOrder.Append);
Assert.Equal(transform, pen.Transform);
}
[Theory]
[InlineData(MatrixOrder.Prepend - 1)]
[InlineData(MatrixOrder.Append + 1)]
public void MultiplyTransform_InvalidOrder_Nop(MatrixOrder matrixOrder)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using Matrix transform = new(1, 2, 3, 4, 5, 6);
using Matrix matrix = new();
pen.Transform = transform;
pen.MultiplyTransform(matrix, matrixOrder);
Assert.Equal(transform, pen.Transform);
}
[Fact]
public void MultiplyTransform_Disposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Matrix matrix = new();
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.MultiplyTransform(matrix));
AssertExtensions.Throws<ArgumentException>(null, () => pen.MultiplyTransform(matrix, MatrixOrder.Prepend));
}
[Fact]
public void ResetTransform_Invoke_SetsTransformToZero()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using Matrix transform = new(1, 2, 3, 4, 5, 6);
using Matrix matrix = new();
pen.Transform = transform;
pen.ResetTransform();
Assert.Equal(matrix, pen.Transform);
pen.ResetTransform();
Assert.Equal(matrix, pen.Transform);
}
[Fact]
public void ResetTransform_Disposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Matrix matrix = new();
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, pen.ResetTransform);
}
public static IEnumerable<object[]> RotateTransform_TestData()
{
yield return new object[] { new Matrix(), 90, MatrixOrder.Prepend };
yield return new object[] { new Matrix(), 90, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 360, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 360, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), -45, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), -45, MatrixOrder.Append };
}
[Theory]
[MemberData(nameof(RotateTransform_TestData))]
public void RotateTransform_Invoke_SetsTransformToExpected(Matrix originalTransform, float angle, MatrixOrder matrixOrder)
{
using (originalTransform)
using (SolidBrush brush = new(Color.Red))
using (Pen pen = new(brush))
using (Matrix expected = originalTransform.Clone())
{
expected.Rotate(angle, matrixOrder);
pen.Transform = originalTransform;
if (matrixOrder == MatrixOrder.Prepend)
{
Pen clone = (Pen)pen.Clone();
clone.RotateTransform(angle);
Assert.Equal(expected, clone.Transform);
}
pen.RotateTransform(angle, matrixOrder);
Assert.Equal(expected, pen.Transform);
}
}
[Theory]
[InlineData(MatrixOrder.Prepend - 1)]
[InlineData(MatrixOrder.Append + 1)]
public void RotateTransform_InvalidOrder_ThrowsArgumentException(MatrixOrder matrixOrder)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.RotateTransform(10, matrixOrder));
}
[Fact]
public void RotateTransform_Disposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Matrix matrix = new();
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.RotateTransform(1));
AssertExtensions.Throws<ArgumentException>(null, () => pen.RotateTransform(1, MatrixOrder.Prepend));
}
public static IEnumerable<object[]> ScaleTransform_TestData()
{
yield return new object[] { new Matrix(), 2, 3, MatrixOrder.Prepend };
yield return new object[] { new Matrix(), 2, 3, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0, 0, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0, 0, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 1, 1, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 1, 1, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), -2, -3, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), -2, -3, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0.5, 0.75, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0.5, 0.75, MatrixOrder.Append };
}
[Theory]
[MemberData(nameof(ScaleTransform_TestData))]
public void ScaleTransform_Invoke_SetsTransformToExpected(Matrix originalTransform, float scaleX, float scaleY, MatrixOrder matrixOrder)
{
using (originalTransform)
using (SolidBrush brush = new(Color.Red))
using (Pen pen = new(brush))
using (Matrix expected = originalTransform.Clone())
{
expected.Scale(scaleX, scaleY, matrixOrder);
pen.Transform = originalTransform;
if (matrixOrder == MatrixOrder.Prepend)
{
Pen clone = (Pen)pen.Clone();
clone.ScaleTransform(scaleX, scaleY);
Assert.Equal(expected, clone.Transform);
}
pen.ScaleTransform(scaleX, scaleY, matrixOrder);
Assert.Equal(expected, pen.Transform);
}
}
[Theory]
[InlineData(MatrixOrder.Prepend - 1)]
[InlineData(MatrixOrder.Append + 1)]
public void ScaleTransform_InvalidOrder_ThrowsArgumentException(MatrixOrder matrixOrder)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.ScaleTransform(1, 2, matrixOrder));
}
[Fact]
public void ScaleTransform_Disposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Matrix matrix = new();
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.ScaleTransform(1, 2));
AssertExtensions.Throws<ArgumentException>(null, () => pen.ScaleTransform(1, 2, MatrixOrder.Prepend));
}
[Theory]
[InlineData(LineCap.Flat, LineCap.Round, DashCap.Triangle)]
[InlineData(LineCap.Flat - 1, LineCap.Flat - 1, DashCap.Flat - 1)]
[InlineData((LineCap)int.MaxValue, (LineCap)int.MaxValue, (DashCap)int.MaxValue)]
public void SetLineCap_Invoke_Success(LineCap startCap, LineCap endCap, DashCap dashCap)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
// Make sure that if DashCap is invalid then it is reset to Flat.
if (Enum.IsDefined(typeof(DashCap), dashCap))
{
pen.DashCap = DashCap.Round;
}
pen.SetLineCap(startCap, endCap, dashCap);
Assert.Equal(startCap, pen.StartCap);
Assert.Equal(endCap, pen.EndCap);
Assert.Equal(Enum.IsDefined(typeof(DashCap), dashCap) ? dashCap : DashCap.Flat, pen.DashCap);
}
[Fact]
public void SetLineCap_Disposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.SetLineCap(LineCap.AnchorMask, LineCap.ArrowAnchor, DashCap.Flat));
}
[Theory]
[MemberData(nameof(LineCap_Valid_TestData))]
public void StartCap_SetValid_GetReturnsExpected(LineCap lineCap)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.StartCap = lineCap;
Assert.Equal(lineCap, pen.StartCap);
}
[Theory]
[MemberData(nameof(LineCap_Invalid_TestData))]
public void StartCap_SetInvalid_ThrowsInvalidEnumArgumentException(LineCap lineCap)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Assert.ThrowsAny<ArgumentException>(() => pen.StartCap = lineCap);
}
[Fact]
public void StartCap_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.StartCap);
AssertExtensions.Throws<ArgumentException>(null, () => pen.StartCap = LineCap.ArrowAnchor);
}
[Fact]
public void Transform_SetValid_GetReturnsExpected()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using Matrix matrix = new(1, 2, 3, 4, 5, 6);
using Matrix expected = new(1, 2, 3, 4, 5, 6);
pen.Transform = matrix;
Assert.Equal(matrix, pen.Transform);
// The Matrix should be cloned.
matrix.Translate(1, 2);
Assert.Equal(expected, pen.Transform);
}
[Fact]
public void Transform_SetNull_ThrowsArgumentNullException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentNullException>("value", () => pen.Transform = null);
}
[Fact]
public void Transform_SetNotInvertible_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
using Matrix matrix = new(123, 24, 82, 16, 47, 30);
AssertExtensions.Throws<ArgumentException>(null, () => pen.Transform = matrix);
}
[Fact]
public void Transform_SetDisposedLineCap_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
Matrix matrix = new();
matrix.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.Transform = matrix);
}
[Fact]
public void Transform_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Matrix matrix = new();
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.Transform);
AssertExtensions.Throws<ArgumentException>(null, () => pen.Transform = matrix);
}
public static IEnumerable<object[]> TranslateTransform_TestData()
{
yield return new object[] { new Matrix(), 2, 3, MatrixOrder.Prepend };
yield return new object[] { new Matrix(), 2, 3, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0, 0, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0, 0, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 1, 1, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 1, 1, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), -2, -3, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), -2, -3, MatrixOrder.Append };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0.5, 0.75, MatrixOrder.Prepend };
yield return new object[] { new Matrix(1, 2, 3, 4, 5, 6), 0.5, 0.75, MatrixOrder.Append };
}
[Theory]
[MemberData(nameof(TranslateTransform_TestData))]
public void TranslateTransform_Invoke_SetsTransformToExpected(Matrix originalTransform, float dX, float dY, MatrixOrder matrixOrder)
{
using (originalTransform)
using (SolidBrush brush = new(Color.Red))
using (Pen pen = new(brush))
using (Matrix expected = originalTransform.Clone())
{
expected.Translate(dX, dY, matrixOrder);
pen.Transform = originalTransform;
if (matrixOrder == MatrixOrder.Prepend)
{
Pen clone = (Pen)pen.Clone();
clone.TranslateTransform(dX, dY);
Assert.Equal(expected, clone.Transform);
}
pen.TranslateTransform(dX, dY, matrixOrder);
Assert.Equal(expected, pen.Transform);
}
}
[Theory]
[InlineData(MatrixOrder.Prepend - 1)]
[InlineData(MatrixOrder.Append + 1)]
public void TranslateTransform_InvalidOrder_ThrowsArgumentException(MatrixOrder matrixOrder)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
AssertExtensions.Throws<ArgumentException>(null, () => pen.TranslateTransform(1, 2, matrixOrder));
}
[Fact]
public void TranslateTransform_Disposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
using Matrix matrix = new();
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.TranslateTransform(1, 2));
AssertExtensions.Throws<ArgumentException>(null, () => pen.TranslateTransform(1, 2, MatrixOrder.Prepend));
}
[Theory]
[InlineData(-10)]
[InlineData(0)]
[InlineData(10)]
[InlineData(float.NegativeInfinity)]
[InlineData(float.PositiveInfinity)]
[InlineData(float.NaN)]
public void Width_Set_GetReturnsExpected(float value)
{
using SolidBrush brush = new(Color.Red);
using Pen pen = new(brush);
pen.Width = value;
Assert.Equal(value, pen.Width);
}
[Fact]
public void Width_GetSetWhenDisposed_ThrowsArgumentException()
{
using SolidBrush brush = new(Color.Red);
Pen pen = new(brush);
pen.Dispose();
AssertExtensions.Throws<ArgumentException>(null, () => pen.Width);
AssertExtensions.Throws<ArgumentException>(null, () => pen.Width = 10);
}
private static void VerifyPen<T>(Pen pen, PenType expectedPenType, float expectedWidth) where T : Brush
{
Assert.Equal(PenAlignment.Center, pen.Alignment);
Assert.IsType<T>(pen.Brush);
Assert.Empty(pen.CompoundArray);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomEndCap);
AssertExtensions.Throws<ArgumentException>(null, () => pen.CustomStartCap);
Assert.Equal(DashCap.Flat, pen.DashCap);
Assert.Equal(0, pen.DashOffset);
Assert.Throws<InvalidOperationException>(() => pen.DashPattern);
Assert.Equal(DashStyle.Solid, pen.DashStyle);
Assert.Equal(LineCap.Flat, pen.EndCap);
Assert.Equal(LineJoin.Miter, pen.LineJoin);
Assert.Equal(10, pen.MiterLimit);
Assert.Equal(expectedPenType, pen.PenType);
Assert.Equal(LineCap.Flat, pen.StartCap);
using (Matrix matrix = new())
{
Assert.Equal(new Matrix(), pen.Transform);
}
Assert.Equal(expectedWidth, pen.Width);
}
}
|