Commit graph

639 commits

Author SHA1 Message Date
Psychpsyo
eb7824339b LibWeb: Improve user-select support 2025-01-06 12:22:37 +00:00
Aliaksandr Kalenik
482e5deb85 LibWeb: Further optimize :hover style invalidation
Previously, we optimized hover style invalidation to mark for style
updates only those elements that were matched by :hover selectors in the
last style calculation.

This change takes it a step further by invalidating only the elements
where the set of selectors that use :hover changes after hovered element
is modified. The implementation is as follows:
1. Collect all elements whose styles might be affected by a change in
   the hovered element.
2. Retrieve a list of all selectors that use :hover.
3. Test each selector against each element and record which selectors
   match.
4. Update m_hovered_node to the newly hovered element.
5. Repeat step 3.
6. For each element, compare the previous and current sets of matched
   selectors. If they differ, mark the element for style recalculation.
2025-01-04 20:32:35 +01:00
Aliaksandr Kalenik
e465e922bd LibWeb: Optimize :hover style invalidation
Instead of recalculating styles for all nodes in the common ancestor of
the new and old hovered nodes' subtrees, this change introduces the
following approach:
- While calculating ComputedProperties, a flag is saved if any rule
  applied to an element is affected by the hover state during the
  execution of SelectorEngine::matches().
- When the hovered element changes, styles are marked for recalculation
  only if the flag saved in ComputedProperties indicates that the
  element could be affected by the hover state.
2025-01-04 20:32:35 +01:00
Jaycadox
db58986e5f LibWeb/CSS: Recalculate calc() numeric type when resolving percentages
Previously, `percentage_of` would be called on the previous value,
potentially changing its numeric type, yet this potential change
was never reflected as the old numeric type was always used. Now,
the numeric type will be re-calculated every time after the
percentage is resolved. As well, VERIFY checks have been placed to
uphold the requirements for the numeric types to match what the
actual values are.
2025-01-04 18:47:44 +00:00
Psychpsyo
33f87288e9 LibWeb: Remove unneeded spec deviation from font loading 2025-01-04 17:58:38 +00:00
Lucas CHOLLET
d879771044 LibWeb/CSS: Consider unresolved calc() when serializing in Normal mode
Unfortunately, there is no explicit and step-by-step spec to perform
the serialization of `color()` declared values, so while being
spec-informed, this is quite ad-hoc.

Fixes 81 subtests in:
 - css/css-color/parsing/color-valid-color-function.html
2025-01-03 16:49:23 +00:00
Aliaksandr Kalenik
ccb543ebb8 LibWeb/CSS: Skip build of rule cache for inactive documents
Some websites (Reddit, for example) create lots of temporary documents
for fragment parsing. Before this change, we had to build a rule cache
for these documents just to determine whether there are :has, :defined,
or attribute selectors, while it should be safe to simply return `false`
right away.
2025-01-03 10:59:41 +01:00
Aliaksandr Kalenik
c7d6a7aafb LibWeb: Insert default font in font list before emoji font
This fixes a bug where, if a non-existent font family is specified in
CSS, whitespaces would be rendered using the emoji font, while letters
would use the default font. This issue occurred because the font was
resolved separately for each code point. Since the emoji font was listed
before the default font, it was chosen for whitespace characters due to
its inclusion of whitespace glyphs (at least in the Apple Color Emoji
font on macOS). This change resolves the issue by placing the default
font before the emoji font in the list.
2025-01-02 10:47:21 +01:00
Aliaksandr Kalenik
8b8d83a318 LibWeb: Request default font with size specified in style 2025-01-02 10:47:21 +01:00
Aliaksandr Kalenik
0b8b690f92 LibWeb+LibWebView: Allow to specify default font size in FontPlugin
Instead of always assuming 12pt size for default font, explicitly pass
it as a parameter.
2025-01-02 10:47:21 +01:00
Gingeh
0a6793c89b LibWeb: Check if types have a present and nonzero percentage value
Co-authored-by: Chase Knowlden <haroldknowlden@gmail.com>
Co-authored-by: "tanner.drake" <tanner.drake@protonmail.com>
2024-12-30 11:09:15 +01:00
Gingeh
436417aabe LibWeb: Parse background positions as shorthands 2024-12-30 11:07:53 +01:00
Timothy Flynn
27478ec7d4 Everywhere: Run clang-format
The following command was used to clang-format these files:

    clang-format-19 -i $(find . \
        -not \( -path "./\.*" -prune \) \
        -not \( -path "./Build/*" -prune \) \
        -not \( -path "./Toolchain/*" -prune \) \
        -type f -name "*.cpp" -o -name "*.mm" -o -name "*.h")
2024-12-28 05:39:32 -08:00
Shannon Booth
b165ffc868 LibWeb/CSS: Add overflow hidden to UA stylesheet for marquee element 2024-12-28 11:18:25 +00:00
Andreas Kling
3bfb0534be LibGC: Rename MarkedVector => RootVector
Let's try to make it a bit more clear that this is a Vector of GC roots.
2024-12-26 19:10:44 +01:00
Lucas CHOLLET
1c61ccef40 LibWeb/DOM: Fire transition[cancel,start,run,end] events 2024-12-25 17:14:08 +01:00
Lucas CHOLLET
a2ab3769f4 LibWeb/CSS: Don't assume that animations have an associated effect
... when computing properties.
2024-12-25 17:14:08 +01:00
Lucas CHOLLET
55b4a983a7 LibWeb/CSS: Add the TransitionEvent type 2024-12-25 17:14:08 +01:00
sideshowbarker
72a86f2df3 LibWeb: Fix selector matching for non-HTML mixed-case element names
This change fixes selector matching for non-HTML elements that have
mixed-case names — such as the SVG foreignObject element.

Otherwise, without this change, attempting to use a selector to match
such an element — e.g., document.querySelector("foreignObject") — fails.
2024-12-25 13:54:06 +00:00
Andreas Kling
f45e24864b LibWeb: Skip unneeded style invalidation on custom element state change
If there are no :defined pseudo-class selectors anywhere in the
document, we don't have to invalidate style at all when an element's
custom element state changes.
2024-12-25 13:26:51 +01:00
Lucas CHOLLET
c5f9710492 LibWeb/CSS: Create a MediaQueryListEvent when calling MQLE::create()
Otherwise, if not implemented, `MediaQueryListEvent::create()` would
result in a call to `DOM::Event::create()`. This issue exists here:
673537b26b/Libraries/LibWeb/DOM/Document.cpp (L2865)
2024-12-25 11:56:37 +01:00
Andreas Kling
b981e6f7bc LibWeb: Avoid many style invalidations on DOM attribute mutation
Many times, attribute mutation doesn't necessitate a full style
invalidation on the element. However, the conditions are pretty
elaborate, so this first version has a lot of false positives.

We only need to invalidate style when any of these things apply:

1. The change may affect the match state of a selector somewhere.
2. The change may affect presentational hints applied to the element.

For (1) in this first version, we have a fixed list of attribute names
that may affect selectors. We also collect all names referenced by
attribute selectors anywhere in the document.

For (2), we add a new Element::is_presentational_hint() virtual that
tells us whether a given attribute name is a presentational hint.

This drastically reduces style work on many websites. As an example,
https://cnn.com/ is once again browseable.
2024-12-24 17:17:09 +01:00
Andreas Kling
6983c65c54 LibWeb: Collect interesting document-wide insights about CSS selectors
Starting out with these two things:
- Whether any :has() selectors are present
- The set of all names referenced by attribute selectors
2024-12-23 17:05:09 +01:00
Andreas Kling
dc8343cc23 LibWeb: Add mechanism to invalidate only inherited styles
We can now mark an element as needing an "inherited style update" rather
than a full "style update". This effectively means that the next style
update will visit the element and pull all of its inherited properties
from the relevant ancestor element.

This is now used for descendants of elements with animated style.
2024-12-23 17:05:09 +01:00
Andreas Kling
92ac702c0c LibWeb: Always note whether a CSS property was inherited
This will be relevant when we start recomputing inherited style only.
2024-12-23 17:05:09 +01:00
Sam Atkins
349caecc18 LibWeb/CSS: Use fetch for CSS import rules
This still has a few FIXMEs, but it's a ResourceLoader use gone! :^)
2024-12-22 12:30:09 +01:00
Sam Atkins
ae943965dc LibWeb/CSS: Implement "fetch a style resource" algorithm 2024-12-22 12:30:09 +01:00
Sam Atkins
00948c4746 LibWeb/CSS: Expose CSSStyleSheet's origin clean flag 2024-12-22 12:30:09 +01:00
Andreas Kling
74469a0c1f LibWeb: Make CSS::ComputedProperties GC-allocated 2024-12-22 10:12:49 +01:00
Andreas Kling
c1cad8fa0e LibWeb: Rename CSS::StyleProperties => CSS::ComputedProperties
Now that StyleProperties is only used to hold computed properties, let's
name it ComputedProperties.
2024-12-22 10:12:49 +01:00
Andreas Kling
ed7f4664c2 LibWeb: Split StyleComputer work into two phases with separate outputs
Before this change, StyleComputer would essentially take a DOM element,
find all the CSS rules that apply to it, and resolve the computed value
for each CSS property for that element.

This worked great, but it meant we had to do all the work of selector
matching and cascading every time.

To enable new optimizations, this change introduces a break in the
middle of this process where we've produced a "CascadedProperties".
This object contains the result of the cascade, before we've begun
turning cascaded values into computed values.

The cascaded properties are now stored with each element, which will
later allow us to do partial updates without re-running the full
StyleComputer machine. This will be particularly valuable for
re-implementing CSS inheritance, which is extremely heavy today.

Note that CSS animations and CSS transitions operate entirely on the
computed values, even though the cascade order would have you believe
they happen earlier. I'm not confident we have the right architecture
for this, but that's a separate issue.
2024-12-22 10:12:49 +01:00
Jelle Raaijmakers
a7c75f6fdb LibWeb: Update CSS resolved values spec link to editor's draft URL 2024-12-21 19:15:58 +01:00
Sam Atkins
eb11c35640 LibWeb/CSS: Use CSSNumericType for CalculationResult's numeric type
When we originally implemented calc(), the result of a calculation was
guaranteed to be a single CSS type like a Length or Angle. However, CSS
Values 4 now allows more complex type arithmetic, which is represented
by the CSSNumericType class. Using that directly makes us more correct,
and allows us to remove a large amount of now ad-hoc code.

Unfortunately this is a large commit but the changes it makes are
interconnected enough that doing one at a time causes test
regressions.

In no particular order:

- Update our "determine the type of a calculation" code to match the
  newest spec, which sets percent hints in a couple more cases. (One of
  these we're skipping for now, I think it fails because of the FIXMEs
  in CSSNumericType::matches_foo().)
- Make the generated math-function-parsing code aware of the difference
  between arguments being the same type, and being "consistent" types,
  for each function. Otherwise those extra percent hints would cause
  them to fail validation incorrectly.
- Use the CSSNumericType as the type for the CalculationResult.
- Calculate and assign each math function's type in its constructor,
  instead of calculating it repeatedly on-demand.

The `CalculationNode::resolved_type()` method is now entirely unused and
has been removed.
2024-12-21 18:14:28 +01:00
Sam Atkins
8d40550478 LibWeb/CSS: Bring CSSNumericType algorithms up to date with spec
Took the opportunity to pull out a helper function for
entry_with_value_1_while_all_others_are_0(), too.

A couple of these require us to have extra contextual information about
what type percentages should resolve to. Until we have that available,
these are left as FIXMEs with a rough approximation.
2024-12-21 18:14:28 +01:00
Sam Atkins
0d19007cb5 LibWeb/CSS: Make CSSNumericType dump() infallible
This is a remnant of the tiny-OOM-propagation party.
2024-12-21 18:14:28 +01:00
Sam Atkins
9cbd08a330 LibWeb/CSS: Implement "consistent type" concept on CSSNumericType 2024-12-21 18:14:28 +01:00
Sam Atkins
2192868a0e LibWeb/CSS: Remove unused ProductOperation enum 2024-12-21 18:14:28 +01:00
Sam Atkins
0149f7d4e4 LibWeb/CSS: Remove unnecessary CalculatedStyleValue const-casts 2024-12-21 18:14:28 +01:00
Sam Atkins
69a0f28d04 Revert "LibWeb/CSS: Rename CalculatedStyleValue -> CSSMathValue"
This reverts commit 76daba3069.

We're going to need separate types for the JS-exposed style values, so
it doesn't make sense for us to match their names with our internal
types.
2024-12-21 18:14:28 +01:00
Sam Atkins
28388f1fd2 LibWeb/CSS: Don't overwrite active font load when requesting a pt size
start_loading_next_url() is a no-op if there's a pending resource load,
but not if that resource load has successfully loaded already. There is
a delay between the font resource loading, and it being processed into
a vector font. Calling font_with_point_size() in that gap would
previously erase the previously-loaded font, if the font had multiple
URLs to choose from.

This fixes the icon font on mods.factorio.com :^)
2024-12-20 18:19:37 +01:00
Totto16
d21bfda900 LibWeb: Handle special cases of PseudoElement::Type correctly
There are some special values for CSS::Selector::PseudoElement::Type
which are after `KnownPseudoElementCount` and therefore not present in
various arrays of pseudo elements, this leads to some errors, if a type
after `KnownPseudoElementCount` is used without checking first. This
adds explicit checks to all usages
2024-12-19 19:35:57 +00:00
Lucien Fiorini
9fd1223992 LibWeb+LibGfx: Refactor CSS filters into LibGfx
CSS filters work similarly to canvas filters, so it makes sense to have
Gfx::Filter that can be used by both libraries in an analogous way
as Gfx::Color.
2024-12-18 18:54:20 +01:00
Sam Atkins
6969d1eba3 LibWeb/CSS: Parse calc() as intermediate types instead of UnparsedCN
Previously we created a tree of CalculationNodes with dummy
UnparsedCalculationNode children, and then swapped those with the real
children. This matched the spec closely but had the unfortunate
downside that CalculationNodes couldn't be immutable, and couldn't know
their properties at construct-time. UnparsedCalculationNode is also a
footgun, as if it gets left in the tree accidentally we would VERIFY().

So instead, let's parse the calc() tree into an intermediate format, and
then convert each node in that tree, depth-first, into its
corresponding CalculationNode. This means each CalculationNode knows
what its children are when it is constructed, and they never change.

Apart from deleting UnparsedCalculationNode, we can also get rid of the
for_each_child_node() method that was only used by this "replace the
children" code.
2024-12-18 12:21:22 +00:00
Sam Atkins
cef1cb6aa7 LibWeb/CSS: Add Parser::Dimension::to_string()
This will be used when printing out unsupported dimensions inside calc,
for a more useful error message.
2024-12-18 12:21:22 +00:00
Johan Dahlin
6fd7b9b6b9 LibWeb: Render otf fonts
This is required by WPT tests so we can validate the OpenType/features
are properly implemented.
2024-12-17 19:07:13 +01:00
Johan Dahlin
1c42d6831b LibWeb: Style font-variant-* css properties 2024-12-17 19:07:13 +01:00
Johan Dahlin
aabbe87628 LibWeb: Parse font-variant-* css properties 2024-12-17 19:07:13 +01:00
Johan Dahlin
8bd94e2593 LibWeb: Add font-variant-* css properties 2024-12-17 19:07:13 +01:00
Lucas CHOLLET
3c60510896 LibWeb/CSS: Correctly serialize the colorspace name of xyz and xyz-d65
This gives us a +40 subtests passes in:
 - css/css-color/parsing/color-valid-color-function.html
2024-12-14 07:43:48 +00:00
Sam Atkins
e318316af7 LibWeb/CSS: Add missing parameter to CSSStyleValue::to_string() calls 2024-12-13 08:23:56 -08:00