diff --git a/ClosedXML/Excel/Style/Colors/XLColor_Static.cs b/ClosedXML/Excel/Style/Colors/XLColor_Static.cs index c4628bc..e0cb109 100644 --- a/ClosedXML/Excel/Style/Colors/XLColor_Static.cs +++ b/ClosedXML/Excel/Style/Colors/XLColor_Static.cs @@ -169,9 +169,20 @@ } } - private static XLColor noColor = new XLColor(); + internal static bool IsNullOrTransparent(XLColor color) + { + return color == null + || !color.HasValue + || IsTransparent(color.Key); + } - public static XLColor NoColor { get { return noColor; } } + internal static bool IsTransparent(in XLColorKey colorKey) + { + return colorKey == NoColor.Key + || (colorKey.ColorType == XLColorType.Indexed && colorKey.Indexed == 64); + } + + public static XLColor NoColor { get; } = new XLColor(); public static XLColor AliceBlue { get { return FromColor(Color.AliceBlue); } } diff --git a/ClosedXML/Excel/Style/XLFill.cs b/ClosedXML/Excel/Style/XLFill.cs index 12f39f7..d5d6849 100644 --- a/ClosedXML/Excel/Style/XLFill.cs +++ b/ClosedXML/Excel/Style/XLFill.cs @@ -91,17 +91,20 @@ if (value == null) throw new ArgumentNullException(nameof(value), "Color cannot be null"); - // 4 ways of determining an "empty" color - if (new XLFillPatternValues[] { XLFillPatternValues.None, XLFillPatternValues.Solid }.Contains(PatternType) - && (BackgroundColor == null - || !BackgroundColor.HasValue - || BackgroundColor == XLColor.NoColor - || BackgroundColor.ColorType == XLColorType.Indexed && BackgroundColor.Indexed == 64)) + if ((PatternType == XLFillPatternValues.None || + PatternType == XLFillPatternValues.Solid) + && XLColor.IsNullOrTransparent(BackgroundColor)) { - PatternType = value.HasValue ? XLFillPatternValues.Solid : XLFillPatternValues.None; + var patternType = value.HasValue ? XLFillPatternValues.Solid : XLFillPatternValues.None; + Modify(k => + { + k.BackgroundColor = value.Key; + k.PatternType = patternType; + return k; + }); } - - Modify(k => { k.BackgroundColor = value.Key; return k; }); + else + Modify(k => { k.BackgroundColor = value.Key; return k; }); } } diff --git a/ClosedXML/Excel/Style/XLFillKey.cs b/ClosedXML/Excel/Style/XLFillKey.cs index 181b223..c7c2278 100644 --- a/ClosedXML/Excel/Style/XLFillKey.cs +++ b/ClosedXML/Excel/Style/XLFillKey.cs @@ -13,35 +13,40 @@ public override int GetHashCode() { var hashCode = 2043579837; + + if (HasNoFill()) return hashCode; + + hashCode = hashCode * -1521134295 + PatternType.GetHashCode(); hashCode = hashCode * -1521134295 + BackgroundColor.GetHashCode(); + + if (HasNoForeground()) return hashCode; + hashCode = hashCode * -1521134295 + PatternColor.GetHashCode(); - - var patternType = PatternType; - if (BackgroundColor.ColorType == XLColorType.Indexed && BackgroundColor.Indexed == 64) - patternType = XLFillPatternValues.None; - - hashCode = hashCode * -1521134295 + patternType.GetHashCode(); - + return hashCode; } public bool Equals(XLFillKey other) { - if (PatternType == XLFillPatternValues.None && other.PatternType == XLFillPatternValues.None) + if (HasNoFill() && other.HasNoFill()) return true; - var patternType1 = PatternType; - var patternType2 = other.PatternType; - - if (BackgroundColor.ColorType == XLColorType.Indexed && BackgroundColor.Indexed == 64) - patternType1 = XLFillPatternValues.None; - - if (other.BackgroundColor.ColorType == XLColorType.Indexed && other.BackgroundColor.Indexed == 64) - patternType2 = XLFillPatternValues.None; - return BackgroundColor == other.BackgroundColor - && PatternColor == other.PatternColor - && patternType1 == patternType2; + && PatternType == other.PatternType + && (HasNoForeground() && other.HasNoForeground() || + PatternColor == other.PatternColor); + } + + private bool HasNoFill() + { + return PatternType == XLFillPatternValues.None + || (PatternType == XLFillPatternValues.Solid && XLColor.IsTransparent(BackgroundColor)); + } + + private bool HasNoForeground() + { + return PatternType == XLFillPatternValues.Solid || + PatternType == XLFillPatternValues.None; } public override bool Equals(object obj) diff --git a/ClosedXML_Tests/Excel/Styles/XLFillTests.cs b/ClosedXML_Tests/Excel/Styles/XLFillTests.cs index 90c3e08..bb7a8fa 100644 --- a/ClosedXML_Tests/Excel/Styles/XLFillTests.cs +++ b/ClosedXML_Tests/Excel/Styles/XLFillTests.cs @@ -30,14 +30,49 @@ var fill1 = new XLFill { BackgroundColor = XLColor.Blue }; var fill2 = new XLFill { BackgroundColor = XLColor.Blue }; Assert.IsTrue(fill1.Equals(fill2)); + Assert.AreEqual(fill1.GetHashCode(), fill2.GetHashCode()); } [Test] public void BackgroundPatternNotEqualCheck() { - var fill1 = new XLFill { BackgroundColor = XLColor.Blue }; - var fill2 = new XLFill { BackgroundColor = XLColor.Red }; + var fill1 = new XLFill { PatternType = XLFillPatternValues.Solid, BackgroundColor = XLColor.Blue }; + var fill2 = new XLFill { PatternType = XLFillPatternValues.Solid, BackgroundColor = XLColor.Red }; Assert.IsFalse(fill1.Equals(fill2)); + Assert.AreNotEqual(fill1.GetHashCode(), fill2.GetHashCode()); + } + + [Test] + public void FillsWithTransparentColorEqual() + { + var fill1 = new XLFill { BackgroundColor = XLColor.ElectricUltramarine, PatternType = XLFillPatternValues.None }; + var fill2 = new XLFill { BackgroundColor = XLColor.EtonBlue, PatternType = XLFillPatternValues.None }; + var fill3 = new XLFill { BackgroundColor = XLColor.FromIndex(64) }; + + Assert.IsTrue(fill1.Equals(fill2)); + Assert.IsTrue(fill1.Equals(fill3)); + Assert.AreEqual(fill1.GetHashCode(), fill2.GetHashCode()); + Assert.AreEqual(fill1.GetHashCode(), fill3.GetHashCode()); + } + + [Test] + public void SolidFillsWithDifferentPatternColorEqual() + { + var fill1 = new XLFill + { + PatternType = XLFillPatternValues.Solid, + BackgroundColor = XLColor.Red, + PatternColor = XLColor.Blue + }; + + var fill2 = new XLFill { + PatternType = XLFillPatternValues.Solid, + BackgroundColor = XLColor.Red, + PatternColor = XLColor.Green + }; + + Assert.IsTrue(fill1.Equals(fill2)); + Assert.AreEqual(fill1.GetHashCode(), fill2.GetHashCode()); } [Test]