Skip to content

Commit

Permalink
Improved computation #136
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianRappl committed Jan 17, 2024
1 parent a5bcabf commit baca67a
Show file tree
Hide file tree
Showing 24 changed files with 81 additions and 34 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Released on tbd.
- Fixed style empty if `text-align` is `start` (#151)
- Fixed computation of priority in CSS rules using multi selector
- 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 support for CSS nesting in style rules (#148)
- Added support for 8-digit hex color codes (#132)
Expand Down
10 changes: 10 additions & 0 deletions src/AngleSharp.Css.Tests/Extensions/AnalysisWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,5 +298,15 @@ public async Task PriorityInMultiSelectorIsEvaluatedPerMatch()
var style = sc.ComputeCascadedStyle(document.QuerySelector("h3"));
Assert.AreEqual("rgba(0, 0, 255, 1)", style.GetColor());
}

[Test]
public async Task ComputesAbsoluteValuesFromRelative_Issue136()
{
var sheet = ParseStyleSheet(@"p { font-size: 1.5em }");
var document = await sheet.Context.OpenAsync(res => res.Content(@"<p>This is <span>only</span> a test.</p>"));
var sc = new StyleCollection(new[] { sheet }, new DefaultRenderDevice());
var style = sc.ComputeDeclarations(document.QuerySelector("span"));
Assert.AreEqual("24px", style.GetFontSize());
}
}
}
7 changes: 7 additions & 0 deletions src/AngleSharp.Css/Dom/ICssProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,12 @@ public interface ICssProperty : IStyleFormattable
/// Gets if the property is a shorthand.
/// </summary>
Boolean IsShorthand { get; }

/// <summary>
/// Creates a computed version of the property.
/// </summary>
/// <param name="device">The device to compute for.</param>
/// <returns>The computed version of the property if uncomputed, otherwise the same.</returns>
ICssProperty Compute(IRenderDevice device);
}
}
17 changes: 17 additions & 0 deletions src/AngleSharp.Css/Dom/Internal/CssProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace AngleSharp.Css.Dom
{
using AngleSharp.Css;
using AngleSharp.Css.Converters;
using AngleSharp.Css.Values;
using AngleSharp.Text;
using System;
using System.IO;
Expand Down Expand Up @@ -86,6 +87,22 @@ public Boolean IsImportant

#endregion

#region Methods

public ICssProperty Compute(IRenderDevice device)
{
if (_value is Length length && length.Type != Length.Unit.Px)
{
var px = length.ToPixel(device);
var value = new Length(px, Length.Unit.Px);
return new CssProperty(_name, _converter, _flags, value, _important);
}

return this;
}

#endregion

#region String Representation

public void ToCss(TextWriter writer, IStyleFormatter formatter) => writer.Write(formatter.Declaration(CssUtilities.Escape(Name), Value, IsImportant));
Expand Down
15 changes: 15 additions & 0 deletions src/AngleSharp.Css/Dom/Internal/CssStyleDeclaration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ sealed class CssStyleDeclaration : ICssStyleDeclaration

#region ctor

public CssStyleDeclaration()
: this(default(IBrowsingContext))
{
}

public CssStyleDeclaration(IBrowsingContext context)
{
_declarations = new List<ICssProperty>();
Expand Down Expand Up @@ -301,6 +306,16 @@ public void SetProperty(String propertyName, String propertyValue, String priori
}
}

public void AddProperty(ICssProperty declaration)
{
_declarations.Add(declaration);
}

public void RemoveProperty(ICssProperty declaration)
{
_declarations.Remove(declaration);
}

#endregion

#region Internal Methods
Expand Down
15 changes: 6 additions & 9 deletions src/AngleSharp.Css/Extensions/CssOmExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace AngleSharp.Css.Dom
{
using AngleSharp.Css.Parser;
using AngleSharp.Css.Values;
using AngleSharp.Text;
using System;
using System.Linq;
Expand Down Expand Up @@ -74,16 +73,14 @@ public static ICssValue GetValueOf(this ICssStyleRule rule, String propertyName)
/// <returns>A new style declaration with the existing or computed values.</returns>
public static ICssStyleDeclaration Compute(this ICssStyleDeclaration style, IRenderDevice device)
{
//var prop = style.GetProperty("font-size");
var computedStyle = new CssStyleDeclaration();

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

return style;
return computedStyle;
}
}
}
16 changes: 8 additions & 8 deletions src/AngleSharp.Css/Extensions/StyleCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ public static IStyleCollection GetStyleCollection(this IWindow window)
/// Computes the declarations for the given element in the context of
/// the specified styling rules.
/// </summary>
/// <param name="rules">The styles to use.</param>
/// <param name="styles">The styles to use.</param>
/// <param name="element">The element that is questioned.</param>
/// <param name="pseudoSelector">The optional pseudo selector to use.</param>
/// <returns>The style declaration containing all the declarations.</returns>
public static ICssStyleDeclaration ComputeDeclarations(this IEnumerable<ICssStyleRule> rules, IElement element, String pseudoSelector = null)
public static ICssStyleDeclaration ComputeDeclarations(this IStyleCollection styles, IElement element, String pseudoSelector = null)
{
var ctx = element.Owner?.Context;
var device = ctx?.GetService<IRenderDevice>();
var device = styles.Device;
var computedStyle = new CssStyleDeclaration(ctx);
var nodes = element.GetAncestors().OfType<IElement>();

Expand All @@ -57,11 +57,11 @@ public static ICssStyleDeclaration ComputeDeclarations(this IEnumerable<ICssStyl
}
}

