diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bf4c9a..c341bc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Released on tbd. - Updated to use AngleSharp 1.0 (#150) - Updated media parsing to media L4 spec (#133) +- Updated naming of CSS values (e.g., `Color` to `CssColorValue`) - Fixed issue when updating shorthands with invalid values (#129) - Fixed issue with appended EOF character in `CssText` (#123) - Fixed missing semicolon in `@page` rule (#135) @@ -15,6 +16,7 @@ Released on tbd. - Fixed `GetInnerText` multi-line / text node behavior (#155) @Seyden - Fixed computation of relative (`em`) values to absolute (`px`) for `Length` (#136) - Added further compactification of CSS tuples (#89, #93) +- Added new value types `CssPercentageValue`, `CssNumberValue`, and `CssIntegerValue` - Added support for CSS nesting in style rules (#148) - Added resolution of CSS variable names (#62) - Added support for 8-digit hex color codes (#132) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index fb4a060..0058dde 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -17,6 +17,7 @@ AngleSharp.Css contains code written by (in order of first pull request / commit * [Fraaankes](https://github.com/Fraaankes) * [Eric Mutta](https://github.com/ericmutta) * [Seyden](https://github.com/Seyden) +* [Dave Dunkin](https://github.com/ddunkin) Without these awesome people AngleSharp.Css could not exist. Thanks to everyone for your contributions! :beers: diff --git a/src/AngleSharp.Css.Tests/Values/Gradient.cs b/src/AngleSharp.Css.Tests/Values/Gradient.cs index e6aec66..017e848 100644 --- a/src/AngleSharp.Css.Tests/Values/Gradient.cs +++ b/src/AngleSharp.Css.Tests/Values/Gradient.cs @@ -41,10 +41,10 @@ namespace AngleSharp.Css.Tests.Values var gradient = value.Items[0] as CssLinearGradientValue; Assert.IsNotNull(gradient); Assert.IsFalse(gradient.IsRepeating); - Assert.AreEqual(Angle.TripleHalfQuarter, gradient.Angle); + Assert.AreEqual(CssAngleValue.TripleHalfQuarter, gradient.Angle); Assert.AreEqual(2, gradient.Stops.Length); - Assert.AreEqual(red, gradient.Stops.First().Color); - Assert.AreEqual(blue, gradient.Stops.Last().Color); + Assert.AreEqual(red, gradient.Stops.OfType().First().Color); + Assert.AreEqual(blue, gradient.Stops.OfType().Last().Color); Assert.AreEqual(source, property.CssText); } @@ -61,16 +61,16 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(1, value.Items.Length); var gradient = value.Items[0] as CssLinearGradientValue; Assert.IsFalse(gradient.IsRepeating); - Assert.AreEqual(Angle.Quarter, gradient.Angle); + Assert.AreEqual(CssAngleValue.Quarter, gradient.Angle); var stops = gradient.Stops.ToArray(); Assert.AreEqual(7, stops.Length); - Assert.AreEqual(CssColors.GetColor("red").Value, stops[0].Color); - Assert.AreEqual(CssColors.GetColor("orange").Value, stops[1].Color); - Assert.AreEqual(CssColors.GetColor("yellow").Value, stops[2].Color); - Assert.AreEqual(CssColors.GetColor("green").Value, stops[3].Color); - Assert.AreEqual(CssColors.GetColor("blue").Value, stops[4].Color); - Assert.AreEqual(CssColors.GetColor("indigo").Value, stops[5].Color); - Assert.AreEqual(CssColors.GetColor("violet").Value, stops[6].Color); + Assert.AreEqual(CssColors.GetColor("red").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColors.GetColor("orange").Value, ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColors.GetColor("yellow").Value, ((CssGradientStopValue)stops[2]).Color); + Assert.AreEqual(CssColors.GetColor("green").Value, ((CssGradientStopValue)stops[3]).Color); + Assert.AreEqual(CssColors.GetColor("blue").Value, ((CssGradientStopValue)stops[4]).Color); + Assert.AreEqual(CssColors.GetColor("indigo").Value, ((CssGradientStopValue)stops[5]).Color); + Assert.AreEqual(CssColors.GetColor("violet").Value, ((CssGradientStopValue)stops[6]).Color); } [Test] @@ -85,10 +85,10 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(1, value.Items.Length); var gradient = value.Items[0] as CssLinearGradientValue; Assert.IsFalse(gradient.IsRepeating); - Assert.AreEqual(Angle.TripleHalfQuarter, gradient.Angle); + Assert.AreEqual(CssAngleValue.TripleHalfQuarter, gradient.Angle); Assert.AreEqual(2, gradient.Stops.Count()); - Assert.AreEqual(CssColorValue.Red, gradient.Stops.First().Color); - Assert.AreEqual(CssColorValue.FromRgba(255, 0, 0, 0), gradient.Stops.Last().Color); + Assert.AreEqual(CssColorValue.Red, gradient.Stops.OfType().First().Color); + Assert.AreEqual(CssColorValue.FromRgba(255, 0, 0, 0), gradient.Stops.OfType().Last().Color); } [Test] @@ -103,10 +103,10 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(1, value.Items.Length); var gradient = value.Items[0] as CssLinearGradientValue; Assert.IsFalse(gradient.IsRepeating); - Assert.AreEqual(Angle.Half, gradient.Angle); + Assert.AreEqual(CssAngleValue.Half, gradient.Angle); Assert.AreEqual(2, gradient.Stops.Count()); - Assert.AreEqual(CssColorValue.FromHsl(0f, 0.8f, 0.7f), gradient.Stops.First().Color); - Assert.AreEqual(CssColorValue.FromHex("bada55"), gradient.Stops.Last().Color); + Assert.AreEqual(CssColorValue.FromHsl(0f, 0.8f, 0.7f), gradient.Stops.OfType().First().Color); + Assert.AreEqual(CssColorValue.FromHex("bada55"), gradient.Stops.OfType().Last().Color); } [Test] @@ -121,11 +121,11 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(1, value.Items.Length); var gradient = value.Items[0] as CssLinearGradientValue; Assert.IsFalse(gradient.IsRepeating); - Assert.AreEqual(Angle.Half, gradient.Angle); + Assert.AreEqual(CssAngleValue.Half, gradient.Angle); Assert.AreEqual(3, gradient.Stops.Count()); - Assert.AreEqual(CssColors.GetColor("yellow").Value, gradient.Stops.First().Color); - Assert.AreEqual(CssColors.GetColor("blue").Value, gradient.Stops.Skip(1).First().Color); - Assert.AreEqual(CssColorValue.FromRgb(0, 255, 0), gradient.Stops.Skip(2).First().Color); + Assert.AreEqual(CssColors.GetColor("yellow").Value, gradient.Stops.OfType().First().Color); + Assert.AreEqual(CssColors.GetColor("blue").Value, gradient.Stops.OfType().Skip(1).First().Color); + Assert.AreEqual(CssColorValue.FromRgb(0, 255, 0), gradient.Stops.OfType().Skip(2).First().Color); } [Test] @@ -146,9 +146,9 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.FarthestCorner, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(3, stops.Length); - Assert.AreEqual(CssColorValue.FromRgb(0, 255, 255), stops[0].Color); - Assert.AreEqual(CssColorValue.FromRgba(0, 0, 255, 0), stops[1].Color); - Assert.AreEqual(CssColorValue.FromRgb(0, 0, 255), stops[2].Color); + Assert.AreEqual(CssColorValue.FromRgb(0, 255, 255), ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromRgba(0, 0, 255, 0), ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromRgb(0, 0, 255), ((CssGradientStopValue)stops[2]).Color); } [Test] @@ -169,9 +169,9 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.FarthestCorner, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(3, stops.Length); - Assert.AreEqual(CssColorValue.FromRgb(0xFF, 0xFF, 0x80), stops[0].Color); - Assert.AreEqual(CssColorValue.FromRgba(204, 153, 153, 0.4f), stops[1].Color); - Assert.AreEqual(CssColorValue.FromRgb(0xE6, 0xE6, 0xFF), stops[2].Color); + Assert.AreEqual(CssColorValue.FromRgb(0xFF, 0xFF, 0x80), ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromRgba(204, 153, 153, 0.4f), ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromRgb(0xE6, 0xE6, 0xFF), ((CssGradientStopValue)stops[2]).Color); } [Test] @@ -192,8 +192,8 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.FarthestCorner, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(2, stops.Length); - Assert.AreEqual(CssColorValue.FromRgb(255, 0, 0), stops[0].Color); - Assert.AreEqual(CssColorValue.FromRgb(0, 0, 255), stops[1].Color); + Assert.AreEqual(CssColorValue.FromRgb(255, 0, 0), ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromRgb(0, 0, 255), ((CssGradientStopValue)stops[1]).Color); } [Test] @@ -216,10 +216,10 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssLengthValue.Full, gradient.MinorRadius); var stops = gradient.Stops.ToArray(); Assert.AreEqual(4, stops.Length); - Assert.AreEqual(CssColorValue.FromRgb(0, 0, 0), stops[0].Color); - Assert.AreEqual(CssColorValue.FromRgb(0, 0, 0), stops[1].Color); - Assert.AreEqual(CssColorValue.FromRgba(0, 0, 0, 0.3), stops[2].Color); - Assert.AreEqual(CssColorValue.Transparent, stops[3].Color); + Assert.AreEqual(CssColorValue.FromRgb(0, 0, 0), ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromRgb(0, 0, 0), ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromRgba(0, 0, 0, 0.3), ((CssGradientStopValue)stops[2]).Color); + Assert.AreEqual(CssColorValue.Transparent, ((CssGradientStopValue)stops[3]).Color); } [Test] @@ -240,8 +240,8 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.None, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(2, stops.Length); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[1].Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[1]).Color); } [Test] @@ -262,8 +262,8 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.None, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(2, stops.Length); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[1].Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[1]).Color); } [Test] @@ -284,8 +284,8 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.None, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(2, stops.Length); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[1].Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[1]).Color); } [Test] @@ -306,8 +306,8 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.FarthestCorner, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(2, stops.Length); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[1].Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[1]).Color); } [Test] @@ -328,9 +328,9 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.ClosestSide, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(3, stops.Length); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[1].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[2].Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[2]).Color); } [Test] @@ -353,9 +353,9 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(new CssLengthValue(30f, CssLengthValue.Unit.Px), gradient.MinorRadius); var stops = gradient.Stops.ToArray(); Assert.AreEqual(3, stops.Length); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[1].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[2].Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[2]).Color); } [Test] @@ -376,9 +376,9 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.ClosestSide, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(3, stops.Length); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[1].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[2].Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[2]).Color); } [Test] @@ -399,9 +399,9 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.FarthestSide, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(3, stops.Length); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[1].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[2].Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[2]).Color); } [Test] @@ -418,9 +418,9 @@ namespace AngleSharp.Css.Tests.Values Assert.IsTrue(gradient.IsRepeating); var stops = gradient.Stops.ToArray(); Assert.AreEqual(3, stops.Length); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("blue").Value, stops[1].Color); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[2].Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("blue").Value, ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[2]).Color); } [Test] @@ -441,9 +441,9 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.None, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(3, stops.Length); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("blue").Value, stops[1].Color); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[2].Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("blue").Value, ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[2]).Color); } [Test] @@ -464,11 +464,11 @@ namespace AngleSharp.Css.Tests.Values Assert.AreEqual(CssRadialGradientValue.SizeMode.ClosestSide, gradient.Mode); var stops = gradient.Stops.ToArray(); Assert.AreEqual(5, stops.Length); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[0].Color); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[1].Color); - Assert.AreEqual(CssColorValue.FromName("green").Value, stops[2].Color); - Assert.AreEqual(CssColorValue.FromName("yellow").Value, stops[3].Color); - Assert.AreEqual(CssColorValue.FromName("red").Value, stops[4].Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[0]).Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[1]).Color); + Assert.AreEqual(CssColorValue.FromName("green").Value, ((CssGradientStopValue)stops[2]).Color); + Assert.AreEqual(CssColorValue.FromName("yellow").Value, ((CssGradientStopValue)stops[3]).Color); + Assert.AreEqual(CssColorValue.FromName("red").Value, ((CssGradientStopValue)stops[4]).Color); } } } diff --git a/src/AngleSharp.Css.Tests/Values/UnitConversion.cs b/src/AngleSharp.Css.Tests/Values/UnitConversion.cs index ee0c631..59eeecc 100644 --- a/src/AngleSharp.Css.Tests/Values/UnitConversion.cs +++ b/src/AngleSharp.Css.Tests/Values/UnitConversion.cs @@ -204,11 +204,11 @@ namespace AngleSharp.Css.Tests.Values public void AngleParseCorrectDegValue() { var s = "1.35e2deg"; - var v = default(Angle); - var r = Angle.TryParse(s, out v); + var v = default(CssAngleValue); + var r = CssAngleValue.TryParse(s, out v); Assert.IsTrue(r); Assert.AreEqual(135f, v.Value); - Assert.AreEqual(Angle.Unit.Deg, v.Type); + Assert.AreEqual(CssAngleValue.Unit.Deg, v.Type); } [Test] @@ -248,8 +248,8 @@ namespace AngleSharp.Css.Tests.Values public void AngleParseIncorrectValue() { var s = "123.deg"; - var v = default(Angle); - var r = Angle.TryParse(s, out v); + var v = default(CssAngleValue); + var r = CssAngleValue.TryParse(s, out v); Assert.IsFalse(r); } } diff --git a/src/AngleSharp.Css/Constants/Map.cs b/src/AngleSharp.Css/Constants/Map.cs index 7485c9e..f831628 100644 --- a/src/AngleSharp.Css/Constants/Map.cs +++ b/src/AngleSharp.Css/Constants/Map.cs @@ -26,16 +26,16 @@ namespace AngleSharp.Css /// /// Contains the string-Angle mapping for linear-gradients.s /// - public static readonly Dictionary GradientAngles = new(StringComparer.OrdinalIgnoreCase) + public static readonly Dictionary GradientAngles = new(StringComparer.OrdinalIgnoreCase) { - { CssKeywords.Left, new Angle(270.0, Angle.Unit.Deg) }, - { CssKeywords.Top, new Angle(0.0, Angle.Unit.Deg) }, - { CssKeywords.Right, new Angle(90.0, Angle.Unit.Deg) }, - { CssKeywords.Bottom, new Angle(180.0, Angle.Unit.Deg) }, - { CssKeywords.LeftTop, new Angle(315.0, Angle.Unit.Deg) }, - { CssKeywords.LeftBottom, new Angle(225.0, Angle.Unit.Deg) }, - { CssKeywords.RightTop, new Angle(45.0, Angle.Unit.Deg) }, - { CssKeywords.RightBottom, new Angle(135.0, Angle.Unit.Deg) }, + { CssKeywords.Left, new CssAngleValue(270.0, CssAngleValue.Unit.Deg) }, + { CssKeywords.Top, new CssAngleValue(0.0, CssAngleValue.Unit.Deg) }, + { CssKeywords.Right, new CssAngleValue(90.0, CssAngleValue.Unit.Deg) }, + { CssKeywords.Bottom, new CssAngleValue(180.0, CssAngleValue.Unit.Deg) }, + { CssKeywords.LeftTop, new CssAngleValue(315.0, CssAngleValue.Unit.Deg) }, + { CssKeywords.LeftBottom, new CssAngleValue(225.0, CssAngleValue.Unit.Deg) }, + { CssKeywords.RightTop, new CssAngleValue(45.0, CssAngleValue.Unit.Deg) }, + { CssKeywords.RightBottom, new CssAngleValue(135.0, CssAngleValue.Unit.Deg) }, }; /// diff --git a/src/AngleSharp.Css/Declarations/ContentDeclaration.cs b/src/AngleSharp.Css/Declarations/ContentDeclaration.cs index 25f79b8..b04a7d7 100644 --- a/src/AngleSharp.Css/Declarations/ContentDeclaration.cs +++ b/src/AngleSharp.Css/Declarations/ContentDeclaration.cs @@ -108,9 +108,9 @@ namespace AngleSharp.Css.Declarations return null; } - private sealed class ContentValue : ICssValue + private sealed class ContentValue : ICssValue, IEquatable { - private ICssValue[] _modes; + private readonly ICssValue[] _modes; public ContentValue(ICssValue[] modes) { @@ -124,6 +124,30 @@ namespace AngleSharp.Css.Declarations var modes = _modes.Select(mode => mode.Compute(context)).ToArray(); return new ContentValue(modes); } + public Boolean Equals(ContentValue other) + { + var l = _modes.Length; + + if (l == other._modes.Length) + { + for (var i = 0; i < l; i++) + { + var a = _modes[i]; + var b = other._modes[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + + Boolean IEquatable.Equals(ICssValue other) => other is ContentValue value && Equals(value); } private abstract class ContentMode : ICssValue @@ -134,10 +158,9 @@ namespace AngleSharp.Css.Declarations public abstract String GetCssText(); - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } + ICssValue ICssValue.Compute(ICssComputeContext context) => this; + + public virtual Boolean Equals(ICssValue other) => Object.ReferenceEquals(this, other); } /// @@ -209,6 +232,16 @@ namespace AngleSharp.Css.Declarations public override String GetCssText() => _text.CssString(); public override String Stringify(IElement element) => _text; + + public override Boolean Equals(ICssValue other) + { + if (other is TextContentMode o) + { + return _text.Equals(o._text); + } + + return false; + } } /// @@ -228,6 +261,16 @@ namespace AngleSharp.Css.Declarations public override String GetCssText() => _counter.CssText; public override String Stringify(IElement element) => String.Empty; + + public override Boolean Equals(ICssValue other) + { + if (other is CounterContentMode o) + { + return _counter.Equals(o._counter); + } + + return false; + } } /// @@ -246,6 +289,16 @@ namespace AngleSharp.Css.Declarations public override String GetCssText() => FunctionNames.Attr.CssFunction(_attribute); public override String Stringify(IElement element) => element.GetAttribute(_attribute) ?? String.Empty; + + public override Boolean Equals(ICssValue other) + { + if (other is AttributeContentMode o) + { + return _attribute.Equals(o._attribute); + } + + return false; + } } /// @@ -265,6 +318,16 @@ namespace AngleSharp.Css.Declarations public override String GetCssText() => _url.CssText; public override String Stringify(IElement element) => String.Empty; + + public override Boolean Equals(ICssValue other) + { + if (other is UrlContentMode o) + { + return _url.Equals(o._url); + } + + return false; + } } } } diff --git a/src/AngleSharp.Css/Declarations/CursorDeclaration.cs b/src/AngleSharp.Css/Declarations/CursorDeclaration.cs index 9df4846..3ef6067 100644 --- a/src/AngleSharp.Css/Declarations/CursorDeclaration.cs +++ b/src/AngleSharp.Css/Declarations/CursorDeclaration.cs @@ -21,20 +21,19 @@ namespace AngleSharp.Css.Declarations { public ICssValue Convert(StringSource source) { - var cursor = default(ICssValue); var definitions = new List(); while (!source.IsDone) { var imageSource = source.ParseImageSource(); - var c = source.SkipSpacesAndComments(); + source.SkipSpacesAndComments(); if (imageSource != null) { var x = source.ParseNumber(); - c = source.SkipSpacesAndComments(); + source.SkipSpacesAndComments(); var y = source.ParseNumber(); - c = source.SkipSpacesAndComments(); + var c = source.SkipSpacesAndComments(); if (x.HasValue != y.HasValue || c != Symbols.Comma) break; @@ -44,16 +43,14 @@ namespace AngleSharp.Css.Declarations if (x.HasValue) { - var xp = new CssLengthValue(x.Value, CssLengthValue.Unit.None); - var yp = new CssLengthValue(y.Value, CssLengthValue.Unit.None); - position = new CssPoint2D(xp, yp); + position = new CssPoint2D(x, y); } definitions.Add(new CssCustomCursorValue(imageSource, position)); } else { - cursor = source.ParseConstant(Map.SystemCursors); + var cursor = source.ParseConstant(Map.SystemCursors); if (cursor != null) { diff --git a/src/AngleSharp.Css/Dom/ICssValue.cs b/src/AngleSharp.Css/Dom/ICssValue.cs index 8b61162..a56cde7 100644 --- a/src/AngleSharp.Css/Dom/ICssValue.cs +++ b/src/AngleSharp.Css/Dom/ICssValue.cs @@ -1,12 +1,12 @@ namespace AngleSharp.Css.Dom { - using System; using AngleSharp.Css.Values; + using System; /// /// Represents a value of a CSS property. /// - public interface ICssValue + public interface ICssValue : IEquatable { /// /// The text representation of the value. diff --git a/src/AngleSharp.Css/Extensions/CssValueExtensions.cs b/src/AngleSharp.Css/Extensions/CssValueExtensions.cs index 2140ec5..5863878 100644 --- a/src/AngleSharp.Css/Extensions/CssValueExtensions.cs +++ b/src/AngleSharp.Css/Extensions/CssValueExtensions.cs @@ -16,17 +16,41 @@ namespace AngleSharp.Css.Dom /// The resulting number. public static Double AsDouble(this ICssValue value) { - if (value is CssLengthValue length && length.Type == CssLengthValue.Unit.None) + if (value is null) { - return length.Value; + return 0.0; + } + else if (value is CssLengthValue l && l.Type == CssLengthValue.Unit.None) + { + return l.Value; + } + else if (value is CssTimeValue t && t.Type == CssTimeValue.Unit.None) + { + return t.Value; + } + else if (value is CssFrequencyValue f && f.Type == CssFrequencyValue.Unit.None) + { + return f.Value; + } + else if (value is CssNumberValue n) + { + return n.Value; + } + else if (value is CssIntegerValue i) + { + return i.Value; + } + else if (value is CssPercentageValue p) + { + return p.Value; } else if (value is CssFractionValue fr) { return fr.Value; } - else if (value is CssRatioValue ratio) + else if (value is CssRatioValue r) { - return ratio.Value; + return r.Top.AsDouble() / r.Bottom.AsDouble(); } else if (value is ICssMultipleValue multiple && multiple.Count == 1) { @@ -49,7 +73,11 @@ namespace AngleSharp.Css.Dom /// The resulting number. public static Double AsPx(this ICssValue value, IRenderDimensions renderDimensions, RenderMode mode) { - if (value is CssLengthValue length && length.Type != CssLengthValue.Unit.None) + if (value is null) + { + return 0.0; + } + else if (value is CssLengthValue length && length.Type != CssLengthValue.Unit.None) { return length.ToPixel(renderDimensions, mode); } @@ -72,7 +100,11 @@ namespace AngleSharp.Css.Dom /// The resulting number. public static Double AsMs(this ICssValue value) { - if (value is CssTimeValue time && time.Type != CssTimeValue.Unit.None) + if (value is null) + { + return 0.0; + } + else if (value is CssTimeValue time && time.Type != CssTimeValue.Unit.None) { return time.ToMilliseconds(); } @@ -95,7 +127,11 @@ namespace AngleSharp.Css.Dom /// The resulting number. public static Double AsHz(this ICssValue value) { - if (value is CssFrequencyValue freq && freq.Type != CssFrequencyValue.Unit.None) + if (value is null) + { + return 0.0; + } + else if (value is CssFrequencyValue freq && freq.Type != CssFrequencyValue.Unit.None) { return freq.ToHertz(); } @@ -118,9 +154,13 @@ namespace AngleSharp.Css.Dom /// The resulting number. public static Double AsDeg(this ICssValue value) { - if (value is Angle angle && angle.Type != Angle.Unit.None) + if (value is null) { - return angle.Value; + return 0.0; + } + else if (value is CssAngleValue angle && angle.Type != CssAngleValue.Unit.None) + { + return angle.ToDegree(); } else if (value is ICssMultipleValue multiple && multiple.Count == 1) { @@ -134,6 +174,33 @@ namespace AngleSharp.Css.Dom return 0.0; } + /// + /// Tries to convert the value to a number of degrees. + /// + /// The value to convert. + /// The resulting number. + public static Double AsRad(this ICssValue value) + { + if (value is null) + { + return 0.0; + } + else if (value is CssAngleValue angle && angle.Type != CssAngleValue.Unit.None) + { + return angle.ToRadian(); + } + else if (value is ICssMultipleValue multiple && multiple.Count == 1) + { + return multiple[0].AsRad(); + } + else if (value is ICssSpecialValue special && special.Value != null) + { + return special.Value.AsRad(); + } + + return 0.0; + } + /// /// Tries to convert the value to a number of dots per inch. /// @@ -141,7 +208,11 @@ namespace AngleSharp.Css.Dom /// The resulting number. public static Double AsDpi(this ICssValue value) { - if (value is CssResolutionValue res && res.Type != CssResolutionValue.Unit.None) + if (value is null) + { + return 0.0; + } + else if (value is CssResolutionValue res && res.Type != CssResolutionValue.Unit.None) { return res.ToDotsPerPixel(); } diff --git a/src/AngleSharp.Css/Parser/Micro/CalcParser.cs b/src/AngleSharp.Css/Parser/Micro/CalcParser.cs index a81f9b7..3c56100 100644 --- a/src/AngleSharp.Css/Parser/Micro/CalcParser.cs +++ b/src/AngleSharp.Css/Parser/Micro/CalcParser.cs @@ -166,10 +166,10 @@ namespace AngleSharp.Css.Parser source.SkipSpacesAndComments(); return new CssTimeValue(result, CssTimeValue.GetUnit(unit.Dimension)); } - else if (Angle.GetUnit(unit.Dimension) != Angle.Unit.None) + else if (CssAngleValue.GetUnit(unit.Dimension) != CssAngleValue.Unit.None) { source.SkipSpacesAndComments(); - return new Angle(result, Angle.GetUnit(unit.Dimension)); + return new CssAngleValue(result, CssAngleValue.GetUnit(unit.Dimension)); } else if (CssFrequencyValue.GetUnit(unit.Dimension) != CssFrequencyValue.Unit.None) { diff --git a/src/AngleSharp.Css/Parser/Micro/ColorParser.cs b/src/AngleSharp.Css/Parser/Micro/ColorParser.cs index d525c8a..2a8bcda 100644 --- a/src/AngleSharp.Css/Parser/Micro/ColorParser.cs +++ b/src/AngleSharp.Css/Parser/Micro/ColorParser.cs @@ -478,11 +478,11 @@ namespace AngleSharp.Css.Parser if (unit != null && Double.TryParse(unit.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var value)) { - var dim = Angle.Unit.Deg; + var dim = CssAngleValue.Unit.Deg; - if (unit.Dimension == String.Empty || (dim = Angle.GetUnit(unit.Dimension)) != Angle.Unit.None) + if (unit.Dimension == String.Empty || (dim = CssAngleValue.GetUnit(unit.Dimension)) != CssAngleValue.Unit.None) { - var angle = new Angle(value, dim); + var angle = new CssAngleValue(value, dim); return angle.ToTurns(); } } diff --git a/src/AngleSharp.Css/Parser/Micro/NumberParser.cs b/src/AngleSharp.Css/Parser/Micro/NumberParser.cs index da25fcd..21b5e61 100644 --- a/src/AngleSharp.Css/Parser/Micro/NumberParser.cs +++ b/src/AngleSharp.Css/Parser/Micro/NumberParser.cs @@ -14,7 +14,7 @@ namespace AngleSharp.Css.Parser /// /// Parses the number (double) value. /// - public static Double? ParseNumber(this StringSource source) + public static CssNumberValue? ParseNumber(this StringSource source) { var unit = source.ParseUnit(); @@ -22,7 +22,7 @@ namespace AngleSharp.Css.Parser unit.Dimension == String.Empty && Double.TryParse(unit.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { - return result; + return new CssNumberValue(result); } return null; @@ -50,12 +50,12 @@ namespace AngleSharp.Css.Parser /// /// Parses the integer (double) value. /// - public static Double? ParseNaturalNumber(this StringSource source) + public static CssNumberValue? ParseNaturalNumber(this StringSource source) { var pos = source.Index; var element = source.ParseNumber(); - if (element.HasValue && element.Value >= 0f) + if (element.HasValue && element.Value.Value >= 0f) { return element; } @@ -67,12 +67,12 @@ namespace AngleSharp.Css.Parser /// /// Parses the natural number (double) value. /// - public static Double? ParseGreaterOrEqualOneNumber(this StringSource source) + public static CssNumberValue? ParseGreaterOrEqualOneNumber(this StringSource source) { var pos = source.Index; var element = source.ParseNumber(); - if (element.HasValue && element.Value >= 1f) + if (element.HasValue && element.Value.Value >= 1f) { return element; } diff --git a/src/AngleSharp.Css/Parser/Micro/TransformParser.cs b/src/AngleSharp.Css/Parser/Micro/TransformParser.cs index b98a42d..68b8192 100644 --- a/src/AngleSharp.Css/Parser/Micro/TransformParser.cs +++ b/src/AngleSharp.Css/Parser/Micro/TransformParser.cs @@ -69,7 +69,7 @@ namespace AngleSharp.Css.Parser private static CssSkewValue ParseSkew2d(StringSource source) { ICssValue x = source.ParseAngleOrCalc(); - ICssValue y = Angle.Zero; + ICssValue y = CssAngleValue.Zero; var c = source.SkipGetSkip(); if (x == null) @@ -148,7 +148,7 @@ namespace AngleSharp.Css.Parser /// private static CssMatrixValue ParseMatrix(StringSource source, Int32 count) { - var numbers = new Double[count]; + var numbers = new ICssValue[count]; var num = source.ParseNumber(); if (num.HasValue) @@ -184,7 +184,7 @@ namespace AngleSharp.Css.Parser /// private static CssRotateValue ParseRotate2d(StringSource source) { - return ParseRotate(source, Double.NaN, Double.NaN, Double.NaN); + return ParseRotate(source, null, null, null); } /// @@ -214,7 +214,7 @@ namespace AngleSharp.Css.Parser /// private static CssRotateValue ParseRotateX(StringSource source) { - return ParseRotate(source, 1f, 0f, 0f); + return ParseRotate(source, CssNumberValue.One, null, null); } /// @@ -223,7 +223,7 @@ namespace AngleSharp.Css.Parser /// private static CssRotateValue ParseRotateY(StringSource source) { - return ParseRotate(source, 0f, 1f, 0f); + return ParseRotate(source, null, CssNumberValue.One, null); } /// @@ -232,21 +232,21 @@ namespace AngleSharp.Css.Parser /// private static CssRotateValue ParseRotateZ(StringSource source) { - return ParseRotate(source, 0f, 0f, 1f); + return ParseRotate(source, null, null, CssNumberValue.One); } /// /// A broad variety of rotate transforms. /// http://www.w3.org/TR/css3-transforms/#funcdef-rotate3d /// - private static CssRotateValue ParseRotate(StringSource source, Double x, Double y, Double z) + private static CssRotateValue ParseRotate(StringSource source, ICssValue x, ICssValue y, ICssValue z) { var angle = source.ParseAngleOrCalc(); var f = source.SkipGetSkip(); if (angle != null && f == Symbols.RoundBracketClose) { - return new CssRotateValue(x, z, y, angle); + return new CssRotateValue(x, y, z, angle); } return null; @@ -263,7 +263,7 @@ namespace AngleSharp.Css.Parser if (x.HasValue) { - var y = default(Double?); + var y = default(ICssValue); if (f == Symbols.Comma) { @@ -273,7 +273,7 @@ namespace AngleSharp.Css.Parser if (f == Symbols.RoundBracketClose) { - return new CssScaleValue(x.Value, y ?? x.Value, 1.0); + return new CssScaleValue(x.Value, y ?? x.Value, null); } } @@ -291,15 +291,15 @@ namespace AngleSharp.Css.Parser if (x.HasValue) { - var y = default(Double?); - var z = default(Double?); + var y = default(ICssValue); + var z = default(ICssValue); if (f == Symbols.Comma) { y = source.ParseNumber(); f = source.SkipGetSkip(); - if (!y.HasValue) + if (y is null) { return null; } @@ -331,7 +331,7 @@ namespace AngleSharp.Css.Parser if (x.HasValue && f == Symbols.RoundBracketClose) { - return new CssScaleValue(x.Value, 1.0, 1.0); + return new CssScaleValue(x.Value, null, null); } return null; @@ -348,7 +348,7 @@ namespace AngleSharp.Css.Parser if (y.HasValue && f == Symbols.RoundBracketClose) { - return new CssScaleValue(1.0, y.Value, 1.0); + return new CssScaleValue(null, y.Value, null); } return null; @@ -365,7 +365,7 @@ namespace AngleSharp.Css.Parser if (z.HasValue && f == Symbols.RoundBracketClose) { - return new CssScaleValue(1.0, 1.0, z.Value); + return new CssScaleValue(null, null, z.Value); } return null; diff --git a/src/AngleSharp.Css/Parser/Micro/UnitParser.cs b/src/AngleSharp.Css/Parser/Micro/UnitParser.cs index 0549b6e..cd4955f 100644 --- a/src/AngleSharp.Css/Parser/Micro/UnitParser.cs +++ b/src/AngleSharp.Css/Parser/Micro/UnitParser.cs @@ -119,19 +119,19 @@ namespace AngleSharp.Css.Parser /// /// Parses an angle value. /// - public static Angle? ParseAngle(this StringSource source) + public static CssAngleValue? ParseAngle(this StringSource source) { var pos = source.Index; var test = source.ParseUnit(); if (test != null) { - var unit = Angle.GetUnit(test.Dimension); + var unit = CssAngleValue.GetUnit(test.Dimension); - if (unit != Angle.Unit.None && + if (unit != CssAngleValue.Unit.None && Double.TryParse(test.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var value)) { - return new Angle(value, unit); + return new CssAngleValue(value, unit); } source.BackTo(pos); diff --git a/src/AngleSharp.Css/ValueConverters.cs b/src/AngleSharp.Css/ValueConverters.cs index c724b5d..6ea32a4 100644 --- a/src/AngleSharp.Css/ValueConverters.cs +++ b/src/AngleSharp.Css/ValueConverters.cs @@ -167,7 +167,7 @@ namespace AngleSharp.Css /// Represents a number object. /// https://developer.mozilla.org/en-US/docs/Web/CSS/number /// - public static readonly IValueConverter OnlyNumberConverter = new StructValueConverter(FromNumber(NumberParser.ParseNumber)); + public static readonly IValueConverter OnlyNumberConverter = new StructValueConverter(NumberParser.ParseNumber); /// /// Represents a (calculated) number object. @@ -202,7 +202,7 @@ namespace AngleSharp.Css /// /// Represents an number object that is zero or greater. /// - public static readonly IValueConverter NaturalNumberConverter = new StructValueConverter(FromNumber(NumberParser.ParseNaturalNumber)); + public static readonly IValueConverter NaturalNumberConverter = new StructValueConverter(NumberParser.ParseNaturalNumber); /// /// Represents an color object (usually hex or name). @@ -753,7 +753,7 @@ namespace AngleSharp.Css /// /// Represents a converter for the StrokeMiterlimit enumeration. /// - public static readonly IValueConverter StrokeMiterlimitConverter = new StructValueConverter(FromNumber(NumberParser.ParseGreaterOrEqualOneNumber)); + public static readonly IValueConverter StrokeMiterlimitConverter = new StructValueConverter(NumberParser.ParseGreaterOrEqualOneNumber); /// /// Represents a ratio object. diff --git a/src/AngleSharp.Css/Values/Composites/CssBackgroundLayerValue.cs b/src/AngleSharp.Css/Values/Composites/CssBackgroundLayerValue.cs index e5dc9a8..699deb6 100644 --- a/src/AngleSharp.Css/Values/Composites/CssBackgroundLayerValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssBackgroundLayerValue.cs @@ -4,7 +4,7 @@ namespace AngleSharp.Css.Values using AngleSharp.Text; using System; - sealed class CssBackgroundLayerValue : ICssCompositeValue + sealed class CssBackgroundLayerValue : ICssCompositeValue, IEquatable { #region Fields @@ -132,6 +132,22 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssBackgroundLayerValue other) + { + return _clip.Equals(other._clip) && + _repeat.Equals(other._repeat) && + _attachment.Equals(other._attachment) && + _origin.Equals(other._origin) && + _size.Equals(other._size); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssBackgroundLayerValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var image = _image.Compute(context); diff --git a/src/AngleSharp.Css/Values/Composites/CssBackgroundSizeValue.cs b/src/AngleSharp.Css/Values/Composites/CssBackgroundSizeValue.cs index 96f519f..2a214c0 100644 --- a/src/AngleSharp.Css/Values/Composites/CssBackgroundSizeValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssBackgroundSizeValue.cs @@ -89,6 +89,15 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Compares to another background size. + /// + /// The other background size. + /// True if both are equivalent, otherwise false. + public Boolean Equals(CssBackgroundSizeValue other) => _mode == other._mode && _height.Equals(other._height) && _width.Equals(other._width); + + Boolean IEquatable.Equals(ICssValue other) => other is CssBackgroundSizeValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { if (_mode == ValueMode.Explicit) @@ -101,13 +110,6 @@ namespace AngleSharp.Css.Values return this; } - /// - /// Compares to another background size. - /// - /// The other background size. - /// True if both are equivalent, otherwise false. - public Boolean Equals(CssBackgroundSizeValue other) => _mode == other._mode && _height == other._height && _width == other._width; - #endregion #region Value Mode diff --git a/src/AngleSharp.Css/Values/Composites/CssBackgroundValue.cs b/src/AngleSharp.Css/Values/Composites/CssBackgroundValue.cs index 70d029f..3410371 100644 --- a/src/AngleSharp.Css/Values/Composites/CssBackgroundValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssBackgroundValue.cs @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS background definition. /// - sealed class CssBackgroundValue : ICssCompositeValue + sealed class CssBackgroundValue : ICssCompositeValue, IEquatable { #region Fields @@ -71,6 +71,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssBackgroundValue other) + { + return _color.Equals(other._color) && _layers.Equals(other._layers); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssBackgroundValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var layers = _layers.Compute(context); diff --git a/src/AngleSharp.Css/Values/Composites/CssBorderImageSliceValue.cs b/src/AngleSharp.Css/Values/Composites/CssBorderImageSliceValue.cs index d619319..5cbed17 100644 --- a/src/AngleSharp.Css/Values/Composites/CssBorderImageSliceValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssBorderImageSliceValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents the CSS border image slice definition. /// - public sealed class CssBorderImageSliceValue : ICssCompositeValue + public sealed class CssBorderImageSliceValue : ICssCompositeValue, IEquatable { #region Fields @@ -117,6 +117,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssBorderImageSliceValue other) + { + return _filled == other._filled && _bottom.Equals(other._bottom) && _left.Equals(other._left) && _right.Equals(other._right) && _top.Equals(other._top); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssBorderImageSliceValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var bottom = (CssLengthValue)((ICssValue)_bottom).Compute(context); diff --git a/src/AngleSharp.Css/Values/Composites/CssBorderImageValue.cs b/src/AngleSharp.Css/Values/Composites/CssBorderImageValue.cs index 3d89220..b07f59f 100644 --- a/src/AngleSharp.Css/Values/Composites/CssBorderImageValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssBorderImageValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS border image definition. /// - sealed class CssBorderImageValue : ICssCompositeValue + sealed class CssBorderImageValue : ICssCompositeValue, IEquatable { #region Fields @@ -113,6 +113,22 @@ namespace AngleSharp.Css.Values #region + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssBorderImageValue other) + { + return _image.Equals(other._image) && + _slice.Equals(other._slice) && + _widths.Equals(other._widths) && + _outsets.Equals(other._outsets) && + _repeat.Equals(other._repeat); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssBorderImageValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var image = _image.Compute(context); diff --git a/src/AngleSharp.Css/Values/Composites/CssBorderRadiusValue.cs b/src/AngleSharp.Css/Values/Composites/CssBorderRadiusValue.cs index 733f1a3..54f2b18 100644 --- a/src/AngleSharp.Css/Values/Composites/CssBorderRadiusValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssBorderRadiusValue.cs @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values /// /// Represents a border radius value. /// - sealed class CssBorderRadiusValue : ICssCompositeValue + sealed class CssBorderRadiusValue : ICssCompositeValue, IEquatable { #region Fields @@ -67,6 +67,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssBorderRadiusValue other) + { + return _horizontal.Equals(other._horizontal) && _vertical.Equals(other._vertical); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssBorderRadiusValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var h = ((ICssValue)_horizontal).Compute(context); diff --git a/src/AngleSharp.Css/Values/Composites/CssCursorValue.cs b/src/AngleSharp.Css/Values/Composites/CssCursorValue.cs index 78a772c..7044b15 100644 --- a/src/AngleSharp.Css/Values/Composites/CssCursorValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssCursorValue.cs @@ -8,7 +8,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS cursor definition. /// - sealed class CssCursorValue : ICssCompositeValue + sealed class CssCursorValue : ICssCompositeValue, IEquatable { #region Fields @@ -67,6 +67,36 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssCursorValue other) + { + var l = _definitions.Length; + + if (_cursor.Equals(other._cursor) && l == other._definitions.Length) + { + for (var i = 0; i < l; i++) + { + var a = _definitions[i]; + var b = other._definitions[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssCursorValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var cursor = _cursor.Compute(context); diff --git a/src/AngleSharp.Css/Values/Composites/CssCustomCursorValue.cs b/src/AngleSharp.Css/Values/Composites/CssCustomCursorValue.cs index 0bee045..fd23ab0 100644 --- a/src/AngleSharp.Css/Values/Composites/CssCustomCursorValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssCustomCursorValue.cs @@ -4,12 +4,12 @@ namespace AngleSharp.Css.Values using AngleSharp.Text; using System; - sealed class CssCustomCursorValue : ICssCompositeValue + sealed class CssCustomCursorValue : ICssCompositeValue, IEquatable { #region Fields private readonly ICssImageValue _source; - private readonly CssPoint2D? _position; + private readonly ICssValue _position; #endregion @@ -20,7 +20,7 @@ namespace AngleSharp.Css.Values /// /// The image source to display. /// The position offset, if any. - public CssCustomCursorValue(ICssImageValue source, CssPoint2D? position) + public CssCustomCursorValue(ICssImageValue source, ICssValue position) { _source = source; _position = position; @@ -38,7 +38,7 @@ namespace AngleSharp.Css.Values /// /// Gets the positional offset, if any. /// - public CssPoint2D? Position => _position; + public ICssValue Position => _position; /// /// Gets the CSS text representation. @@ -51,10 +51,10 @@ namespace AngleSharp.Css.Values sb.Append(_source.CssText); - if (_position.HasValue) + if (_position is not null) { sb.Append(Symbols.Space); - sb.Append(_position.Value.CssText); + sb.Append(_position.CssText); } return sb.ToPool(); @@ -65,10 +65,22 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssCustomCursorValue other) + { + return _position.Equals(other._position) && _source.Equals(other._source); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssCustomCursorValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var source = (ICssImageValue)_source.Compute(context); - var position = _position.HasValue ? (CssPoint2D?)((ICssValue)_position.Value).Compute(context) : null; + var position = _position?.Compute(context); return new CssCustomCursorValue(source, position); } diff --git a/src/AngleSharp.Css/Values/Composites/CssFontValue.cs b/src/AngleSharp.Css/Values/Composites/CssFontValue.cs index 38f454d..607ecc1 100644 --- a/src/AngleSharp.Css/Values/Composites/CssFontValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssFontValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS font definition. /// - sealed class CssFontValue : ICssCompositeValue + sealed class CssFontValue : ICssCompositeValue, IEquatable { #region Fields @@ -138,6 +138,24 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssFontValue other) + { + return _lineHeight.Equals(other._lineHeight) && + _size.Equals(other._size) && + _weight.Equals(other._weight) && + _stretch.Equals(other._stretch) && + _variant.Equals(other._variant) && + _style.Equals(other._style) && + _fontFamilies.Equals(other._fontFamilies); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssFontValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var fontFamilies = _fontFamilies.Compute(context); diff --git a/src/AngleSharp.Css/Values/Composites/CssGradientStopValue.cs b/src/AngleSharp.Css/Values/Composites/CssGradientStopValue.cs index cfd5483..a3e57a2 100644 --- a/src/AngleSharp.Css/Values/Composites/CssGradientStopValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssGradientStopValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// More information can be found at the W3C: /// http://dev.w3.org/csswg/css-images-3/#color-stop-syntax /// - public sealed class CssGradientStopValue : ICssCompositeValue + public sealed class CssGradientStopValue : ICssCompositeValue, IEquatable { #region Fields @@ -62,6 +62,16 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssGradientStopValue other) + { + return _color.Equals(other._color) && _location.Equals(other._location); + } + ICssValue ICssValue.Compute(ICssComputeContext context) { var color = ((ICssValue)_color).Compute(context); @@ -69,6 +79,8 @@ namespace AngleSharp.Css.Values return new CssGradientStopValue((CssColorValue)color, location); } + Boolean IEquatable.Equals(ICssValue other) => other is CssGradientStopValue value && Equals(value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Composites/CssGridTemplateValue.cs b/src/AngleSharp.Css/Values/Composites/CssGridTemplateValue.cs index 1eb516c..154011e 100644 --- a/src/AngleSharp.Css/Values/Composites/CssGridTemplateValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssGridTemplateValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS grid template definition. /// - sealed class CssGridTemplateValue : ICssCompositeValue + sealed class CssGridTemplateValue : ICssCompositeValue, IEquatable { #region Fields @@ -107,6 +107,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssGridTemplateValue other) + { + return _areas.Equals(other._areas) && _columns.Equals(other._columns) && _rows.Equals(other._rows); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssGridTemplateValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var rows = _rows.Compute(context); diff --git a/src/AngleSharp.Css/Values/Composites/CssGridValue.cs b/src/AngleSharp.Css/Values/Composites/CssGridValue.cs index 8035795..369d919 100644 --- a/src/AngleSharp.Css/Values/Composites/CssGridValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssGridValue.cs @@ -9,7 +9,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS grid definition. /// - sealed class CssGridValue : ICssCompositeValue + sealed class CssGridValue : ICssCompositeValue, IEquatable { #region Fields @@ -92,6 +92,37 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssGridValue other) + { + if (_rows.Equals(other._rows) && _columns.Equals(other._columns) && _dense == other._dense) + { + var l = _sizes.Length; + + if (l == other._sizes.Length) + { + for (var i = 0; i < l; i++) + { + var a = _sizes[i]; + var b = other._sizes[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + } + + return false; + } + ICssValue ICssValue.Compute(ICssComputeContext context) { var rows = _rows.Compute(context); @@ -100,6 +131,8 @@ namespace AngleSharp.Css.Values return new CssGridValue(rows, columns, sizes, _dense); } + Boolean IEquatable.Equals(ICssValue other) => other is CssGridValue value && Equals(value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Composites/CssImageRepeatsValue.cs b/src/AngleSharp.Css/Values/Composites/CssImageRepeatsValue.cs index d8f9292..ca5cfbd 100644 --- a/src/AngleSharp.Css/Values/Composites/CssImageRepeatsValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssImageRepeatsValue.cs @@ -7,11 +7,17 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS image repeat definition. /// - public sealed class CssImageRepeatsValue : ICssCompositeValue + public sealed class CssImageRepeatsValue : ICssCompositeValue, IEquatable { + #region Fields + private readonly ICssValue _horizontal; private readonly ICssValue _vertical; + #endregion + + #region ctor + /// /// Creates a new CSS image repeat definition. /// @@ -23,6 +29,10 @@ namespace AngleSharp.Css.Values _vertical = vertical; } + #endregion + + #region Properties + /// /// Gets the value of the horizontal repeat component. /// @@ -60,11 +70,29 @@ namespace AngleSharp.Css.Values } } + #endregion + + #region Methods + + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssImageRepeatsValue other) + { + return _horizontal.Equals(other._horizontal) && _vertical.Equals(other._vertical); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssImageRepeatsValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var h = _horizontal.Compute(context); var v = _vertical.Compute(context); return new CssImageRepeatsValue(h, v); } + + #endregion } } diff --git a/src/AngleSharp.Css/Values/Composites/CssOriginValue.cs b/src/AngleSharp.Css/Values/Composites/CssOriginValue.cs index 33839f2..41d9811 100644 --- a/src/AngleSharp.Css/Values/Composites/CssOriginValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssOriginValue.cs @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS origin definition. /// - public sealed class CssOriginValue : ICssCompositeValue + public sealed class CssOriginValue : ICssCompositeValue, IEquatable { #region Fields @@ -66,6 +66,16 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssOriginValue other) + { + return _x.Equals(other._x) && _y.Equals(other._y) && _z.Equals(other._z); + } + ICssValue ICssValue.Compute(ICssComputeContext context) { var x = _x.Compute(context); @@ -80,6 +90,8 @@ namespace AngleSharp.Css.Values return this; } + Boolean IEquatable.Equals(ICssValue other) => other is CssOriginValue value && Equals(value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Multiples/CssPoint2D.cs b/src/AngleSharp.Css/Values/Composites/CssPoint2D.cs similarity index 69% rename from src/AngleSharp.Css/Values/Multiples/CssPoint2D.cs rename to src/AngleSharp.Css/Values/Composites/CssPoint2D.cs index b4a45c8..42eb945 100644 --- a/src/AngleSharp.Css/Values/Multiples/CssPoint2D.cs +++ b/src/AngleSharp.Css/Values/Composites/CssPoint2D.cs @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values /// /// Represents a point value consisting of two distances. /// - public readonly struct CssPoint2D : IEquatable, ICssPrimitiveValue + public readonly struct CssPoint2D : ICssCompositeValue, IEquatable { #region Basic values @@ -147,6 +147,16 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssPoint2D other) + { + return _x.Equals(other._x) && _y.Equals(other._y); + } + ICssValue ICssValue.Compute(ICssComputeContext context) { var x = _x.Compute(context); @@ -160,59 +170,7 @@ namespace AngleSharp.Css.Values return this; } - #endregion - - #region Equality - - /// - /// Checks the equality of the two given points. - /// - /// The left point. - /// The right point. - /// True if both points are equal, otherwise false. - public static Boolean operator ==(CssPoint2D a, CssPoint2D b) => a.Equals(b); - - /// - /// Checks the inequality of the two given points. - /// - /// The left point. - /// The right point. - /// True if both points are not equal, otherwise false. - public static Boolean operator !=(CssPoint2D a, CssPoint2D b) => !a.Equals(b); - - /// - /// Checks if both points are actually equal. - /// - /// The other point to compare to. - /// True if both points are equal, otherwise false. - public Boolean Equals(CssPoint2D other) => _x.Equals(other._x) && _y.Equals(other._y); - - /// - /// Tests if another object is equal to this object. - /// - /// The object to test with. - /// True if the two objects are equal, otherwise false. - public override Boolean Equals(Object obj) - { - var other = obj as CssPoint2D?; - - if (other != null) - { - return Equals(other.Value); - } - - return false; - } - - /// - /// Returns a hash code that defines the current point. - /// - /// The integer value of the hashcode. - public override Int32 GetHashCode() - { - var hash = 17 * 37 + _x.GetHashCode(); - return hash * 37 + _y.GetHashCode(); - } + Boolean IEquatable.Equals(ICssValue other) => other is CssPoint2D value && Equals(value); #endregion } diff --git a/src/AngleSharp.Css/Values/Composites/CssRatioValue.cs b/src/AngleSharp.Css/Values/Composites/CssRatioValue.cs new file mode 100644 index 0000000..a68e353 --- /dev/null +++ b/src/AngleSharp.Css/Values/Composites/CssRatioValue.cs @@ -0,0 +1,81 @@ +namespace AngleSharp.Css.Values +{ + using AngleSharp.Css.Dom; + using System; + + /// + /// Represents a ratio (top to bottom) value. + /// + public readonly struct CssRatioValue : ICssCompositeValue, IEquatable + { + #region Fields + + private readonly ICssValue _top; + private readonly ICssValue _bottom; + + #endregion + + #region ctor + + /// + /// Creates a new ratio value. + /// + /// The first number. + /// The second number. + public CssRatioValue(ICssValue top, ICssValue bottom) + { + _top = top; + _bottom = bottom; + } + + #endregion + + #region Properties + + /// + /// Gets the CSS text representation. + /// + public String CssText => String.Concat(_top.CssText, "/", _bottom.CssText); + + /// + /// Gets the first number of the ratio. + /// + public ICssValue Top => _top; + + /// + /// Gets the second number of the ratio. + /// + public ICssValue Bottom => _bottom; + + #endregion + + #region Methods + + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssRatioValue other) + { + return _top.Equals(other._top) && _bottom.Equals(other._bottom); + } + + ICssValue ICssValue.Compute(ICssComputeContext context) + { + var top = _top.Compute(context); + var bottom = _bottom.Compute(context); + + if (top != _top || bottom != _bottom) + { + return new CssRatioValue(top, bottom); + } + + return this; + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssRatioValue value && Equals(value); + + #endregion + } +} diff --git a/src/AngleSharp.Css/Values/Composites/CssShadowValue.cs b/src/AngleSharp.Css/Values/Composites/CssShadowValue.cs index 65f20bd..6d5d9f6 100644 --- a/src/AngleSharp.Css/Values/Composites/CssShadowValue.cs +++ b/src/AngleSharp.Css/Values/Composites/CssShadowValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// The shadow class for holding information about a box or text-shadow. /// - public sealed class CssShadowValue : ICssCompositeValue + public sealed class CssShadowValue : ICssCompositeValue, IEquatable { #region Fields @@ -115,6 +115,23 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssShadowValue other) + { + return _blurRadius.Equals(other._blurRadius) && + _spreadRadius.Equals(other._spreadRadius) && + _color.Equals(other._color) && + _inset == other._inset && + _offsetX.Equals(other._offsetX) && + _offsetY.Equals(other._offsetY); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssShadowValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var offsetX = _offsetX.Compute(context); diff --git a/src/AngleSharp.Css/Values/CssChildValue.cs b/src/AngleSharp.Css/Values/CssChildValue.cs index 6816cc4..aad3bc6 100644 --- a/src/AngleSharp.Css/Values/CssChildValue.cs +++ b/src/AngleSharp.Css/Values/CssChildValue.cs @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS value that was born from a shorthand. /// - class CssChildValue : ICssValue + sealed class CssChildValue : ICssValue, IEquatable { #region Fields @@ -51,6 +51,16 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssChildValue other) + { + return _parent.Equals(other._parent) && _value.Equals(other._value); + } + ICssValue ICssValue.Compute(ICssComputeContext context) { var parent = _parent.Compute(context); @@ -58,6 +68,8 @@ namespace AngleSharp.Css.Values return new CssChildValue(parent, value); } + Boolean IEquatable.Equals(ICssValue other) => other is CssChildValue value && Equals(value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcAddExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcAddExpression.cs index 3b022a3..c9d5374 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcAddExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcAddExpression.cs @@ -8,9 +8,15 @@ namespace AngleSharp.Css.Values /// sealed class CssCalcAddExpression : ICssCompositeValue { + #region Fields + private readonly ICssValue _left; private readonly ICssValue _right; + #endregion + + #region ctor + /// /// Creates a new calc add expression. /// @@ -22,6 +28,10 @@ namespace AngleSharp.Css.Values _right = right; } + #endregion + + #region Properties + /// /// Gets the left operand. /// @@ -37,6 +47,10 @@ namespace AngleSharp.Css.Values /// public String CssText => String.Concat(_left.CssText, " + ", _right.CssText); + #endregion + + #region Methods + ICssValue ICssValue.Compute(ICssComputeContext context) { var left = _left.Compute(context); @@ -48,8 +62,11 @@ namespace AngleSharp.Css.Values return (ICssValue)Activator.CreateInstance(x.GetType(), result); } - // TOOD INVALID - return this; + return null; } + + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); + + #endregion } } diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcBracketExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcBracketExpression.cs index c677c94..e0850a0 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcBracketExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcBracketExpression.cs @@ -8,8 +8,14 @@ namespace AngleSharp.Css.Values /// sealed class CssCalcBracketExpression : ICssCompositeValue { + #region Fields + private readonly ICssValue _content; + #endregion + + #region ctor + /// /// Creates a new calc bracket expression. /// @@ -19,6 +25,10 @@ namespace AngleSharp.Css.Values _content = content; } + #endregion + + #region Properties + /// /// Gets the bracket's content. /// @@ -29,9 +39,14 @@ namespace AngleSharp.Css.Values /// public String CssText => String.Concat("(", _content.CssText, ")"); - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return _content.Compute(context); - } + #endregion + + #region Methods + + ICssValue ICssValue.Compute(ICssComputeContext context) => _content.Compute(context); + + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); + + #endregion } } diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcDivExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcDivExpression.cs index 3bc44a2..45a7bb7 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcDivExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcDivExpression.cs @@ -8,9 +8,15 @@ namespace AngleSharp.Css.Values /// sealed class CssCalcDivExpression : ICssCompositeValue { + #region Fields + private readonly ICssValue _left; private readonly ICssValue _right; + #endregion + + #region ctor + /// /// Creates a new calc division expression. /// @@ -22,6 +28,10 @@ namespace AngleSharp.Css.Values _right = right; } + #endregion + + #region Properties + /// /// Gets the left operand. /// @@ -37,6 +47,10 @@ namespace AngleSharp.Css.Values /// public String CssText => String.Concat(_left.CssText, " / ", _right.CssText); + #endregion + + #region Methods + ICssValue ICssValue.Compute(ICssComputeContext context) { var left = _left.Compute(context); @@ -48,8 +62,11 @@ namespace AngleSharp.Css.Values return (ICssValue)Activator.CreateInstance(x.GetType(), result); } - // TOOD INVALID - return this; + return null; } + + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); + + #endregion } } diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcMulExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcMulExpression.cs index d82f7b3..9c767df 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcMulExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcMulExpression.cs @@ -8,9 +8,15 @@ namespace AngleSharp.Css.Values /// sealed class CssCalcMulExpression : ICssCompositeValue { + #region Fields + private readonly ICssValue _left; private readonly ICssValue _right; + #endregion + + #region ctor + /// /// Creates a new calc multiplication expression. /// @@ -22,6 +28,10 @@ namespace AngleSharp.Css.Values _right = right; } + #endregion + + #region Properties + /// /// Gets the left operand. /// @@ -37,6 +47,10 @@ namespace AngleSharp.Css.Values /// public String CssText => String.Concat(_left.CssText, " * ", _right.CssText); + #endregion + + #region Methods + ICssValue ICssValue.Compute(ICssComputeContext context) { var left = _left.Compute(context); @@ -48,8 +62,11 @@ namespace AngleSharp.Css.Values return (ICssValue)Activator.CreateInstance(x.GetType(), result); } - // TOOD INVALID - return this; + return null; } + + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); + + #endregion } } diff --git a/src/AngleSharp.Css/Values/Expressions/CssCalcSubExpression.cs b/src/AngleSharp.Css/Values/Expressions/CssCalcSubExpression.cs index a441d3e..b37db24 100644 --- a/src/AngleSharp.Css/Values/Expressions/CssCalcSubExpression.cs +++ b/src/AngleSharp.Css/Values/Expressions/CssCalcSubExpression.cs @@ -8,9 +8,15 @@ namespace AngleSharp.Css.Values /// sealed class CssCalcSubExpression : ICssCompositeValue { + #region Fields + private readonly ICssValue _left; private readonly ICssValue _right; + #endregion + + #region ctor + /// /// Creates a new calc subtraction expression. /// @@ -22,6 +28,10 @@ namespace AngleSharp.Css.Values _right = right; } + #endregion + + #region Properties + /// /// Gets the left operand. /// @@ -37,6 +47,10 @@ namespace AngleSharp.Css.Values /// public String CssText => String.Concat(_left.CssText, " - ", _right.CssText); + #endregion + + #region Methods + ICssValue ICssValue.Compute(ICssComputeContext context) { var left = _left.Compute(context); @@ -48,8 +62,11 @@ namespace AngleSharp.Css.Values return (ICssValue)Activator.CreateInstance(x.GetType(), result); } - // TOOD INVALID - return this; + return null; } + + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); + + #endregion } } diff --git a/src/AngleSharp.Css/Values/Functions/CssAttrValue.cs b/src/AngleSharp.Css/Values/Functions/CssAttrValue.cs index 54fb8d8..522d1cf 100644 --- a/src/AngleSharp.Css/Values/Functions/CssAttrValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssAttrValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS attr function call. /// - public sealed class CssAttrValue : ICssFunctionValue + public sealed class CssAttrValue : ICssFunctionValue, IEquatable { #region Fields @@ -54,6 +54,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssAttrValue other) + { + return _attribute.Equals(other._attribute); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssAttrValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { return this; diff --git a/src/AngleSharp.Css/Values/Functions/CssCalcValue.cs b/src/AngleSharp.Css/Values/Functions/CssCalcValue.cs index 09055cf..885ba1b 100644 --- a/src/AngleSharp.Css/Values/Functions/CssCalcValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssCalcValue.cs @@ -59,10 +59,9 @@ namespace AngleSharp.Css.Values #region Methods - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return _expression.Compute(context); - } + ICssValue ICssValue.Compute(ICssComputeContext context) => _expression.Compute(context); + + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); #endregion } diff --git a/src/AngleSharp.Css/Values/Functions/CssConicGradientValue.cs b/src/AngleSharp.Css/Values/Functions/CssConicGradientValue.cs index ac763b4..2497ec6 100644 --- a/src/AngleSharp.Css/Values/Functions/CssConicGradientValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssConicGradientValue.cs @@ -9,11 +9,11 @@ namespace AngleSharp.Css.Values /// Represents a linear gradient: /// https://drafts.csswg.org/css-images-4/#conic-gradients /// - sealed class CssConicGradientValue : ICssGradientFunctionValue + sealed class CssConicGradientValue : ICssGradientFunctionValue, IEquatable { #region Fields - private readonly CssGradientStopValue[] _stops; + private readonly ICssValue[] _stops; private readonly ICssValue _center; private readonly ICssValue _angle; private readonly Boolean _repeating; @@ -29,7 +29,7 @@ namespace AngleSharp.Css.Values /// The center to use. /// The stops to use. /// Indicates if the gradient is repeating. - public CssConicGradientValue(ICssValue angle, ICssValue center, CssGradientStopValue[] stops, Boolean repeating = false) + public CssConicGradientValue(ICssValue angle, ICssValue center, ICssValue[] stops, Boolean repeating = false) { _stops = stops; _center = center; @@ -76,7 +76,7 @@ namespace AngleSharp.Css.Values { get { - var defaultAngle = _angle as Angle?; + var defaultAngle = _angle as CssAngleValue?; var defaultPosition = _center as CssPoint2D?; var offset = (defaultAngle.HasValue ? 1 : 0) + (defaultPosition.HasValue ? 1 : 0); var args = new String[_stops.Length + offset]; @@ -103,7 +103,7 @@ namespace AngleSharp.Css.Values /// /// Gets the angle of the conic gradient. /// - public ICssValue Angle => _angle ?? Values.Angle.Half; + public ICssValue Angle => _angle ?? Values.CssAngleValue.Half; /// /// Gets the position of the conic gradient. @@ -113,7 +113,7 @@ namespace AngleSharp.Css.Values /// /// Gets all stops. /// - public CssGradientStopValue[] Stops => _stops; + public ICssValue[] Stops => _stops; /// /// Gets if the gradient is repeating. @@ -124,6 +124,36 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssConicGradientValue other) + { + var l = _stops.Length; + + if (_angle.Equals(other._angle) && _center.Equals(other._center) && _repeating == other._repeating && l == other._stops.Length) + { + for (var i = 0; i < l; i++) + { + var a = _stops[i]; + var b = other._stops[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssConicGradientValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var center = _center.Compute(context); diff --git a/src/AngleSharp.Css/Values/Functions/CssContentValue.cs b/src/AngleSharp.Css/Values/Functions/CssContentValue.cs index b4d76c7..463e11d 100644 --- a/src/AngleSharp.Css/Values/Functions/CssContentValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssContentValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS content function call. /// - public sealed class CssContentValue : ICssFunctionValue + public sealed class CssContentValue : ICssFunctionValue, IEquatable { #region Fields @@ -54,10 +54,16 @@ namespace AngleSharp.Css.Values #region Methods - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssContentValue other) => _type.Equals(other._type); + + Boolean IEquatable.Equals(ICssValue other) => other is CssContentValue value && Equals(value); + + ICssValue ICssValue.Compute(ICssComputeContext context) => this; #endregion } diff --git a/src/AngleSharp.Css/Values/Functions/CssCubicBezierValue.cs b/src/AngleSharp.Css/Values/Functions/CssCubicBezierValue.cs index f93cb91..8c698af 100644 --- a/src/AngleSharp.Css/Values/Functions/CssCubicBezierValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssCubicBezierValue.cs @@ -13,10 +13,10 @@ namespace AngleSharp.Css.Values { #region Fields - private readonly Double _x1; - private readonly Double _y1; - private readonly Double _x2; - private readonly Double _y2; + private readonly ICssValue _x1; + private readonly ICssValue _y1; + private readonly ICssValue _x2; + private readonly ICssValue _y2; /// /// The pre-configured ease function. @@ -56,7 +56,7 @@ namespace AngleSharp.Css.Values /// The y-coordinate of P1. /// The x-coordinate of P2. /// The y-coordinate of P2. - public CssCubicBezierValue(Double x1, Double y1, Double x2, Double y2) + public CssCubicBezierValue(ICssValue x1, ICssValue y1, ICssValue x2, ICssValue y2) { _x1 = x1; _y1 = y1; @@ -64,6 +64,20 @@ namespace AngleSharp.Css.Values _y2 = y2; } + /// + /// The four values specify points P1 and P2 of the curve as (x1, y1, x2, y2). Both + /// x values must be in the range [0, 1] or the definition is invalid. The y values + /// can exceed this range. + /// + /// The x-coordinate of P1. + /// The y-coordinate of P1. + /// The x-coordinate of P2. + /// The y-coordinate of P2. + public CssCubicBezierValue(Double x1, Double y1, Double x2, Double y2) + : this(new CssNumberValue(x1), new CssNumberValue(y1), new CssNumberValue(x2), new CssNumberValue(y2)) + { + } + #endregion #region Properties @@ -78,10 +92,10 @@ namespace AngleSharp.Css.Values /// public ICssValue[] Arguments => new ICssValue[] { - new CssLengthValue(_x1, CssLengthValue.Unit.None), - new CssLengthValue(_y1, CssLengthValue.Unit.None), - new CssLengthValue(_x2, CssLengthValue.Unit.None), - new CssLengthValue(_y2, CssLengthValue.Unit.None), + _x1, + _y1, + _x2, + _y2, }; /// @@ -119,22 +133,22 @@ namespace AngleSharp.Css.Values /// /// Gets the x-coordinate of the p1. /// - public Double X1 => _x1; + public ICssValue X1 => _x1; /// /// Gets the y-coordinate of the p1. /// - public Double Y1 => _y1; + public ICssValue Y1 => _y1; /// /// Gets the x-coordinate of the p2. /// - public Double X2 => _x2; + public ICssValue X2 => _x2; /// /// Gets the y-coordinate of the p2. /// - public Double Y2 => _y2; + public ICssValue Y2 => _y2; #endregion @@ -146,13 +160,19 @@ namespace AngleSharp.Css.Values /// The cubic bezier to compare to. /// True if both have the same parameters, otherwise false. public Boolean Equals(CssCubicBezierValue other) => - _x1 == other._x1 && _x2 == other._x2 && _y1 == other._y1 && _y2 == other._y2; + _x1.Equals(other._x1) && _x2.Equals(other._x2) && _y1.Equals(other._y1) && _y2.Equals(other._y2); ICssValue ICssValue.Compute(ICssComputeContext context) { - return this; + var x1 = _x1.Compute(context); + var x2 = _x2.Compute(context); + var y1 = _y1.Compute(context); + var y2 = _y2.Compute(context); + return new CssCubicBezierValue(x1, y1, x2, y2); } + Boolean IEquatable.Equals(ICssValue other) => other is CssCubicBezierValue value && Equals(value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Functions/CssFitContentValue.cs b/src/AngleSharp.Css/Values/Functions/CssFitContentValue.cs index 7a4baf5..81b769e 100644 --- a/src/AngleSharp.Css/Values/Functions/CssFitContentValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssFitContentValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS fit-content function call. /// - sealed class CssFitContentValue : ICssFunctionValue + sealed class CssFitContentValue : ICssFunctionValue, IEquatable { #region Fields @@ -54,6 +54,15 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssFitContentValue other) => _dim.Equals(other._dim); + + Boolean IEquatable.Equals(ICssValue other) => other is CssFitContentValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var dim = _dim.Compute(context); diff --git a/src/AngleSharp.Css/Values/Functions/CssFontFormatValue.cs b/src/AngleSharp.Css/Values/Functions/CssFontFormatValue.cs index 4e192b3..d62946a 100644 --- a/src/AngleSharp.Css/Values/Functions/CssFontFormatValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssFontFormatValue.cs @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values using AngleSharp.Text; using System; - sealed class CssFontFormatValue : ICssFunctionValue + sealed class CssFontFormatValue : ICssFunctionValue, IEquatable { #region Fields @@ -34,10 +34,16 @@ namespace AngleSharp.Css.Values #region Methods - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssFontFormatValue other) => _fontFormat.Equals(other._fontFormat); + + Boolean IEquatable.Equals(ICssValue other) => other is CssFontFormatValue value && Equals(value); + + ICssValue ICssValue.Compute(ICssComputeContext context) => this; #endregion } diff --git a/src/AngleSharp.Css/Values/Functions/CssLinearGradientValue.cs b/src/AngleSharp.Css/Values/Functions/CssLinearGradientValue.cs index 309b1c6..6a1d470 100644 --- a/src/AngleSharp.Css/Values/Functions/CssLinearGradientValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssLinearGradientValue.cs @@ -9,11 +9,11 @@ namespace AngleSharp.Css.Values /// Represents a linear gradient: /// http://dev.w3.org/csswg/css-images-3/#linear-gradients /// - sealed class CssLinearGradientValue : ICssGradientFunctionValue + sealed class CssLinearGradientValue : ICssGradientFunctionValue, IEquatable { #region Fields - private readonly CssGradientStopValue[] _stops; + private readonly ICssValue[] _stops; private readonly ICssValue _angle; private readonly Boolean _repeating; @@ -27,7 +27,7 @@ namespace AngleSharp.Css.Values /// The angle of the linear gradient. /// The stops to use. /// Indicates if the gradient is repeating. - public CssLinearGradientValue(ICssValue angle, CssGradientStopValue[] stops, Boolean repeating = false) + public CssLinearGradientValue(ICssValue angle, ICssValue[] stops, Boolean repeating = false) { _stops = stops; _angle = angle; @@ -68,7 +68,7 @@ namespace AngleSharp.Css.Values { get { - var defaultAngle = _angle as Angle?; + var defaultAngle = _angle as CssAngleValue?; var offset = defaultAngle.HasValue ? 1 : 0; var args = new String[_stops.Length + offset]; @@ -100,12 +100,12 @@ namespace AngleSharp.Css.Values /// /// Gets the angle of the linear gradient. /// - public ICssValue Angle => _angle ?? Values.Angle.Half; + public ICssValue Angle => _angle ?? Values.CssAngleValue.Half; /// /// Gets all stops. /// - public CssGradientStopValue[] Stops => _stops; + public ICssValue[] Stops => _stops; /// /// Gets if the gradient is repeating. @@ -116,6 +116,36 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssLinearGradientValue other) + { + var l = _stops.Length; + + if (_angle.Equals(other._angle) && _repeating == other._repeating && l == other._stops.Length) + { + for (var i = 0; i < l; i++) + { + var a = _stops[i]; + var b = other._stops[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssLinearGradientValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var angle = _angle.Compute(context); diff --git a/src/AngleSharp.Css/Values/Functions/CssLocalFontValue.cs b/src/AngleSharp.Css/Values/Functions/CssLocalFontValue.cs index aee0fa2..38cc33b 100644 --- a/src/AngleSharp.Css/Values/Functions/CssLocalFontValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssLocalFontValue.cs @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values using AngleSharp.Text; using System; - sealed class CssLocalFontValue : ICssFunctionValue + sealed class CssLocalFontValue : ICssFunctionValue, IEquatable { #region Fields @@ -34,10 +34,16 @@ namespace AngleSharp.Css.Values #region Methods - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssLocalFontValue other) => _fontName.Equals(other._fontName); + + Boolean IEquatable.Equals(ICssValue other) => other is CssLocalFontValue value && Equals(value); + + ICssValue ICssValue.Compute(ICssComputeContext context) => this; #endregion } diff --git a/src/AngleSharp.Css/Values/Functions/CssMatrixValue.cs b/src/AngleSharp.Css/Values/Functions/CssMatrixValue.cs index 47b5690..6975cfe 100644 --- a/src/AngleSharp.Css/Values/Functions/CssMatrixValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssMatrixValue.cs @@ -4,21 +4,22 @@ namespace AngleSharp.Css.Values using AngleSharp.Css.Dom; using AngleSharp.Text; using System; + using System.Linq; /// /// Represents the matrix3d transformation. /// - sealed class CssMatrixValue : ICssTransformFunctionValue + sealed class CssMatrixValue : ICssTransformFunctionValue, IEquatable { #region Fields - private readonly Double[] _values; + private readonly ICssValue[] _values; #endregion #region ctor - internal CssMatrixValue(Double[] values) + internal CssMatrixValue(ICssValue[] values) { _values = values; } @@ -35,20 +36,7 @@ namespace AngleSharp.Css.Values /// /// Gets the arguments. /// - public ICssValue[] Arguments - { - get - { - var args = new ICssValue[_values.Length]; - - for (var i = 0; i < args.Length; i++) - { - args[i] = new CssLengthValue(_values[i], CssLengthValue.Unit.None); - } - - return args; - } - } + public ICssValue[] Arguments => _values; /// /// Gets the CSS text representation. @@ -60,37 +48,69 @@ namespace AngleSharp.Css.Values /// /// The index to look for. /// The value. - public Double this[Int32 index] => _values[index]; + public ICssValue this[Int32 index] => _values[index]; #endregion #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssMatrixValue other) + { + var count = _values.Length; + + if (count == other._values.Length) + { + for (var i = 0; i < count; i++) + { + var a = _values[i]; + var b = other._values[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssMatrixValue value && Equals(value); + /// /// Returns the stored matrix. /// /// The current transformation. public TransformMatrix ComputeMatrix(IRenderDimensions dimensions) { - var values = _values; + var values = _values.Select(v => v.AsDouble()).ToList(); - if (values.Length == 6) + if (values.Count == 6) { - values = new Double[] - { - _values[0], _values[2], 0.0, _values[4], - _values[1], _values[3], 0.0, _values[5], - 1.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 1.0 - }; + values.Add(1.0); + values.Add(0.0); + values.Add(0.0); + values.Add(0.0); + values.Add(0.0); + values.Add(0.0); + values.Add(0.0); + values.Add(1.0); } - return new TransformMatrix(values); + return new TransformMatrix(values.ToArray()); } ICssValue ICssValue.Compute(ICssComputeContext context) { - return this; + var values = _values.Select(v => v.Compute(context)).ToArray(); + return new CssMatrixValue(values); } #endregion diff --git a/src/AngleSharp.Css/Values/Functions/CssMinMaxValue.cs b/src/AngleSharp.Css/Values/Functions/CssMinMaxValue.cs index c2d518f..9d7f9cf 100644 --- a/src/AngleSharp.Css/Values/Functions/CssMinMaxValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssMinMaxValue.cs @@ -8,7 +8,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS minmax function call. /// - sealed class CssMinMaxValue : ICssFunctionValue + sealed class CssMinMaxValue : ICssFunctionValue, IEquatable { #region Fields @@ -63,6 +63,16 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssMinMaxValue other) + { + return _min.Equals(other._min) && _max.Equals(other._max); + } + ICssValue ICssValue.Compute(ICssComputeContext context) { var min = _min.Compute(context); @@ -70,6 +80,8 @@ namespace AngleSharp.Css.Values return new CssMinMaxValue(min, max); } + Boolean IEquatable.Equals(ICssValue other) => other is CssMinMaxValue value && Equals(value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Functions/CssNoneValue.cs b/src/AngleSharp.Css/Values/Functions/CssNoneValue.cs index caca821..49600c9 100644 --- a/src/AngleSharp.Css/Values/Functions/CssNoneValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssNoneValue.cs @@ -17,10 +17,9 @@ namespace AngleSharp.Css.Values #region Methods - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); + + ICssValue ICssValue.Compute(ICssComputeContext context) => this; #endregion } diff --git a/src/AngleSharp.Css/Values/Functions/CssPerspectiveValue.cs b/src/AngleSharp.Css/Values/Functions/CssPerspectiveValue.cs index 8e7ec99..4b6ecf1 100644 --- a/src/AngleSharp.Css/Values/Functions/CssPerspectiveValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssPerspectiveValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents the distance transformation. /// - sealed class CssPerspectiveValue : ICssTransformFunctionValue + sealed class CssPerspectiveValue : ICssTransformFunctionValue, IEquatable { #region Fields @@ -50,6 +50,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssPerspectiveValue other) + { + return _distance.Equals(other._distance); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssPerspectiveValue value && Equals(value); + /// /// Computes the matrix for the given transformation. /// diff --git a/src/AngleSharp.Css/Values/Functions/CssRadialGradientValue.cs b/src/AngleSharp.Css/Values/Functions/CssRadialGradientValue.cs index fc425e2..133ced5 100644 --- a/src/AngleSharp.Css/Values/Functions/CssRadialGradientValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssRadialGradientValue.cs @@ -11,11 +11,11 @@ namespace AngleSharp.Css.Values /// Represents a radial gradient: /// http://dev.w3.org/csswg/css-images-3/#radial-gradients /// - public sealed class CssRadialGradientValue : ICssGradientFunctionValue + public sealed class CssRadialGradientValue : ICssGradientFunctionValue, IEquatable { #region Fields - private readonly CssGradientStopValue[] _stops; + private readonly ICssValue[] _stops; private readonly CssPoint2D _center; private readonly ICssValue _width; private readonly ICssValue _height; @@ -37,7 +37,7 @@ namespace AngleSharp.Css.Values /// The size mode of the ellipsoid. /// A collection of stops to use. /// The repeating setting. - public CssRadialGradientValue(Boolean circle, CssPoint2D center, ICssValue width, ICssValue height, SizeMode sizeMode, CssGradientStopValue[] stops, Boolean repeating = false) + public CssRadialGradientValue(Boolean circle, CssPoint2D center, ICssValue width, ICssValue height, SizeMode sizeMode, ICssValue[] stops, Boolean repeating = false) { _stops = stops; _center = center; @@ -64,7 +64,8 @@ namespace AngleSharp.Css.Values { get { - var isDefault = _center == CssPoint2D.Center && !_circle && _height == null && _width == null && _sizeMode == SizeMode.None; + var center = CssPoint2D.Center; + var isDefault = _center.X == center.X && _center.Y == center.Y && !_circle && _height == null && _width == null && _sizeMode == SizeMode.None; var args = new List(); if (!isDefault) @@ -145,7 +146,7 @@ namespace AngleSharp.Css.Values /// /// Gets all stops. /// - public CssGradientStopValue[] Stops => _stops; + public ICssValue[] Stops => _stops; /// /// Gets if the gradient is repeating. @@ -156,6 +157,37 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssRadialGradientValue other) + { + if (_center.Equals(other._center) && _width.Equals(other._width) && _height.Equals(other._height) && _repeating == other._repeating && _sizeMode == other._sizeMode && _circle == other._circle) + { + var count = _stops.Length; + + if (count == other._stops.Length) + { + for (var i = 0; i < count; i++) + { + var a = _stops[i]; + var b = other._stops[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + } + + return false; + } + ICssValue ICssValue.Compute(ICssComputeContext context) { var center = (CssPoint2D)((ICssValue)_center).Compute(context); @@ -165,6 +197,8 @@ namespace AngleSharp.Css.Values return new CssRadialGradientValue(_circle, center, width, height, _sizeMode, stops, _repeating); } + Boolean IEquatable.Equals(ICssValue other) => other is CssRadialGradientValue value && Equals(value); + #endregion #region Sizes diff --git a/src/AngleSharp.Css/Values/Functions/CssRepeatValue.cs b/src/AngleSharp.Css/Values/Functions/CssRepeatValue.cs index bb85715..07848f1 100644 --- a/src/AngleSharp.Css/Values/Functions/CssRepeatValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssRepeatValue.cs @@ -8,7 +8,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS repeat function call. /// - sealed class CssRepeatValue : ICssFunctionValue + sealed class CssRepeatValue : ICssFunctionValue, IEquatable { #region Fields @@ -63,6 +63,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssRepeatValue other) + { + return _count.Equals(other._count) && _value.Equals(other._value); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssRepeatValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var count = _count.Compute(context); diff --git a/src/AngleSharp.Css/Values/Functions/CssRotateValue.cs b/src/AngleSharp.Css/Values/Functions/CssRotateValue.cs index 7099509..91f77a7 100644 --- a/src/AngleSharp.Css/Values/Functions/CssRotateValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssRotateValue.cs @@ -8,13 +8,13 @@ namespace AngleSharp.Css.Values /// /// Represents the rotate3d transformation. /// - sealed class CssRotateValue : ICssTransformFunctionValue + sealed class CssRotateValue : ICssTransformFunctionValue, IEquatable { #region Fields - private readonly Double _x; - private readonly Double _y; - private readonly Double _z; + private readonly ICssValue _x; + private readonly ICssValue _y; + private readonly ICssValue _z; private readonly ICssValue _angle; #endregion @@ -28,7 +28,7 @@ namespace AngleSharp.Css.Values /// The y coordinate. /// The z coordinate. /// The angle of rotation. - public CssRotateValue(Double x, Double y, Double z, ICssValue angle) + public CssRotateValue(ICssValue x, ICssValue y, ICssValue z, ICssValue angle) { _x = x; _y = y; @@ -47,19 +47,19 @@ namespace AngleSharp.Css.Values { get { - if (Double.IsNaN(_x) && Double.IsNaN(_y) && Double.IsNaN(_z)) + if (_x is null && _y is null && _z is null) { return FunctionNames.Rotate; } - else if (_x == 1f && _y == 0f && _z == 0f) + else if (_x is not null && _y is null && _z is null) { return FunctionNames.RotateX; } - else if (_x == 0f && _y == 1f && _z == 0f) + else if (_x is null && _y is not null && _z is null) { return FunctionNames.RotateY; } - else if (_x == 0f && _y == 0f && _z == 1f) + else if (_x is null && _y is null && _z is not null) { return FunctionNames.RotateY; } @@ -73,9 +73,9 @@ namespace AngleSharp.Css.Values /// public ICssValue[] Arguments => new ICssValue[] { - new CssLengthValue(_x, CssLengthValue.Unit.None), - new CssLengthValue(_y, CssLengthValue.Unit.None), - new CssLengthValue(_z, CssLengthValue.Unit.None), + _x, + _y, + _z, _angle, }; @@ -101,17 +101,17 @@ namespace AngleSharp.Css.Values /// /// Gets the value of the x-component of the rotation vector. /// - public Double X => _x; + public ICssValue X => _x; /// /// Gets the value of the y-component of the rotation vector. /// - public Double Y => _y; + public ICssValue Y => _y; /// /// Gets the value of the z-component of the rotation vector. /// - public Double Z => _z; + public ICssValue Z => _z; /// /// Gets the angle. @@ -122,19 +122,34 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssRotateValue other) + { + return _angle.Equals(other._angle) && _x.Equals(other._x) && _y.Equals(other._y) && _z.Equals(other._z); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssRotateValue value && Equals(value); + /// /// Computes the matrix for the given transformation. /// /// The transformation matrix representation. public TransformMatrix ComputeMatrix(IRenderDimensions renderDimensions) { - var norm = 1.0 / Math.Sqrt(_x * _x + _y * _y + _z * _z); - var alpha = _angle as Angle ? ?? Values.Angle.Zero; - var sina = Math.Sin(alpha.ToRadian()); - var cosa = Math.Cos(alpha.ToRadian()); - var l = _x * norm; - var m = _y * norm; - var n = _z * norm; + var x = _x.AsDouble(); + var y = _x.AsDouble(); + var z = _x.AsDouble(); + var norm = 1.0 / Math.Sqrt(x * x + y * y + z * z); + var alpha = _angle.AsRad(); + var sina = Math.Sin(alpha); + var cosa = Math.Cos(alpha); + var l = x * norm; + var m = y * norm; + var n = z * norm; var omc = (1.0 - cosa); return new TransformMatrix( l * l * omc + cosa, m * l * omc - n * sina, n * l * omc + m * sina, @@ -145,8 +160,11 @@ namespace AngleSharp.Css.Values ICssValue ICssValue.Compute(ICssComputeContext context) { + var x = _x?.Compute(context); + var y = _y?.Compute(context); + var z = _z?.Compute(context); var angle = _angle.Compute(context); - return new CssRotateValue(_x, _y, _z, angle); + return new CssRotateValue(x, y, z, angle); } #endregion diff --git a/src/AngleSharp.Css/Values/Functions/CssRunningValue.cs b/src/AngleSharp.Css/Values/Functions/CssRunningValue.cs index 3fdbc3d..a2aad04 100644 --- a/src/AngleSharp.Css/Values/Functions/CssRunningValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssRunningValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS running function call. /// - public sealed class CssRunningValue : ICssFunctionValue + public sealed class CssRunningValue : ICssFunctionValue, IEquatable { #region Fields @@ -54,10 +54,16 @@ namespace AngleSharp.Css.Values #region Methods - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssRunningValue other) => _ident.Equals(other._ident); + + Boolean IEquatable.Equals(ICssValue other) => other is CssRunningValue value && Equals(value); + + ICssValue ICssValue.Compute(ICssComputeContext context) => this; #endregion } diff --git a/src/AngleSharp.Css/Values/Functions/CssScaleValue.cs b/src/AngleSharp.Css/Values/Functions/CssScaleValue.cs index a30cbcc..e7b65a0 100644 --- a/src/AngleSharp.Css/Values/Functions/CssScaleValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssScaleValue.cs @@ -3,18 +3,17 @@ namespace AngleSharp.Css.Values using AngleSharp.Css.Dom; using AngleSharp.Text; using System; - using System.Globalization; /// /// Represents the scale3d transformation. /// - sealed class CssScaleValue : ICssTransformFunctionValue + sealed class CssScaleValue : ICssTransformFunctionValue, IEquatable { #region Fields - private readonly Double _sx; - private readonly Double _sy; - private readonly Double _sz; + private readonly ICssValue _sx; + private readonly ICssValue _sy; + private readonly ICssValue _sz; #endregion @@ -26,7 +25,7 @@ namespace AngleSharp.Css.Values /// The x scaling factor. /// The y scaling factor. /// The z scaling factor. - public CssScaleValue(Double sx, Double sy, Double sz) + public CssScaleValue(ICssValue sx, ICssValue sy, ICssValue sz) { _sx = sx; _sy = sy; @@ -44,24 +43,26 @@ namespace AngleSharp.Css.Values { get { - if (_sz == 1f) + if (_sx is null && _sz is null) + { + return FunctionNames.ScaleY; + } + else if (_sy is null && _sz is null) + { + return FunctionNames.ScaleX; + } + else if (_sx is null && _sy is null) + { + return FunctionNames.ScaleX; + } + else if (_sz is null) { - if (_sx != _sy) - { - if (_sx == 1f) - { - return FunctionNames.ScaleY; - } - else if (_sy == 1f) - { - return FunctionNames.ScaleX; - } - } - return FunctionNames.Scale; } - - return FunctionNames.Scale3d; + else + { + return FunctionNames.Scale3d; + } } } @@ -70,9 +71,9 @@ namespace AngleSharp.Css.Values /// public ICssValue[] Arguments => new ICssValue[] { - new CssLengthValue(_sx, CssLengthValue.Unit.None), - new CssLengthValue(_sy, CssLengthValue.Unit.None), - new CssLengthValue(_sz, CssLengthValue.Unit.None), + _sx, + _sy, + _sz, }; /// @@ -82,68 +83,84 @@ namespace AngleSharp.Css.Values { get { - var args = String.Empty; - - if (_sz == 1.0) + if (_sx is null && _sz is null) { - if (_sx == _sy || _sy == 1.0) - { - args = _sx.ToString(CultureInfo.InvariantCulture); - } - else if (_sx == 1.0) - { - args = _sy.ToString(CultureInfo.InvariantCulture); - } - else - { - args = String.Concat( - _sx.ToString(CultureInfo.InvariantCulture), ", ", - _sy.ToString(CultureInfo.InvariantCulture)); - } + return FunctionNames.ScaleY.CssFunction(_sy.CssText); } - else if (_sx != _sy || _sx != _sz) + else if (_sy is null && _sz is null) { - args = String.Concat( - _sx.ToString(CultureInfo.InvariantCulture), ", ", - _sy.ToString(CultureInfo.InvariantCulture), ", ", - _sz.ToString(CultureInfo.InvariantCulture)); + return FunctionNames.ScaleX.CssFunction(_sx.CssText); + } + else if (_sx is null && _sy is null) + { + return FunctionNames.ScaleZ.CssFunction($"{_sz.CssText}"); + } + else if (_sz is null && _sx.Equals(_sy)) + { + return FunctionNames.Scale.CssFunction(_sx.CssText); + } + else if (_sz is null) + { + return FunctionNames.Scale.CssFunction($"{_sx.CssText}, {_sy.CssText}"); + } + else + { + return FunctionNames.Scale3d.CssFunction($"{_sx.CssText}, {_sy.CssText}, {_sz.CssText}"); } - - return Name.CssFunction(args); } } /// /// Gets the scaling in x-direction. /// - public Double ScaleX => _sx; + public ICssValue ScaleX => _sx; /// /// Gets the scaling in y-direction. /// - public Double ScaleY => _sy; + public ICssValue ScaleY => _sy; /// /// Gets the scaling in z-direction. /// - public Double ScaleZ => _sz; + public ICssValue ScaleZ => _sz; #endregion #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssScaleValue other) + { + return _sx.Equals(other._sx) && _sy.Equals(other._sy) && _sz.Equals(other._sz); + } + /// /// Computes the matrix for the given transformation. /// /// The transformation matrix representation. - public TransformMatrix ComputeMatrix(IRenderDimensions renderDimensions) => - new(_sx, 0f, 0f, 0f, _sy, 0f, 0f, 0f, _sz, 0f, 0f, 0f, 0f, 0f, 0f); + public TransformMatrix ComputeMatrix(IRenderDimensions renderDimensions) + { + var sx = _sx?.AsDouble() ?? 1.0; + var sy = _sy?.AsDouble() ?? 1.0; + var sz = _sz?.AsDouble() ?? 1.0; + return new TransformMatrix(sx, 0f, 0f, 0f, sy, 0f, 0f, 0f, sz, 0f, 0f, 0f, 0f, 0f, 0f); + } ICssValue ICssValue.Compute(ICssComputeContext context) { - return new CssScaleValue(_sx, _sy, _sz); + var sx = _sx?.Compute(context); + var sy = _sy?.Compute(context); + var sz = _sz?.Compute(context); + return new CssScaleValue(sx, sy, sz); } + Boolean IEquatable.Equals(ICssValue other) => other is CssScaleValue value && Equals(value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Functions/CssShapeValue.cs b/src/AngleSharp.Css/Values/Functions/CssShapeValue.cs index dcf5bf5..760fa41 100644 --- a/src/AngleSharp.Css/Values/Functions/CssShapeValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssShapeValue.cs @@ -9,7 +9,7 @@ namespace AngleSharp.Css.Values /// Represents a CSS shape. /// https://developer.mozilla.org/en-US/docs/Web/CSS/shape /// - public sealed class CssShapeValue : ICssValue, ICssFunctionValue + public sealed class CssShapeValue : ICssValue, ICssFunctionValue, IEquatable { #region Fields @@ -86,6 +86,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssShapeValue other) + { + return _top.Equals(other._top) && _right.Equals(other._right) && _bottom.Equals(other._bottom) && _left.Equals(other._left); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssShapeValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { var top = _top.Compute(context); diff --git a/src/AngleSharp.Css/Values/Functions/CssSkewValue.cs b/src/AngleSharp.Css/Values/Functions/CssSkewValue.cs index 30b483a..46a7b22 100644 --- a/src/AngleSharp.Css/Values/Functions/CssSkewValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssSkewValue.cs @@ -7,7 +7,7 @@ namespace AngleSharp.Css.Values /// /// Represents the skew transformation. /// - public sealed class CssSkewValue : ICssTransformFunctionValue + public sealed class CssSkewValue : ICssTransformFunctionValue, IEquatable { #region Fields @@ -100,14 +100,26 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssSkewValue other) + { + return _alpha.Equals(other._alpha) && _beta.Equals(other._beta); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssSkewValue value && Equals(value); + /// /// Computes the matrix for the given transformation. /// /// The transformation matrix representation. public TransformMatrix ComputeMatrix(IRenderDimensions renderDimensions) { - var a = Math.Tan((_alpha as Angle ? ?? Angle.Zero).ToRadian()); - var b = Math.Tan((_beta as Angle? ?? Angle.Zero).ToRadian()); + var a = Math.Tan((_alpha as CssAngleValue ? ?? CssAngleValue.Zero).ToRadian()); + var b = Math.Tan((_beta as CssAngleValue? ?? CssAngleValue.Zero).ToRadian()); return new TransformMatrix(1.0, a, 0.0, b, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); } diff --git a/src/AngleSharp.Css/Values/Functions/CssStepsValue.cs b/src/AngleSharp.Css/Values/Functions/CssStepsValue.cs index dc2ba99..c69c737 100644 --- a/src/AngleSharp.Css/Values/Functions/CssStepsValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssStepsValue.cs @@ -10,7 +10,7 @@ namespace AngleSharp.Css.Values /// Represents a steps timing-function object. /// https://developer.mozilla.org/en-US/docs/Web/CSS/timing-function /// - sealed class CssStepsValue : ICssTimingFunctionValue + sealed class CssStepsValue : ICssTimingFunctionValue, IEquatable { #region Fields @@ -101,6 +101,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssStepsValue other) + { + return _start == other._start && _intervals == other._intervals; + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssStepsValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { return this; diff --git a/src/AngleSharp.Css/Values/Functions/CssSymbolsValue.cs b/src/AngleSharp.Css/Values/Functions/CssSymbolsValue.cs index 04a93fa..7c13c7d 100644 --- a/src/AngleSharp.Css/Values/Functions/CssSymbolsValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssSymbolsValue.cs @@ -9,7 +9,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS symbols function call. /// - public sealed class CssSymbolsValue : ICssFunctionValue + public sealed class CssSymbolsValue : ICssFunctionValue, IEquatable { #region Fields @@ -59,6 +59,36 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssSymbolsValue other) + { + var l = _entries.Count; + + if (_type.Equals(other._type) && l == other._entries.Count) + { + for (var i = 0; i < l; i++) + { + var a = _entries[i]; + var b = other._entries[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssSymbolsValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { if (_type == null) diff --git a/src/AngleSharp.Css/Values/Functions/CssTranslateValue.cs b/src/AngleSharp.Css/Values/Functions/CssTranslateValue.cs index 06fcf5a..47c2df5 100644 --- a/src/AngleSharp.Css/Values/Functions/CssTranslateValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssTranslateValue.cs @@ -8,7 +8,7 @@ namespace AngleSharp.Css.Values /// /// Represents the translate3d transformation. /// - sealed class CssTranslateValue : ICssTransformFunctionValue + sealed class CssTranslateValue : ICssTransformFunctionValue, IEquatable { #region Fields @@ -99,18 +99,27 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssTranslateValue other) + { + return _x.Equals(other._x) && _y.Equals(other._y) && _z.Equals(other._z); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssTranslateValue value && Equals(value); + /// /// Computes the matrix for the given transformation. /// /// The transformation matrix representation. public TransformMatrix ComputeMatrix(IRenderDimensions renderDimensions) { - var x = _x as CssLengthValue? ?? CssLengthValue.Zero; - var y = _y as CssLengthValue? ?? CssLengthValue.Zero; - var z = _z as CssLengthValue? ?? CssLengthValue.Zero; - var dx = x.ToPixel(renderDimensions, RenderMode.Horizontal); - var dy = y.ToPixel(renderDimensions, RenderMode.Vertical); - var dz = z.ToPixel(renderDimensions, RenderMode.Undefined); + var dx = _x.AsPx(renderDimensions, RenderMode.Horizontal); + var dy = _y.AsPx(renderDimensions, RenderMode.Vertical); + var dz = _z.AsPx(renderDimensions, RenderMode.Undefined); return new TransformMatrix(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, dx, dy, dz, 0.0, 0.0, 0.0); } diff --git a/src/AngleSharp.Css/Values/Functions/CssUrlValue.cs b/src/AngleSharp.Css/Values/Functions/CssUrlValue.cs index 9d1c19e..14a1611 100644 --- a/src/AngleSharp.Css/Values/Functions/CssUrlValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssUrlValue.cs @@ -8,7 +8,7 @@ namespace AngleSharp.Css.Values /// Represents an URL object. /// https://developer.mozilla.org/en-US/docs/Web/CSS/uri /// - public sealed class CssUrlValue : ICssImageValue, ICssFunctionValue + public sealed class CssUrlValue : ICssImageValue, ICssFunctionValue, IEquatable { #region Fields @@ -55,6 +55,18 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssUrlValue other) + { + return _path.Equals(other._path); + } + + Boolean IEquatable.Equals(ICssValue other) => other is CssUrlValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { return this; diff --git a/src/AngleSharp.Css/Values/Functions/CssVarValue.cs b/src/AngleSharp.Css/Values/Functions/CssVarValue.cs index 0fb9192..58723c8 100644 --- a/src/AngleSharp.Css/Values/Functions/CssVarValue.cs +++ b/src/AngleSharp.Css/Values/Functions/CssVarValue.cs @@ -8,7 +8,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS var replacement. /// - public sealed class CssVarValue : ICssFunctionValue + public sealed class CssVarValue : ICssFunctionValue, IEquatable { #region Fields @@ -96,6 +96,16 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssVarValue other) + { + return _defaultValue.Equals(other._defaultValue) && _variableName.Equals(other._variableName); + } + /// /// Resolves the value of the referenced variable. Returns null /// if the reference is invalid or cannot be resolved. @@ -114,6 +124,8 @@ namespace AngleSharp.Css.Values return _defaultValue?.Compute(context); } + Boolean IEquatable.Equals(ICssValue other) => other is CssVarValue value && Equals(value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/ICssGradientFunctionValue.cs b/src/AngleSharp.Css/Values/ICssGradientFunctionValue.cs index 91cf038..9196376 100644 --- a/src/AngleSharp.Css/Values/ICssGradientFunctionValue.cs +++ b/src/AngleSharp.Css/Values/ICssGradientFunctionValue.cs @@ -1,5 +1,6 @@ namespace AngleSharp.Css.Values { + using AngleSharp.Css.Dom; using System; /// @@ -10,7 +11,7 @@ namespace AngleSharp.Css.Values /// /// Gets an enumeration of all stops. /// - CssGradientStopValue[] Stops { get; } + ICssValue[] Stops { get; } /// /// Gets if the gradient is repeating. diff --git a/src/AngleSharp.Css/Values/Multiples/CssFlowRelativeValue.cs b/src/AngleSharp.Css/Values/Multiples/CssFlowRelativeValue.cs index 57134f1..804b17b 100644 --- a/src/AngleSharp.Css/Values/Multiples/CssFlowRelativeValue.cs +++ b/src/AngleSharp.Css/Values/Multiples/CssFlowRelativeValue.cs @@ -10,7 +10,7 @@ namespace AngleSharp.Css.Values /// /// Represents a flow relative CSS value. /// - public class CssFlowRelativeValue : ICssMultipleValue + public class CssFlowRelativeValue : ICssMultipleValue, IEquatable> where T : ICssValue { #region Fields @@ -84,6 +84,34 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssFlowRelativeValue other) + { + var count = _values.Length; + + if (count == other._values.Length) + { + for (var i = 0; i < count; i++) + { + var a = _values[i]; + var b = other._values[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + IEnumerator IEnumerable.GetEnumerator() { yield return Start; @@ -98,6 +126,8 @@ namespace AngleSharp.Css.Values return new CssFlowRelativeValue(values); } + Boolean IEquatable.Equals(ICssValue other) => other is CssFlowRelativeValue value && Equals(value); + #endregion } diff --git a/src/AngleSharp.Css/Values/Multiples/CssListValue.cs b/src/AngleSharp.Css/Values/Multiples/CssListValue.cs index 15794c0..8fcaef3 100644 --- a/src/AngleSharp.Css/Values/Multiples/CssListValue.cs +++ b/src/AngleSharp.Css/Values/Multiples/CssListValue.cs @@ -10,7 +10,7 @@ namespace AngleSharp.Css.Values /// /// Represents a CSS value list. /// - public class CssListValue : ICssMultipleValue + public class CssListValue : ICssMultipleValue, IEquatable> where T : ICssValue { #region Fields @@ -50,6 +50,34 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssListValue other) + { + var count = _items.Length; + + if (count == other._items.Length) + { + for (var i = 0; i < count; i++) + { + var a = _items[i]; + var b = other._items[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + IEnumerator IEnumerable.GetEnumerator() => _items.OfType().GetEnumerator(); @@ -61,6 +89,8 @@ namespace AngleSharp.Css.Values return new CssListValue(items); } + Boolean IEquatable.Equals(ICssValue other) => other is CssListValue value && Equals(value); + #endregion } diff --git a/src/AngleSharp.Css/Values/Multiples/CssPeriodicValue.cs b/src/AngleSharp.Css/Values/Multiples/CssPeriodicValue.cs index 6a069c7..600aae5 100644 --- a/src/AngleSharp.Css/Values/Multiples/CssPeriodicValue.cs +++ b/src/AngleSharp.Css/Values/Multiples/CssPeriodicValue.cs @@ -10,7 +10,7 @@ namespace AngleSharp.Css.Values /// /// Represents a periodic CSS value. /// - public class CssPeriodicValue : ICssMultipleValue + public class CssPeriodicValue : ICssMultipleValue, IEquatable> where T : ICssValue { #region Fields @@ -104,6 +104,34 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssPeriodicValue other) + { + var count = _values.Length; + + if (count == other._values.Length) + { + for (var i = 0; i < count; i++) + { + var a = _values[i]; + var b = other._values[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + IEnumerator IEnumerable.GetEnumerator() { yield return Top; @@ -120,6 +148,8 @@ namespace AngleSharp.Css.Values return new CssPeriodicValue(values); } + Boolean IEquatable.Equals(ICssValue other) => other is CssPeriodicValue value && Equals(value); + #endregion } diff --git a/src/AngleSharp.Css/Values/Multiples/CssRadiusValue.cs b/src/AngleSharp.Css/Values/Multiples/CssRadiusValue.cs index 82a31c7..5530bfb 100644 --- a/src/AngleSharp.Css/Values/Multiples/CssRadiusValue.cs +++ b/src/AngleSharp.Css/Values/Multiples/CssRadiusValue.cs @@ -10,7 +10,7 @@ namespace AngleSharp.Css.Values /// /// Represents a periodic CSS value. /// - public class CssRadiusValue : ICssMultipleValue + public class CssRadiusValue : ICssMultipleValue, IEquatable> where T : ICssValue { #region Fields @@ -84,6 +84,34 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssRadiusValue other) + { + var count = _values.Length; + + if (count == other._values.Length) + { + for (var i = 0; i < count; i++) + { + var a = _values[i]; + var b = other._values[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + IEnumerator IEnumerable.GetEnumerator() { yield return Width; @@ -98,6 +126,8 @@ namespace AngleSharp.Css.Values return new CssRadiusValue(values); } + Boolean IEquatable.Equals(ICssValue other) => other is CssRadiusValue value && Equals(value); + #endregion } diff --git a/src/AngleSharp.Css/Values/Multiples/CssTupleValue.cs b/src/AngleSharp.Css/Values/Multiples/CssTupleValue.cs index 5512e22..c40b400 100644 --- a/src/AngleSharp.Css/Values/Multiples/CssTupleValue.cs +++ b/src/AngleSharp.Css/Values/Multiples/CssTupleValue.cs @@ -10,7 +10,7 @@ namespace AngleSharp.Css.Values /// /// Represents a tuple of CSS values. /// - public class CssTupleValue : ICssMultipleValue + public class CssTupleValue : ICssMultipleValue, IEquatable> where T : ICssValue { #region Fields @@ -58,6 +58,34 @@ namespace AngleSharp.Css.Values #region Methods + /// + /// Checks if the current value is equal to the provided one. + /// + /// The value to check against. + /// True if both are equal, otherwise false. + public Boolean Equals(CssTupleValue other) + { + var count = _items.Length; + + if (_separator.Equals(other._separator) && count == other._items.Length) + { + for (var i = 0; i < count; i++) + { + var a = _items[i]; + var b = other._items[i]; + + if (!a.Equals(b)) + { + return false; + } + } + + return true; + } + + return false; + } + IEnumerator IEnumerable.GetEnumerator() => _items.OfType().GetEnumerator(); @@ -69,6 +97,8 @@ namespace AngleSharp.Css.Values return new CssTupleValue(items, _separator); } + Boolean IEquatable.Equals(ICssValue other) => other is CssTupleValue value && Equals(value); + #endregion } diff --git a/src/AngleSharp.Css/Values/Primitives/Angle.cs b/src/AngleSharp.Css/Values/Primitives/CssAngleValue.cs similarity index 77% rename from src/AngleSharp.Css/Values/Primitives/Angle.cs rename to src/AngleSharp.Css/Values/Primitives/CssAngleValue.cs index 2eec643..8052ef5 100644 --- a/src/AngleSharp.Css/Values/Primitives/Angle.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssAngleValue.cs @@ -7,34 +7,34 @@ namespace AngleSharp.Css.Values /// Represents an angle object. /// https://developer.mozilla.org/en-US/docs/Web/CSS/angle /// - public readonly struct Angle : IEquatable, IComparable, ICssMetricValue + public readonly struct CssAngleValue : IEquatable, IComparable, ICssMetricValue { #region Basic angles /// /// The zero angle. /// - public static readonly Angle Zero = new(0.0, Angle.Unit.Rad); + public static readonly CssAngleValue Zero = new(0.0, CssAngleValue.Unit.Rad); /// /// The 45° angle. /// - public static readonly Angle HalfQuarter = new(45.0, Angle.Unit.Deg); + public static readonly CssAngleValue HalfQuarter = new(45.0, CssAngleValue.Unit.Deg); /// /// The 90° angle. /// - public static readonly Angle Quarter = new(90.0, Angle.Unit.Deg); + public static readonly CssAngleValue Quarter = new(90.0, CssAngleValue.Unit.Deg); /// /// The 135° angle. /// - public static readonly Angle TripleHalfQuarter = new(135.0, Angle.Unit.Deg); + public static readonly CssAngleValue TripleHalfQuarter = new(135.0, CssAngleValue.Unit.Deg); /// /// The 180° angle. /// - public static readonly Angle Half = new(180.0, Angle.Unit.Deg); + public static readonly CssAngleValue Half = new(180.0, CssAngleValue.Unit.Deg); #endregion @@ -51,7 +51,7 @@ namespace AngleSharp.Css.Values /// Creates a new angle value. /// /// The value of the angle in rad. - public Angle(Double value) + public CssAngleValue(Double value) : this(value, Unit.Rad) { } @@ -61,7 +61,7 @@ namespace AngleSharp.Css.Values /// /// The value of the angle. /// The unit of the angle. - public Angle(Double value, Unit unit) + public CssAngleValue(Double value, Unit unit) { _value = value; _unit = unit; @@ -111,7 +111,7 @@ namespace AngleSharp.Css.Values /// /// Compares the magnitude of two angles. /// - public static Boolean operator >=(Angle a, Angle b) + public static Boolean operator >=(CssAngleValue a, CssAngleValue b) { var result = a.CompareTo(b); return result == 0 || result == 1; @@ -120,12 +120,12 @@ namespace AngleSharp.Css.Values /// /// Compares the magnitude of two angles. /// - public static Boolean operator >(Angle a, Angle b) => a.CompareTo(b) == 1; + public static Boolean operator >(CssAngleValue a, CssAngleValue b) => a.CompareTo(b) == 1; /// /// Compares the magnitude of two angles. /// - public static Boolean operator <=(Angle a, Angle b) + public static Boolean operator <=(CssAngleValue a, CssAngleValue b) { var result = a.CompareTo(b); return result == 0 || result == -1; @@ -134,14 +134,14 @@ namespace AngleSharp.Css.Values /// /// Compares the magnitude of two angles. /// - public static Boolean operator <(Angle a, Angle b) => a.CompareTo(b) == -1; + public static Boolean operator <(CssAngleValue a, CssAngleValue b) => a.CompareTo(b) == -1; /// /// Compares the current angle against the given one. /// /// The angle to compare to. /// The result of the comparison. - public Int32 CompareTo(Angle other) => ToRadian().CompareTo(other.ToRadian()); + public Int32 CompareTo(CssAngleValue other) => ToRadian().CompareTo(other.ToRadian()); #endregion @@ -152,7 +152,7 @@ namespace AngleSharp.Css.Values if (_unit != Unit.Rad) { var rad = ToRadian(); - return new Angle(rad, Unit.Rad); + return new CssAngleValue(rad, Unit.Rad); } return this; @@ -164,13 +164,13 @@ namespace AngleSharp.Css.Values /// The string to convert. /// The reference to the result. /// True if successful, otherwise false. - public static Boolean TryParse(String s, out Angle result) + public static Boolean TryParse(String s, out CssAngleValue result) { var unit = GetUnit(s.CssUnit(out double value)); if (unit != Unit.None) { - result = new Angle(value, unit); + result = new CssAngleValue(value, unit); return true; } @@ -225,12 +225,27 @@ namespace AngleSharp.Css.Values }; } + /// + /// Converts the contained value to degree. + /// + /// The value in degree. + public Double ToDegree() + { + return _unit switch + { + Unit.Turn => _value * 360.0, + Unit.Grad => _value * (360.0 / 400.0), + Unit.Rad => _value / (180.0 / Math.PI), + _ => _value, + }; + } + /// /// Checks for equality with the other angle. /// /// The angle to compare with. /// True if both represent the same angle in rad. - public Boolean Equals(Angle other) => ToRadian() == other.ToRadian(); + public Boolean Equals(CssAngleValue other) => ToRadian() == other.ToRadian(); #endregion @@ -270,12 +285,12 @@ namespace AngleSharp.Css.Values /// /// Checks for equality of two angles. /// - public static Boolean operator ==(Angle a, Angle b) => a.Equals(b); + public static Boolean operator ==(CssAngleValue a, CssAngleValue b) => a.Equals(b); /// /// Checks for inequality of two angles. /// - public static Boolean operator !=(Angle a, Angle b) => !a.Equals(b); + public static Boolean operator !=(CssAngleValue a, CssAngleValue b) => !a.Equals(b); /// /// Tests if another object is equal to this object. @@ -284,7 +299,7 @@ namespace AngleSharp.Css.Values /// True if the two objects are equal, otherwise false. public override Boolean Equals(Object obj) { - var other = obj as Angle?; + var other = obj as CssAngleValue?; if (other != null) { @@ -294,6 +309,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssAngleValue value && Equals(value); + /// /// Returns a hash code that defines the current angle. /// diff --git a/src/AngleSharp.Css/Values/Primitives/Color.cs b/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs similarity index 99% rename from src/AngleSharp.Css/Values/Primitives/Color.cs rename to src/AngleSharp.Css/Values/Primitives/CssColorValue.cs index 3c540d1..fc045e4 100644 --- a/src/AngleSharp.Css/Values/Primitives/Color.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs @@ -585,6 +585,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssColorValue value && Equals(value); + Int32 IComparable.CompareTo(CssColorValue other) => _hashcode - other._hashcode; /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssConstantValue.cs b/src/AngleSharp.Css/Values/Primitives/CssConstantValue.cs index 4954a8a..a4a8b92 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssConstantValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssConstantValue.cs @@ -62,6 +62,8 @@ namespace AngleSharp.Css.Values public override Boolean Equals(Object obj) => obj is CssConstantValue constant && Equals(constant); + Boolean IEquatable.Equals(ICssValue other) => other is CssConstantValue value && Equals(value); + /// /// Gets the computed hash code of the constant. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssCounterDefinitionValue.cs b/src/AngleSharp.Css/Values/Primitives/CssCounterDefinitionValue.cs index ac99c29..2feef37 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssCounterDefinitionValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssCounterDefinitionValue.cs @@ -72,6 +72,8 @@ namespace AngleSharp.Css.Values ListStyle.Is(other.ListStyle) && DefinedSeparator.Is(other.DefinedSeparator); + Boolean IEquatable.Equals(ICssValue other) => other is CssCounterDefinitionValue value && Equals(value); + /// /// Checks for equality against the given object, if /// the provided object is no counter definition the diff --git a/src/AngleSharp.Css/Values/Primitives/CssCounterValue.cs b/src/AngleSharp.Css/Values/Primitives/CssCounterValue.cs index 86e31c4..79395c0 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssCounterValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssCounterValue.cs @@ -59,6 +59,8 @@ namespace AngleSharp.Css.Values /// True if both are equal, otherwise false. public Boolean Equals(CssCounterValue other) => Name.Is(other.Name) && Value == other.Value; + Boolean IEquatable.Equals(ICssValue other) => other is CssCounterValue value && Equals(value); + /// /// Checks for equality against the given object, /// if the provided object is no counter value the diff --git a/src/AngleSharp.Css/Values/Primitives/CssFractionValue.cs b/src/AngleSharp.Css/Values/Primitives/CssFractionValue.cs index f577ad5..7187060 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssFractionValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssFractionValue.cs @@ -175,6 +175,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssFractionValue value && Equals(value); + /// /// Returns a hash code that defines the current fraction. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssFrequencyValue.cs b/src/AngleSharp.Css/Values/Primitives/CssFrequencyValue.cs index 2d53341..1f9f437 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssFrequencyValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssFrequencyValue.cs @@ -228,6 +228,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssFrequencyValue value && Equals(value); + /// /// Returns a hash code that defines the current frequency. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssIdentifierValue.cs b/src/AngleSharp.Css/Values/Primitives/CssIdentifierValue.cs index fd43499..5bba78c 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssIdentifierValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssIdentifierValue.cs @@ -61,6 +61,8 @@ namespace AngleSharp.Css.Values public override Boolean Equals(Object obj) => obj is CssIdentifierValue ident && Equals(ident); + Boolean IEquatable.Equals(ICssValue other) => other is CssIdentifierValue value && Equals(value); + /// /// Gets the hash code of the object. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssIntegerValue.cs b/src/AngleSharp.Css/Values/Primitives/CssIntegerValue.cs index 6331b96..5360929 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssIntegerValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssIntegerValue.cs @@ -120,6 +120,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssIntegerValue value && Equals(value); + /// /// Returns a hash code that defines the current integer. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssLengthValue.cs b/src/AngleSharp.Css/Values/Primitives/CssLengthValue.cs index ceef748..cffee8d 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssLengthValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssLengthValue.cs @@ -547,6 +547,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssLengthValue value && Equals(value); + /// /// Returns a hash code that defines the current length. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssLineNamesValue.cs b/src/AngleSharp.Css/Values/Primitives/CssLineNamesValue.cs index 23b08f6..5044875 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssLineNamesValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssLineNamesValue.cs @@ -71,6 +71,8 @@ namespace AngleSharp.Css.Values /// The computed hash code. public override Int32 GetHashCode() => CssText.GetHashCode(); + Boolean IEquatable.Equals(ICssValue other) => other is CssLineNamesValue value && Equals(value); + ICssValue ICssValue.Compute(ICssComputeContext context) { return this; diff --git a/src/AngleSharp.Css/Values/Primitives/CssNumberValue.cs b/src/AngleSharp.Css/Values/Primitives/CssNumberValue.cs index f596791..d6cc573 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssNumberValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssNumberValue.cs @@ -8,6 +8,20 @@ namespace AngleSharp.Css.Values /// public readonly struct CssNumberValue : IEquatable, IComparable, ICssMetricValue { + #region Basic lengths + + /// + /// Gets the 0.0. + /// + public static readonly CssNumberValue Zero = new(0.0); + + /// + /// Gets the 1.0. + /// + public static readonly CssNumberValue One = new(0.0); + + #endregion + #region Fields private readonly Double _value; @@ -105,6 +119,7 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssNumberValue value && Equals(value); /// /// Returns a hash code that defines the current number. diff --git a/src/AngleSharp.Css/Values/Primitives/CssPercentageValue.cs b/src/AngleSharp.Css/Values/Primitives/CssPercentageValue.cs index 25e7477..0bf20db 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssPercentageValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssPercentageValue.cs @@ -8,6 +8,25 @@ namespace AngleSharp.Css.Values /// public readonly struct CssPercentageValue : IEquatable, IComparable, ICssMetricValue { + #region Basic percentages + + /// + /// Gets a zero percentage value. + /// + public static readonly CssPercentageValue Zero = new(0.0); + + /// + /// Gets the half relative length, i.e. 50%. + /// + public static readonly CssPercentageValue Half = new(50.0); + + /// + /// Gets the full relative length, i.e. 100%. + /// + public static readonly CssPercentageValue Full = new(100.0); + + #endregion + #region Fields private readonly Double _value; @@ -175,6 +194,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssPercentageValue value && Equals(value); + /// /// Returns a hash code that defines the current percentage. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssQuoteValue.cs b/src/AngleSharp.Css/Values/Primitives/CssQuoteValue.cs index d42fa6a..b742649 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssQuoteValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssQuoteValue.cs @@ -73,6 +73,7 @@ namespace AngleSharp.Css.Values /// True if both are equal, otherwise false. public override Boolean Equals(Object obj) => obj is CssQuoteValue quote && Equals(quote); + Boolean IEquatable.Equals(ICssValue other) => other is CssQuoteValue value && Equals(value); /// /// Gets the hash code of the object. diff --git a/src/AngleSharp.Css/Values/Primitives/CssRatioValue.cs b/src/AngleSharp.Css/Values/Primitives/CssRatioValue.cs deleted file mode 100644 index bdab8e1..0000000 --- a/src/AngleSharp.Css/Values/Primitives/CssRatioValue.cs +++ /dev/null @@ -1,107 +0,0 @@ -namespace AngleSharp.Css.Values -{ - using AngleSharp.Css.Dom; - using System; - - /// - /// Represents a ratio (top to bottom) value. - /// - public readonly struct CssRatioValue : IEquatable, IComparable, ICssPrimitiveValue - { - #region Fields - - private readonly Double _top; - private readonly Double _bottom; - - #endregion - - #region ctor - - /// - /// Creates a new ratio value. - /// - /// The first number. - /// The second number. - public CssRatioValue(Double top, Double bottom) - { - _top = top; - _bottom = bottom; - } - - #endregion - - #region Properties - - /// - /// Gets the CSS text representation. - /// - public String CssText => String.Concat(_top.CssStringify(), "/", _bottom.CssStringify()); - - /// - /// Gets the first number of the ratio. - /// - public Double Top => _top; - - /// - /// Gets the second number of the ratio. - /// - public Double Bottom => _bottom; - - /// - /// Gets the normalized (Top / Bottom) value. - /// - public Double Value => _top / _bottom; - - #endregion - - #region Methods - - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } - - /// - /// Checks if the current resolution equals the given one. - /// - /// The given resolution to check for equality. - /// True if both are equal, otherwise false. - public Boolean Equals(CssRatioValue other) => Value == other.Value; - - #endregion - - #region Equality - - /// - /// Compares the current fraction against the given one. - /// - /// The fraction to compare to. - /// The result of the comparison. - public Int32 CompareTo(CssRatioValue other) => Value.CompareTo(other.Value); - - /// - /// Tests if another object is equal to this object. - /// - /// The object to test with. - /// True if the two objects are equal, otherwise false. - public override Boolean Equals(Object obj) - { - var other = obj as CssRatioValue?; - - if (other != null) - { - return Equals(other.Value); - } - - return false; - } - - /// - /// Returns a hash code that defines the current fraction. - /// - /// The integer value of the hashcode. - public override Int32 GetHashCode() => Value.GetHashCode(); - - #endregion - } -} diff --git a/src/AngleSharp.Css/Values/Primitives/CssResolutionValue.cs b/src/AngleSharp.Css/Values/Primitives/CssResolutionValue.cs index f5617a7..ebe347d 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssResolutionValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssResolutionValue.cs @@ -225,6 +225,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssResolutionValue value && Equals(value); + /// /// Returns a hash code that defines the current resolution. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssStringValue.cs b/src/AngleSharp.Css/Values/Primitives/CssStringValue.cs index 841dc8d..eef5352 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssStringValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssStringValue.cs @@ -66,6 +66,8 @@ namespace AngleSharp.Css.Values public override Boolean Equals(Object obj) => obj is CssStringValue str && Equals(str); + Boolean IEquatable.Equals(ICssValue other) => other is CssStringValue value && Equals(value); + /// /// Gets the hash code of the object. /// diff --git a/src/AngleSharp.Css/Values/Primitives/CssTimeValue.cs b/src/AngleSharp.Css/Values/Primitives/CssTimeValue.cs index 47a70a7..e3c9916 100644 --- a/src/AngleSharp.Css/Values/Primitives/CssTimeValue.cs +++ b/src/AngleSharp.Css/Values/Primitives/CssTimeValue.cs @@ -237,6 +237,8 @@ namespace AngleSharp.Css.Values return false; } + Boolean IEquatable.Equals(ICssValue other) => other is CssTimeValue value && Equals(value); + /// /// Returns a hash code that defines the current time. /// diff --git a/src/AngleSharp.Css/Values/Raws/CssAnyValue.cs b/src/AngleSharp.Css/Values/Raws/CssAnyValue.cs index e78cda5..7acbdb5 100644 --- a/src/AngleSharp.Css/Values/Raws/CssAnyValue.cs +++ b/src/AngleSharp.Css/Values/Raws/CssAnyValue.cs @@ -57,6 +57,8 @@ namespace AngleSharp.Css.Values return null; } + Boolean IEquatable.Equals(ICssValue other) => other is CssAnyValue o && _text.Equals(o.CssText); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Raws/CssInheritValue.cs b/src/AngleSharp.Css/Values/Raws/CssInheritValue.cs index 674b4ee..9e1718c 100644 --- a/src/AngleSharp.Css/Values/Raws/CssInheritValue.cs +++ b/src/AngleSharp.Css/Values/Raws/CssInheritValue.cs @@ -37,10 +37,9 @@ namespace AngleSharp.Css.Values #region Methods - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } + ICssValue ICssValue.Compute(ICssComputeContext context) => this; + + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); #endregion } diff --git a/src/AngleSharp.Css/Values/Raws/CssInitialValue.cs b/src/AngleSharp.Css/Values/Raws/CssInitialValue.cs index e10cc37..c23e403 100644 --- a/src/AngleSharp.Css/Values/Raws/CssInitialValue.cs +++ b/src/AngleSharp.Css/Values/Raws/CssInitialValue.cs @@ -43,10 +43,9 @@ namespace AngleSharp.Css.Values #region Methods - ICssValue ICssValue.Compute(ICssComputeContext context) - { - return this; - } + ICssValue ICssValue.Compute(ICssComputeContext context) => this; + + Boolean IEquatable.Equals(ICssValue other) => other is CssInitialValue o && _value.Equals(o.Value); #endregion } diff --git a/src/AngleSharp.Css/Values/Raws/CssReferenceValue.cs b/src/AngleSharp.Css/Values/Raws/CssReferenceValue.cs index aba00a4..f949517 100644 --- a/src/AngleSharp.Css/Values/Raws/CssReferenceValue.cs +++ b/src/AngleSharp.Css/Values/Raws/CssReferenceValue.cs @@ -76,6 +76,8 @@ namespace AngleSharp.Css.Values return null; } + Boolean IEquatable.Equals(ICssValue other) => Object.ReferenceEquals(this, other); + #endregion } } diff --git a/src/AngleSharp.Css/Values/Raws/CssUnsetValue.cs b/src/AngleSharp.Css/Values/Raws/CssUnsetValue.cs index b496e74..73a1f9e 100644 --- a/src/AngleSharp.Css/Values/Raws/CssUnsetValue.cs +++ b/src/AngleSharp.Css/Values/Raws/CssUnsetValue.cs @@ -48,6 +48,8 @@ namespace AngleSharp.Css.Values return this; } + Boolean IEquatable.Equals(ICssValue other) => other is CssUnsetValue o && _value.Equals(o.Value); + #endregion } } diff --git a/src/AngleSharp.Css/Values/TransformMatrix.cs b/src/AngleSharp.Css/Values/TransformMatrix.cs index 98236a6..0caa1a6 100644 --- a/src/AngleSharp.Css/Values/TransformMatrix.cs +++ b/src/AngleSharp.Css/Values/TransformMatrix.cs @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values /// Represents a transformation matrix value. /// http://dev.w3.org/csswg/css-transforms/#mathematical-description /// - public class TransformMatrix : IEquatable + public sealed class TransformMatrix : IEquatable { #region Fields