Skip to content

Commit baca67a

Browse files
committed
Improved computation #136
1 parent a5bcabf commit baca67a

24 files changed

+81
-34
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Released on tbd.
1313
- Fixed style empty if `text-align` is `start` (#151)
1414
- Fixed computation of priority in CSS rules using multi selector
1515
- Fixed `GetInnerText` multi-line / text node behavior (#155) @Seyden
16+
- Fixed computation of relative (`em`) values to absolute (`px`) for `Length` (#136)
1617
- Added further compactification of CSS tuples (#89, #93)
1718
- Added support for CSS nesting in style rules (#148)
1819
- Added support for 8-digit hex color codes (#132)

src/AngleSharp.Css.Tests/Extensions/AnalysisWindow.cs

+10
Original file line numberDiff line numberDiff line change
@@ -298,5 +298,15 @@ public async Task PriorityInMultiSelectorIsEvaluatedPerMatch()
298298
var style = sc.ComputeCascadedStyle(document.QuerySelector("h3"));
299299
Assert.AreEqual("rgba(0, 0, 255, 1)", style.GetColor());
300300
}
301+
302+
[Test]
303+
public async Task ComputesAbsoluteValuesFromRelative_Issue136()
304+
{
305+
var sheet = ParseStyleSheet(@"p { font-size: 1.5em }");
306+
var document = await sheet.Context.OpenAsync(res => res.Content(@"<p>This is <span>only</span> a test.</p>"));
307+
var sc = new StyleCollection(new[] { sheet }, new DefaultRenderDevice());
308+
var style = sc.ComputeDeclarations(document.QuerySelector("span"));
309+
Assert.AreEqual("24px", style.GetFontSize());
310+
}
301311
}
302312
}

src/AngleSharp.Css/Dom/ICssProperty.cs

+7
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,12 @@ public interface ICssProperty : IStyleFormattable
5757
/// Gets if the property is a shorthand.
5858
/// </summary>
5959
Boolean IsShorthand { get; }
60+
61+
/// <summary>
62+
/// Creates a computed version of the property.
63+
/// </summary>
64+
/// <param name="device">The device to compute for.</param>
65+
/// <returns>The computed version of the property if uncomputed, otherwise the same.</returns>
66+
ICssProperty Compute(IRenderDevice device);
6067
}
6168
}

src/AngleSharp.Css/Dom/Internal/CssProperty.cs

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ namespace AngleSharp.Css.Dom
22
{
33
using AngleSharp.Css;
44
using AngleSharp.Css.Converters;
5+
using AngleSharp.Css.Values;
56
using AngleSharp.Text;
67
using System;
78
using System.IO;
@@ -86,6 +87,22 @@ public Boolean IsImportant
8687

8788
#endregion
8889

90+
#region Methods
91+
92+
public ICssProperty Compute(IRenderDevice device)
93+
{
94+
if (_value is Length length && length.Type != Length.Unit.Px)
95+
{
96+
var px = length.ToPixel(device);
97+
var value = new Length(px, Length.Unit.Px);
98+
return new CssProperty(_name, _converter, _flags, value, _important);
99+
}
100+
101+
return this;
102+
}
103+
104+
#endregion
105+
89106
#region String Representation
90107

91108
public void ToCss(TextWriter writer, IStyleFormatter formatter) => writer.Write(formatter.Declaration(CssUtilities.Escape(Name), Value, IsImportant));

src/AngleSharp.Css/Dom/Internal/CssStyleDeclaration.cs

+15
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ sealed class CssStyleDeclaration : ICssStyleDeclaration
3232

3333
#region ctor
3434

35+
public CssStyleDeclaration()
36+
: this(default(IBrowsingContext))
37+
{
38+
}
39+
3540
public CssStyleDeclaration(IBrowsingContext context)
3641
{
3742
_declarations = new List<ICssProperty>();
@@ -301,6 +306,16 @@ public void SetProperty(String propertyName, String propertyValue, String priori
301306
}
302307
}
303308

309+
public void AddProperty(ICssProperty declaration)
310+
{
311+
_declarations.Add(declaration);
312+
}
313+
314+
public void RemoveProperty(ICssProperty declaration)
315+
{
316+
_declarations.Remove(declaration);
317+
}
318+
304319
#endregion
305320

306321
#region Internal Methods

src/AngleSharp.Css/Extensions/CssOmExtensions.cs

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
namespace AngleSharp.Css.Dom
22
{
33
using AngleSharp.Css.Parser;
4-
using AngleSharp.Css.Values;
54
using AngleSharp.Text;
65
using System;
76
using System.Linq;
@@ -74,16 +73,14 @@ public static ICssValue GetValueOf(this ICssStyleRule rule, String propertyName)
7473
/// <returns>A new style declaration with the existing or computed values.</returns>
7574
public static ICssStyleDeclaration Compute(this ICssStyleDeclaration style, IRenderDevice device)
7675
{
77-
//var prop = style.GetProperty("font-size");
76+
var computedStyle = new CssStyleDeclaration();
7877

79-
//if (prop is not null && prop.RawValue is Length length)
80-
//{
81-
// var px = length.ToPixel(device, RenderMode.Horizontal);
82-
// var prio = prop.IsImportant ? CssKeywords.Important : null;
83-
// style.SetProperty(prop.Name, $"{px}px", prio);
84-
//}
78+
foreach (var property in style)
79+
{
80+
computedStyle.AddProperty(property.Compute(device));
81+
}
8582

86-
return style;
83+
return computedStyle;
8784
}
8885
}
8986
}

src/AngleSharp.Css/Extensions/StyleCollectionExtensions.cs

+8-8
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ public static IStyleCollection GetStyleCollection(this IWindow window)
3636
/// Computes the declarations for the given element in the context of
3737
/// the specified styling rules.
3838
/// </summary>
39-
/// <param name="rules">The styles to use.</param>
39+
/// <param name="styles">The styles to use.</param>
4040
/// <param name="element">The element that is questioned.</param>
4141
/// <param name="pseudoSelector">The optional pseudo selector to use.</param>
4242
/// <returns>The style declaration containing all the declarations.</returns>
43-
public static ICssStyleDeclaration ComputeDeclarations(this IEnumerable<ICssStyleRule> rules, IElement element, String pseudoSelector = null)
43+
public static ICssStyleDeclaration ComputeDeclarations(this IStyleCollection styles, IElement element, String pseudoSelector = null)
4444
{
4545
var ctx = element.Owner?.Context;
46-
var device = ctx?.GetService<IRenderDevice>();
46+
var device = styles.Device;
4747
var computedStyle = new CssStyleDeclaration(ctx);
4848
var nodes = element.GetAncestors().OfType<IElement>();
4949

@@ -57,11 +57,11 @@ public static ICssStyleDeclaration ComputeDeclarations(this IEnumerable<ICssStyl
5757
}
5858
}
5959

60-
computedStyle.SetDeclarations(rules.ComputeCascadedStyle(element));
60+
computedStyle.SetDeclarations(styles.ComputeCascadedStyle(element));
6161

6262
foreach (var node in nodes)
6363
{
64-
computedStyle.UpdateDeclarations(rules.ComputeCascadedStyle(node));
64+
computedStyle.UpdateDeclarations(styles.ComputeCascadedStyle(node));
6565
}
6666

6767
if (device is not null)
@@ -77,14 +77,14 @@ public static ICssStyleDeclaration ComputeDeclarations(this IEnumerable<ICssStyl
7777
/// Two rules with the same specificity are ordered according to their appearance. The more
7878
/// recent declaration wins. Inheritance is not taken into account.
7979
/// </summary>
80-
/// <param name="styleCollection">The style rules to apply.</param>
80+
/// <param name="rules">The style rules to apply.</param>
8181
/// <param name="element">The element to compute the cascade for.</param>
8282
/// <param name="parent">The potential parent for the cascade.</param>
8383
/// <returns>Returns the cascaded read-only style declaration.</returns>
84-
public static ICssStyleDeclaration ComputeCascadedStyle(this IEnumerable<ICssStyleRule> styleCollection, IElement element, ICssStyleDeclaration parent = null)
84+
public static ICssStyleDeclaration ComputeCascadedStyle(this IStyleCollection styles, IElement element, ICssStyleDeclaration parent = null)
8585
{
8686
var computedStyle = new CssStyleDeclaration(element.Owner?.Context);
87-
var rules = styleCollection.SortBySpecificity(element);
87+
var rules = styles.SortBySpecificity(element);
8888

8989
foreach (var rule in rules)
9090
{

src/AngleSharp.Css/Values/Primitives/Angle.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// Represents an angle object.
77
/// https://developer.mozilla.org/en-US/docs/Web/CSS/angle
88
/// </summary>
9-
public struct Angle : IEquatable<Angle>, IComparable<Angle>, ICssPrimitiveValue
9+
public readonly struct Angle : IEquatable<Angle>, IComparable<Angle>, ICssPrimitiveValue
1010
{
1111
#region Basic angles
1212

src/AngleSharp.Css/Values/Primitives/Constant.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
55
/// <summary>
66
/// Represents a selected CSS enum value.
77
/// </summary>
8-
public struct Constant<T> : ICssPrimitiveValue, IEquatable<Constant<T>>
8+
public readonly struct Constant<T> : ICssPrimitiveValue, IEquatable<Constant<T>>
99
{
1010
#region Fields
1111

src/AngleSharp.Css/Values/Primitives/CounterDefinition.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// <summary>
77
/// Represents a CSS counter.
88
/// </summary>
9-
public struct CounterDefinition : ICssPrimitiveValue, IEquatable<CounterDefinition>
9+
public readonly struct CounterDefinition : ICssPrimitiveValue, IEquatable<CounterDefinition>
1010
{
1111
#region Fields
1212

src/AngleSharp.Css/Values/Primitives/CounterValue.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// <summary>
77
/// Sets a CSS counter.
88
/// </summary>
9-
public struct CounterValue : ICssPrimitiveValue, IEquatable<CounterValue>
9+
public readonly struct CounterValue : ICssPrimitiveValue, IEquatable<CounterValue>
1010
{
1111
#region Fields
1212

src/AngleSharp.Css/Values/Primitives/Fraction.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
55
/// <summary>
66
/// Represents a fractional value.
77
/// </summary>
8-
public struct Fraction : IEquatable<Fraction>, IComparable<Fraction>, ICssPrimitiveValue
8+
public readonly struct Fraction : IEquatable<Fraction>, IComparable<Fraction>, ICssPrimitiveValue
99
{
1010
#region Fields
1111

src/AngleSharp.Css/Values/Primitives/Frequency.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
55
/// <summary>
66
/// Represents a time value.
77
/// </summary>
8-
public struct Frequency : IEquatable<Frequency>, IComparable<Frequency>, ICssPrimitiveValue
8+
public readonly struct Frequency : IEquatable<Frequency>, IComparable<Frequency>, ICssPrimitiveValue
99
{
1010
#region Fields
1111

src/AngleSharp.Css/Values/Primitives/Identifier.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// <summary>
77
/// Represents a CSS identifier value.
88
/// </summary>
9-
public struct Identifier : ICssPrimitiveValue, IEquatable<Identifier>
9+
public readonly struct Identifier : ICssPrimitiveValue, IEquatable<Identifier>
1010
{
1111
#region Fields
1212

src/AngleSharp.Css/Values/Primitives/Label.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// <summary>
77
/// Represents a CSS label ("string") value.
88
/// </summary>
9-
public struct Label : ICssPrimitiveValue, IEquatable<Label>
9+
public readonly struct Label : ICssPrimitiveValue, IEquatable<Label>
1010
{
1111
#region Fields
1212

src/AngleSharp.Css/Values/Primitives/Length.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
55
/// <summary>
66
/// Represents an absolute length value.
77
/// </summary>
8-
public struct Length : IEquatable<Length>, IComparable<Length>, ICssPrimitiveValue
8+
public readonly struct Length : IEquatable<Length>, IComparable<Length>, ICssPrimitiveValue
99
{
1010
#region Basic lengths
1111

src/AngleSharp.Css/Values/Primitives/LineNames.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace AngleSharp.Css.Values
88
/// <summary>
99
/// Represents a CSS line names definition.
1010
/// </summary>
11-
public struct LineNames : ICssPrimitiveValue, IEquatable<LineNames>
11+
public readonly struct LineNames : ICssPrimitiveValue, IEquatable<LineNames>
1212
{
1313
#region Fields
1414

src/AngleSharp.Css/Values/Primitives/Point.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// <summary>
77
/// Represents a point value consisting of two distances.
88
/// </summary>
9-
public struct Point : IEquatable<Point>, ICssPrimitiveValue
9+
public readonly struct Point : IEquatable<Point>, ICssPrimitiveValue
1010
{
1111
#region Basic values
1212

src/AngleSharp.Css/Values/Primitives/Quote.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// <summary>
77
/// Represents a CSS quote.
88
/// </summary>
9-
public struct Quote : ICssPrimitiveValue, IEquatable<Quote>
9+
public readonly struct Quote : ICssPrimitiveValue, IEquatable<Quote>
1010
{
1111
#region Fields
1212

src/AngleSharp.Css/Values/Primitives/Ratio.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
55
/// <summary>
66
/// Represents a ratio (top to bottom) value.
77
/// </summary>
8-
public struct Ratio : IEquatable<Ratio>, IComparable<Ratio>, ICssPrimitiveValue
8+
public readonly struct Ratio : IEquatable<Ratio>, IComparable<Ratio>, ICssPrimitiveValue
99
{
1010
#region Fields
1111

src/AngleSharp.Css/Values/Primitives/Resolution.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
55
/// <summary>
66
/// Represents a resolution value.
77
/// </summary>
8-
public struct Resolution : IEquatable<Resolution>, IComparable<Resolution>, ICssPrimitiveValue
8+
public readonly struct Resolution : IEquatable<Resolution>, IComparable<Resolution>, ICssPrimitiveValue
99
{
1010
#region Fields
1111

src/AngleSharp.Css/Values/Primitives/Time.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
55
/// <summary>
66
/// Represents a time value.
77
/// </summary>
8-
public struct Time : IEquatable<Time>, IComparable<Time>, ICssPrimitiveValue
8+
public readonly struct Time : IEquatable<Time>, IComparable<Time>, ICssPrimitiveValue
99
{
1010
#region Basic times
1111

src/AngleSharp.Css/Values/Raws/CssInitialValue.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// <summary>
77
/// Represents the CSS initial value.
88
/// </summary>
9-
struct CssInitialValue : ICssSpecialValue
9+
readonly struct CssInitialValue : ICssSpecialValue
1010
{
1111
#region Fields
1212

src/AngleSharp.Css/Values/Raws/CssUnsetValue.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
66
/// <summary>
77
/// Represents a CSS unset value.
88
/// </summary>
9-
struct CssUnsetValue : ICssSpecialValue
9+
readonly struct CssUnsetValue : ICssSpecialValue
1010
{
1111
#region Fields
1212

0 commit comments

Comments
 (0)