mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Support non-fixed <random-value-sharing>
This works by generating random values using XorShift128PlusRNG at compute time and then caching them on the document using the relevant random-caching-key
This commit is contained in:
parent
86e6aa0291
commit
12e8f503aa
Notes:
github-actions[bot]
2025-12-01 11:01:47 +00:00
Author: https://github.com/Calme1709
Commit: 12e8f503aa
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6707
Reviewed-by: https://github.com/AtkinsSJ ✅
Reviewed-by: https://github.com/gmta
15 changed files with 226 additions and 54 deletions
|
|
@ -2595,7 +2595,9 @@ String RandomCalculationNode::to_string(CalculationContext const& context, Seria
|
|||
StringBuilder builder;
|
||||
|
||||
builder.append("random("sv);
|
||||
builder.appendff("{}, ", m_random_value_sharing->to_string(serialization_mode));
|
||||
auto random_value_sharing_stringified = m_random_value_sharing->to_string(serialization_mode);
|
||||
if (!random_value_sharing_stringified.is_empty())
|
||||
builder.appendff("{}, ", random_value_sharing_stringified);
|
||||
builder.appendff("{}, ", serialize_a_calculation_tree(m_minimum, context, serialization_mode));
|
||||
builder.append(serialize_a_calculation_tree(m_maximum, context, serialization_mode));
|
||||
if (m_step)
|
||||
|
|
|
|||
|
|
@ -7,11 +7,15 @@
|
|||
#include "RandomValueSharingStyleValue.h"
|
||||
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
ValueComparingNonnullRefPtr<StyleValue const> RandomValueSharingStyleValue::absolutized(ComputationContext const& computation_context) const
|
||||
{
|
||||
// https://drafts.csswg.org/css-values-5/#random-caching
|
||||
// Each instance of a random function in styles has an associated random base value.
|
||||
// If the random function’s <random-value-sharing> is fixed <number>, the random base value is that number.
|
||||
if (m_fixed_value) {
|
||||
auto const& absolutized_fixed_value = m_fixed_value->absolutized(computation_context);
|
||||
|
||||
|
|
@ -21,7 +25,29 @@ ValueComparingNonnullRefPtr<StyleValue const> RandomValueSharingStyleValue::abso
|
|||
return RandomValueSharingStyleValue::create_fixed(absolutized_fixed_value);
|
||||
}
|
||||
|
||||
TODO();
|
||||
// Otherwise, the random base value is a pseudo-random real number in the range `[0, 1)` (greater than or equal to 0
|
||||
// and less than 1), generated from a uniform distribution, and influenced by the function’s random caching key.
|
||||
|
||||
// A random caching key is a tuple of:
|
||||
RandomCachingKey random_caching_key {
|
||||
// 1. A string name: the value of the <dashed-ident>, if specified in <random-value-sharing>; or else a string
|
||||
// of the form "PROPERTY N", where PROPERTY is the name of the property the random function is used in
|
||||
// (before shorthand expansion, if relevant), and N is the index of the random function among other random
|
||||
// functions in the same property value.
|
||||
.name = m_name.value(),
|
||||
|
||||
// 2. An element ID identifying the element the style is being applied to, or null if element-shared is
|
||||
// specified in <random-value-sharing>.
|
||||
// FIXME: Use the pseudo element's unique_id() when that's accessible
|
||||
.element_id = m_element_shared ? Optional<UniqueNodeID> { OptionalNone {} } : Optional<UniqueNodeID> { computation_context.abstract_element->element().unique_id() },
|
||||
|
||||
// 3. A document ID identifying the Document the styles are from.
|
||||
// NB: This is implicit since the cache is stored on the document or the element (which is a child of the document).
|
||||
};
|
||||
|
||||
auto random_base_value = const_cast<DOM::Element&>(computation_context.abstract_element->element()).ensure_css_random_base_value(random_caching_key);
|
||||
|
||||
return RandomValueSharingStyleValue::create_fixed(NumberStyleValue::create(random_base_value));
|
||||
}
|
||||
|
||||
double RandomValueSharingStyleValue::random_base_value() const
|
||||
|
|
@ -43,7 +69,18 @@ String RandomValueSharingStyleValue::to_string(SerializationMode serialization_m
|
|||
if (m_fixed_value)
|
||||
return MUST(String::formatted("fixed {}", m_fixed_value->to_string(serialization_mode)));
|
||||
|
||||
TODO();
|
||||
StringBuilder builder;
|
||||
|
||||
if (!m_is_auto)
|
||||
builder.appendff("{}", m_name.value());
|
||||
|
||||
if (m_element_shared) {
|
||||
if (!builder.is_empty())
|
||||
builder.append(' ');
|
||||
builder.append("element-shared"sv);
|
||||
}
|
||||
|
||||
return builder.to_string_without_validation();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,26 @@
|
|||
|
||||
namespace Web::CSS {
|
||||
|
||||
struct RandomCachingKey {
|
||||
FlyString name;
|
||||
Optional<Web::UniqueNodeID> element_id;
|
||||
};
|
||||
|
||||
class RandomValueSharingStyleValue : public StyleValueWithDefaultOperators<RandomValueSharingStyleValue> {
|
||||
public:
|
||||
static ValueComparingNonnullRefPtr<RandomValueSharingStyleValue const> create_fixed(NonnullRefPtr<StyleValue const> const& fixed_value)
|
||||
{
|
||||
return adopt_ref(*new (nothrow) RandomValueSharingStyleValue(fixed_value));
|
||||
return adopt_ref(*new (nothrow) RandomValueSharingStyleValue(fixed_value, false, {}, false));
|
||||
}
|
||||
|
||||
static ValueComparingNonnullRefPtr<RandomValueSharingStyleValue const> create_auto(FlyString name, bool element_shared)
|
||||
{
|
||||
return adopt_ref(*new (nothrow) RandomValueSharingStyleValue({}, true, move(name), element_shared));
|
||||
}
|
||||
|
||||
static ValueComparingNonnullRefPtr<RandomValueSharingStyleValue const> create_dashed_ident(FlyString name, bool element_shared)
|
||||
{
|
||||
return adopt_ref(*new (nothrow) RandomValueSharingStyleValue({}, false, move(name), element_shared));
|
||||
}
|
||||
|
||||
virtual ~RandomValueSharingStyleValue() override = default;
|
||||
|
|
@ -28,17 +43,46 @@ public:
|
|||
|
||||
bool properties_equal(RandomValueSharingStyleValue const& other) const
|
||||
{
|
||||
return m_fixed_value == other.m_fixed_value;
|
||||
return m_fixed_value == other.m_fixed_value
|
||||
&& m_is_auto == other.m_is_auto
|
||||
&& m_name == other.m_name
|
||||
&& m_element_shared == other.m_element_shared;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit RandomValueSharingStyleValue(RefPtr<StyleValue const> fixed_value)
|
||||
explicit RandomValueSharingStyleValue(RefPtr<StyleValue const> fixed_value, bool is_auto, Optional<FlyString> name, bool element_shared)
|
||||
: StyleValueWithDefaultOperators(Type::RandomValueSharing)
|
||||
, m_fixed_value(move(fixed_value))
|
||||
, m_is_auto(is_auto)
|
||||
, m_name(move(name))
|
||||
, m_element_shared(element_shared)
|
||||
{
|
||||
}
|
||||
|
||||
ValueComparingRefPtr<StyleValue const> m_fixed_value;
|
||||
bool m_is_auto;
|
||||
Optional<FlyString> m_name;
|
||||
bool m_element_shared;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace AK {
|
||||
|
||||
template<>
|
||||
struct Traits<Web::CSS::RandomCachingKey> : public DefaultTraits<Web::CSS::RandomCachingKey> {
|
||||
static unsigned hash(Web::CSS::RandomCachingKey const& key)
|
||||
{
|
||||
if (!key.element_id.has_value())
|
||||
return key.name.hash();
|
||||
|
||||
return pair_int_hash(key.name.hash(), Traits<i64>::hash(key.element_id->value()));
|
||||
}
|
||||
|
||||
static bool equals(Web::CSS::RandomCachingKey const& a, Web::CSS::RandomCachingKey const& b)
|
||||
{
|
||||
return a.element_id == b.element_id && a.name == b.name;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue