Commit Graph

288 Commits

Author SHA1 Message Date
Tim Ledbetter
f05bc7c0cd LibWeb: Implement dominant-baseline for SVG text
This property determines the default baseline used to align content
within the given box.
2026-02-26 09:23:23 +01:00
Luke Wilde
21713377e2 LibWeb: Paint SVG-in-img with a nested display list
This makes SVG-in-img appear sharp no matter the current
(pinch-to-)zoom level.
2026-02-24 19:13:23 +01:00
Aliaksandr Kalenik
d79fbd903d LibWeb: Cache parsed CSS values for SVG width/height attributes
width_style_value_from_attribute() and
height_style_value_from_attribute() were showing up as hot functions
when profiling YouTube Music. They call parse_css_value() on every
invocation, but the underlying attributes rarely change. The call path
is SVGSVGBox::natural_size() → negotiate_natural_metrics() → these
functions, so they are invoked on every layout pass.
2026-02-22 16:09:15 +01:00
Andreas Kling
395a126110 LibWeb: Use cached bitmap in SVGDecodedImageData::paint()
Use the existing bitmap() method which caches the ImmutableBitmap,
instead of creating a fresh snapshot from the painting surface on
every paint call.

This was regressed by d9e04ec9e8 which replaced draw_painting_surface
with a per-call snapshot to remove the DrawPaintingSurface dependency,
but didn't use the existing bitmap cache.
2026-02-22 14:22:51 +01:00
Aliaksandr Kalenik
e87fece8c6 LibWeb: Force position:static on non-root SVG elements
SVG elements (except the outermost <svg>) use SVG's coordinate system,
not the CSS box model, so CSS positioning doesn't apply to them.

This adds SVGElement::adjust_computed_style() to force position:static
on all SVG elements except the outermost <svg> element (which has no
owner_svg_element()). SVGSymbolElement's existing override now calls
Base::adjust_computed_style() to inherit this behavior.

With this in place, the FIXME in layout_absolutely_positioned_element()
for SVG boxes becomes unreachable and is replaced with
VERIFY_NOT_REACHED().
2026-02-21 05:12:55 +01:00
Aliaksandr Kalenik
d9e04ec9e8 LibWeb: Snapshot SVG surface into ImmutableBitmap before painting
The last consumer of draw_painting_surface now snapshots the surface
into an ImmutableBitmap and uses draw_scaled_immutable_bitmap instead,
removing the final dependency on DrawPaintingSurface.
2026-02-20 18:41:33 +01:00
Luke Wilde
fc13f15193 LibWeb/CSP: Apply strict-dynamic to inline scripts
This implements https://github.com/w3c/webappsec-csp/pull/787 that
fixed the linked spec issue.
2026-02-19 14:58:09 +01:00
Callum Law
b8f2989ccb LibWeb: Reduce recompilation from editing CascadedProperties.h
This reduces the recompilation of editing `Properties.json` from ~1429
to ~158
2026-02-19 11:27:06 +00:00
Callum Law
f0434655f9 LibWeb: Reduce recompilation from editing Enums.json
Reduces the recompilation caused by editing `Enums.json` from ~1528 to
~327
2026-02-19 11:27:06 +00:00
Timothy Flynn
ea32502947 Everywhere: Run clang-format
The following command was used to clang-format these files:

    clang-format-21 -i $(find . \
        -not \( -path "./\.*" -prune \) \
        -not \( -path "./Build/*" -prune \) \
        -not \( -path "./Toolchain/*" -prune \) \
        -type f -name "*.cpp" -o -name "*.mm" -o -name "*.h")
2026-02-18 08:02:45 -05:00
Sam Atkins
44cbdc34fa LibWeb: Make StyleElementUtils into a base class, StyleElementBase
This will allow us to cast an Element to a StyleElementBase without
having to know whether it's an HTML or SVG style element.
2026-02-12 16:23:12 +01:00
Callum Law
e8354fed48 LibWeb: Avoid use of NumberOrCalculated for stroke-dasharray
This is already fully absolutized as part of the computation process so
we can resolve it in `ComputedProperties::stroke_dasharray` instead of
persisting it as a `NumberOrCalculated`
2026-02-12 10:26:43 +00:00
Psychpsyo
dab742ed84 Everywhere: Remove double // on comments 2026-02-11 13:28:01 -06:00
Aliaksandr Kalenik
fde2015846 LibWeb: Reduce recompilation impact of DOM/Element.h
Remove unused/redundant includes from Element.h:
- AK/IterationDecision.h (redundant)
- ARIA/AttributeNames.h (redundant via ARIAMixin.h)
- CSS/CascadedProperties.h (redundant via PseudoElement.h)
- CSS/StylePropertyMapReadOnly.h (pointer types only)
- HTML/LazyLoadingElement.h (unused in header)