computedStyle.SetDeclarations(rules.ComputeCascadedStyle(element));
computedStyle.SetDeclarations(styles.ComputeCascadedStyle(element));

foreach (var node in nodes)
{
computedStyle.UpdateDeclarations(rules.ComputeCascadedStyle(node));
computedStyle.UpdateDeclarations(styles.ComputeCascadedStyle(node));
}

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

foreach (var rule in rules)
{
Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Angle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// Represents an angle object.
/// https://developer.mozilla.org/en-US/docs/Web/CSS/angle
/// </summary>
public struct Angle : IEquatable<Angle>, IComparable<Angle>, ICssPrimitiveValue
public readonly struct Angle : IEquatable<Angle>, IComparable<Angle>, ICssPrimitiveValue
{
#region Basic angles

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Constant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a selected CSS enum value.
/// </summary>
public struct Constant<T> : ICssPrimitiveValue, IEquatable<Constant<T>>
public readonly struct Constant<T> : ICssPrimitiveValue, IEquatable<Constant<T>>
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/CounterDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a CSS counter.
/// </summary>
public struct CounterDefinition : ICssPrimitiveValue, IEquatable<CounterDefinition>
public readonly struct CounterDefinition : ICssPrimitiveValue, IEquatable<CounterDefinition>
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/CounterValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Sets a CSS counter.
/// </summary>
public struct CounterValue : ICssPrimitiveValue, IEquatable<CounterValue>
public readonly struct CounterValue : ICssPrimitiveValue, IEquatable<CounterValue>
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Fraction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a fractional value.
/// </summary>
public struct Fraction : IEquatable<Fraction>, IComparable<Fraction>, ICssPrimitiveValue
public readonly struct Fraction : IEquatable<Fraction>, IComparable<Fraction>, ICssPrimitiveValue
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Frequency.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a time value.
/// </summary>
public struct Frequency : IEquatable<Frequency>, IComparable<Frequency>, ICssPrimitiveValue
public readonly struct Frequency : IEquatable<Frequency>, IComparable<Frequency>, ICssPrimitiveValue
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Identifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a CSS identifier value.
/// </summary>
public struct Identifier : ICssPrimitiveValue, IEquatable<Identifier>
public readonly struct Identifier : ICssPrimitiveValue, IEquatable<Identifier>
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Label.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a CSS label ("string") value.
/// </summary>
public struct Label : ICssPrimitiveValue, IEquatable<Label>
public readonly struct Label : ICssPrimitiveValue, IEquatable<Label>
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Length.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents an absolute length value.
/// </summary>
public struct Length : IEquatable<Length>, IComparable<Length>, ICssPrimitiveValue
public readonly struct Length : IEquatable<Length>, IComparable<Length>, ICssPrimitiveValue
{
#region Basic lengths

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/LineNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a CSS line names definition.
/// </summary>
public struct LineNames : ICssPrimitiveValue, IEquatable<LineNames>
public readonly struct LineNames : ICssPrimitiveValue, IEquatable<LineNames>
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Point.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a point value consisting of two distances.
/// </summary>
public struct Point : IEquatable<Point>, ICssPrimitiveValue
public readonly struct Point : IEquatable<Point>, ICssPrimitiveValue
{
#region Basic values

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Quote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a CSS quote.
/// </summary>
public struct Quote : ICssPrimitiveValue, IEquatable<Quote>
public readonly struct Quote : ICssPrimitiveValue, IEquatable<Quote>
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Ratio.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a ratio (top to bottom) value.
/// </summary>
public struct Ratio : IEquatable<Ratio>, IComparable<Ratio>, ICssPrimitiveValue
public readonly struct Ratio : IEquatable<Ratio>, IComparable<Ratio>, ICssPrimitiveValue
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Resolution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a resolution value.
/// </summary>
public struct Resolution : IEquatable<Resolution>, IComparable<Resolution>, ICssPrimitiveValue
public readonly struct Resolution : IEquatable<Resolution>, IComparable<Resolution>, ICssPrimitiveValue
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Primitives/Time.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a time value.
/// </summary>
public struct Time : IEquatable<Time>, IComparable<Time>, ICssPrimitiveValue
public readonly struct Time : IEquatable<Time>, IComparable<Time>, ICssPrimitiveValue
{
#region Basic times

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Raws/CssInitialValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents the CSS initial value.
/// </summary>
struct CssInitialValue : ICssSpecialValue
readonly struct CssInitialValue : ICssSpecialValue
{
#region Fields

Expand Down
2 changes: 1 addition & 1 deletion src/AngleSharp.Css/Values/Raws/CssUnsetValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AngleSharp.Css.Values
/// <summary>
/// Represents a CSS unset value.
/// </summary>
struct CssUnsetValue : ICssSpecialValue
readonly struct CssUnsetValue : ICssSpecialValue
{
#region Fields

Expand Down

0 comments on commit baca67a

Please sign in to comment.