Extract IntersectionObserverRegistration struct from
IntersectionObserver.h into its own lightweight header.
This breaks the heavy transitive include chain through
IntersectionObserverEntry.h and Geometry/DOMRect.h that
was pulled into every file including Element.h.

Indirect recompilation impact reductions:
- IntersectionObserver.h: ~1387 -> ~27 files
- LazyLoadingElement.h: ~1387 -> ~1002 files
2026-02-11 20:02:28 +01:00
Aliaksandr Kalenik
30e4779acb AK+LibWeb: Reduce recompilation impact of DOM/Node.h
Remove includes from Node.h that are only needed for forward
declarations (AccessibilityTreeNode.h, XMLSerializer.h,
JsonObjectSerializer.h). Extract StyleInvalidationReason and
FragmentSerializationMode enums into standalone lightweight
headers so downstream headers (CSSStyleSheet.h, CSSStyleProperties.h,
HTMLParser.h) can include just the enum they need instead of all of
Node.h. Replace Node.h with forward declarations in headers that only
use Node by pointer/reference.

This breaks the circular dependency between Node.h and
AccessibilityTreeNode.h, reducing AccessibilityTreeNode.h's
recompilation footprint from ~1399 to ~25 files.
2026-02-11 20:02:28 +01:00
Luke Wilde
e9f5df2131 LibWeb/SVG: Implement the feTurbulence filter 2026-02-11 09:39:39 +01:00
Luke Wilde
a89b02e5c3 LibWeb/SVG: Implement SVGAnimatedInteger
This is basically the same as SVGAnimatedNumber, but stores an i32
instead.
2026-02-11 09:39:39 +01:00
Aliaksandr Kalenik
aa24da8a93 LibWeb: Only invalidate layout on SVG viewBox/preserveAspectRatio change
These attributes are consumed during layout in SVGFormattingContext to
compute the viewbox transform. They don't affect the layout tree
structure, so a layout-only invalidation is sufficient instead of a
full layout tree rebuild.
2026-02-09 19:49:10 +01:00
Aliaksandr Kalenik
1f0f427a3c LibWeb: Remove Document.h include from XMLDocumentBuilder.h
...and SVGDecodedImageData.h

These headers only use Document via forward-declarable references and
smart pointers. Add explicit Document.h includes to .cpp files that
were relying on the transitive include.
2026-02-08 18:51:13 +01:00
Aliaksandr Kalenik
edf42ec9f9 LibWeb: Remove Document.h include from SVGElement.h
This reduces the recompilation cascade when Document.h is modified,
cutting off the transitive path through ~30 SVG element headers.

Move the inline try_resolve_url_to() template body in
SVGGraphicsElement.h to a non-template helper in the .cpp file to
avoid needing Document.h and ShadowRoot.h in the header.

Add explicit includes to files that relied on the transitive dependency.
2026-02-08 18:51:13 +01:00
Aliaksandr Kalenik
488123c75b LibWeb: Don't rebuild layout tree on SVG transform change
The SVG `transform` attribute is stored on the DOM element and read
directly during layout by
`SVGFormattingContext::layout_graphics_element()`. Since changing the
transform doesn't affect which DOM nodes produce layout boxes or how
they're structured, we only need to re-run layout on the existing tree
instead of rebuild it from scratch.
2026-02-07 15:47:17 +01:00
Aliaksandr Kalenik
076726a990 LibWeb: Invalidate layout when SVGPolylineElement attributes change
SVGPolylineElement::get_path() produces a path based on the points
attribute. During layout, this path is copied into paintables. If the
points attribute changes after layout, the path stored in the paintable
becomes stale. Fix by calling set_needs_layout_update() when it changes
so the path is recomputed.
2026-02-05 15:43:41 +01:00
Aliaksandr Kalenik
00fe4a2946 LibWeb: Invalidate layout when SVGPolygonElement attributes change
SVGPolygonElement::get_path() produces a path based on the points
attribute. During layout, this path is copied into paintables. If the
points attribute changes after layout, the path stored in the paintable
becomes stale. Fix by calling set_needs_layout_update() when it changes
so the path is recomputed.
2026-02-05 15:43:41 +01:00
Aliaksandr Kalenik
317075e8b0 LibWeb: Invalidate layout when SVGPathElement attributes change
SVGPathElement::get_path() produces a path based on the d attribute.
During layout, this path is copied into paintables. If the d attribute
changes after layout, the path stored in the paintable becomes stale.
Fix by calling set_needs_layout_update() when it changes so the path
is recomputed.
2026-02-05 15:43:41 +01:00
Aliaksandr Kalenik
c4bdbfbec5 LibWeb: Invalidate layout when SVGLineElement attributes change
SVGLineElement::get_path() produces a path based on x1, y1, x2, and
y2 attributes. During layout, this path is copied into paintables.
If any of these attributes change after layout, the path stored in the
paintable becomes stale. Fix by calling set_needs_layout_update() when
a geometry attribute changes so the path is recomputed.
2026-02-05 15:43:41 +01:00
Sam Atkins
2994a7532d LibWeb: Make shadow_including_first_ancestor_of_type() use the flat tree
Every user of this actually wants an ancestor in the flat tree - taking
things like `<slot>` into account. So rename it and adjust its behavior
to use that.
2026-02-05 11:21:08 +01:00
Aliaksandr Kalenik
e190f3ec23 LibWeb: Compute SVG mask/clip transforms using layout tree hierarchy
No observable behavior change — this is a refactoring of how SVG
transforms are computed for mask and clip content.

Previously, SVGGraphicsElement::get_transform() computed accumulated
transforms by walking the DOM tree. This didn't work correctly for masks
and clips because their DOM structure differs from layout: in the DOM,
mask/clip elements are siblings or ancestors of their targets, but in
the layout tree they become children of the target element. Walking the
DOM tree caused transforms from the target's ancestors to incorrectly
leak into mask/clip content.

The fix walks the layout tree instead of the DOM tree, which means
transform computation must happen during layout (where we have access to
the layout tree structure) rather than on-demand from the DOM element.
This moves the logic to SVGFormattingContext and removes get_transform()
since it can no longer serve its purpose — the DOM element only provides
element_transform() for its own transform now.

During layout, we walk up the layout tree and stop at mask/clip
boundaries, ensuring mask/clip content stays in its own coordinate
space. The target's accumulated transform is applied separately at paint
time.
2026-02-05 09:00:56 +01:00
Psychpsyo
b8b0522cdc LibWeb: Apply base presentational hints across the board 2026-02-04 20:21:36 +01:00
Callum Law
f13e0bb8a5 LibWeb: Replace ComputedProperties::length_percentage
Since we now clamp values as part of interpolation (96b628f) this
function is equivalent to `LengthPercentage::from_style_value`
2026-02-03 10:33:04 +00:00
Jonathan Gamble
b8ee6ec476 LibWeb: Use SizeWithAspectRatio struct 2026-02-02 14:36:49 +00:00
Tim Ledbetter
73fcbb0666 LibWeb: Add a flag for UA internal shadow roots 2026-02-02 12:28:05 +00:00
Andreas Kling
91cf575b82 LibWeb: Disable script execution for SVG images loaded via <img>
SVG images loaded as <img> elements must not execute scripts per spec.
Previously, SVGScriptElement::process_the_script_element() did not
check whether scripting was disabled, so script processing was
triggered via the children_changed() callback during XML parsing,
causing a nested event loop spin.

Fix this by:
- Disabling scripting on the SVG image's Page
- Passing XMLScriptingSupport::Disabled to the XML document builder
- Checking is_scripting_disabled() in SVGScriptElement before
  processing any script element
- Logging a diagnostic when SVG XML parsing fails (previously the
  parse result was silently discarded)
2026-02-01 22:48:51 +01:00
Ben Eidson
7f9de62cb1 LibWeb/SVG: Fix typo in replace_item
Change FIXNE to FIXME.
2026-01-22 01:29:30 +00:00
Shannon Booth
e1171618d4 LibWeb/SVG: Detect invalid circular reference for <use> elements
Previously, referencing an element that eventually pointed back to
the original <use> element would cause a stack overflow.

We now look at the referenced element and follow every <use> element
in its subtree and aim to detect any duplicates. If so, we consider
that referenced element invalid.
2026-01-21 22:26:14 +01:00
Luke Wilde
babfd70ca7 LibGC: Enforce that a Cell type must declare the allocator to use
This ensures that we are explicitly declaring the allocator to use when
allocating a cell(-inheriting) type, instead of silently falling back
to size-based allocation.

Since this is done in allocate_cell, this will only be detected for
types that are actively being allocated. However, since that means
they're _not_ being allocated, that means it's safe to not declare
an allocator to use for those. For example, the base TypedArray<T>,
which is never directly allocated and only the defined specializations
are ever allocated.
2026-01-20 12:00:11 +01:00
Adam Colvin
3a6d82245b LibWeb: Implement Screen.isExtended attribute
- Add WindowManagement to PolicyControlledFeature enum
- Add screen_count() virtual method to PageClient
- Store all screen rects in WebContent::PageClient, derive both
  screen_rect() and screen_count() from stored data
- Implement screen_count() overrides in SVGPageClient and PageHost
- Replace FIXME stub in Screen.cpp with spec-compliant implementation
2026-01-16 20:34:58 +01:00
aplefull
4608987da9 LibWeb: Resolve SVG url() references in shadow root scope 2026-01-15 11:06:22 +00:00
Andreas Kling
a64ea670fd LibWeb: Fix excessive recursion when removing SVG elements from use tree
When an SVGElement is removed from a <use> element's shadow tree, we
need to check if it was in a use element's shadow root to avoid
notifying use elements about the removal of their own clones.

The check was incorrectly using root() instead of old_root. Since the
element has already been detached when removed_from() is called,
root() no longer returns the shadow root, causing the early-return
check to fail.

This led to O(n) recursion depth when clearing a use element's shadow
tree, as each removed clone would trigger another round of
remove_all_children() on use elements referencing the same ID.
2026-01-14 11:46:23 +01:00
Tim Ledbetter
94fa08dcfe LibWeb/SVG: Implement activation behavior for SVGAElement
This makes navigation work when clicking on SVG `<a>` elements.
2026-01-13 10:05:40 +01:00
Jonathan Gamble
fc22c9ea38 LibWeb+WebContent: Allow WebContent to disentangle zoom from css pixels
So Ladybird can paint scrollbar & resizer chrome at the same size
regardless of zoom level while still respecting device pixel ratio
2026-01-12 11:00:14 +00:00
Shannon Booth
71cfc859f9 LibWeb/SVG: Implement <feDropShadow> filter integration 2026-01-11 13:14:40 +01:00
Shannon Booth
40b490a6a2 LibWeb/SVG: Implement SVGFEDropShadowElement IDL interface 2026-01-11 13:14:40 +01:00
Shannon Booth
cf66b3f5d6 LibWeb/SVG: Don't handle null computed properties in SVGFEFloodElement
This should (as far as I understand) never be called in a situation
where this is null.
2026-01-11 13:14:40 +01:00
Shannon Booth
7a309dd9e2 LibWeb/SVG: Use angle includes in SVGFECompositeElement
For consistency.
2026-01-11 13:14:40 +01:00
Shannon Booth
ddda4b7a3f LibWeb/SVG: Fix typo of double slash comment 2026-01-11 13:14:40 +01:00
sideshowbarker
1b41659efd LibXML+LibWeb: Use existing HTML entities table for XML parsing too
For XHTML documents, resolve named character entities (e.g., &nbsp;)
using the HTML entity table via a getEntity SAX callback. This avoids
parsing a large embedded DTD on every document and matches the approach
used by Blink and WebKit.

This also removes the now-unused DTD infrastructure:

- Remove resolve_external_resource callback from Parser::Options
- Remove resolve_xml_resource() function and its ~60KB embedded DTD
- Remove all call sites passing the unused callback
2026-01-09 19:13:41 +00:00
Luke Wilde
72083425d0 LibWeb: Always render SVGs onto a painting surface
This allows us to render SVGs on the GPU even when requesting a bitmap.
Since SVG bitmaps are an ImmutableBitmap, it can store a painting
surface snapshot, so we don't need to render bitmaps on the CPU.

Fixes Shopify homepage freezing for ~20 seconds rendering an SVG
background-image on the CPU on my machine.
2026-01-05 15:56:15 +01:00
Aliaksandr Kalenik
defbd0ec05 LibWeb/SVG: Percent-decode same-document <use> href fragments
`SVGUseElement::referenced_element()` previously passed
`m_href->fragment()` directly to `Document::get_element_by_id()`. URL
fragments are stored in their serialized form, so references to elements
whose IDs contain non-ASCII characters would fail to resolve.
2025-12-23 00:11:42 +01:00
Andreas Kling
9e5ce016d5 LibWeb: Add fast_is<T>() for variously commonly-checked DOM node types 2025-12-20 09:13:19 -06:00
InvalidUsernameException
28ba610f32 Everywhere: Avoid large rebuilds when editing (Immutable)Bitmap headers
This reduces the number of recompiled files as follow:
- Bitmap.h: 1309 -> 101
- ImmutableBitmap.h: 1218 -> 75
2025-11-28 18:32:48 +01:00