/src/serenity/Userland/Libraries/LibWeb/Layout/SVGSVGBox.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org> |
3 | | * Copyright (c) 2022-2024, Andreas Kling <andreas@ladybird.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <LibWeb/CSS/Parser/Parser.h> |
9 | | #include <LibWeb/CSS/StyleValues/LengthStyleValue.h> |
10 | | #include <LibWeb/Layout/ReplacedBox.h> |
11 | | #include <LibWeb/Layout/SVGGeometryBox.h> |
12 | | #include <LibWeb/Painting/SVGSVGPaintable.h> |
13 | | |
14 | | namespace Web::Layout { |
15 | | |
16 | | JS_DEFINE_ALLOCATOR(SVGSVGBox); |
17 | | |
18 | | SVGSVGBox::SVGSVGBox(DOM::Document& document, SVG::SVGSVGElement& element, NonnullRefPtr<CSS::StyleProperties> properties) |
19 | 0 | : ReplacedBox(document, element, move(properties)) |
20 | 0 | { |
21 | 0 | } |
22 | | |
23 | | JS::GCPtr<Painting::Paintable> SVGSVGBox::create_paintable() const |
24 | 0 | { |
25 | 0 | return Painting::SVGSVGPaintable::create(*this); |
26 | 0 | } |
27 | | |
28 | | void SVGSVGBox::prepare_for_replaced_layout() |
29 | 0 | { |
30 | | // https://www.w3.org/TR/SVG2/coords.html#SizingSVGInCSS |
31 | | |
32 | | // The intrinsic dimensions must also be determined from the width and height sizing properties. |
33 | | // If either width or height are not specified, the used value is the initial value 'auto'. |
34 | | // 'auto' and percentage lengths must not be used to determine an intrinsic width or intrinsic height. |
35 | |
|
36 | 0 | Optional<CSSPixels> natural_width; |
37 | 0 | if (auto width = dom_node().width_style_value_from_attribute(); width && width->is_length() && width->as_length().length().is_absolute()) { |
38 | 0 | natural_width = width->as_length().length().absolute_length_to_px(); |
39 | 0 | } |
40 | |
|
41 | 0 | Optional<CSSPixels> natural_height; |
42 | 0 | if (auto height = dom_node().height_style_value_from_attribute(); height && height->is_length() && height->as_length().length().is_absolute()) { |
43 | 0 | natural_height = height->as_length().length().absolute_length_to_px(); |
44 | 0 | } |
45 | | |
46 | | // The intrinsic aspect ratio must be calculated using the following algorithm. If the algorithm returns null, then there is no intrinsic aspect ratio. |
47 | 0 | auto natural_aspect_ratio = [&]() -> Optional<CSSPixelFraction> { |
48 | | // 1. If the width and height sizing properties on the ‘svg’ element are both absolute values: |
49 | 0 | if (natural_width.has_value() && natural_height.has_value()) { |
50 | 0 | if (natural_width != 0 && natural_height != 0) { |
51 | | // 1. return width / height |
52 | 0 | return *natural_width / *natural_height; |
53 | 0 | } |
54 | 0 | return {}; |
55 | 0 | } |
56 | | |
57 | | // FIXME: 2. If an SVG View is active: |
58 | | // FIXME: 1. let viewbox be the viewbox defined by the active SVG View |
59 | | // FIXME: 2. return viewbox.width / viewbox.height |
60 | | |
61 | | // 3. If the ‘viewBox’ on the ‘svg’ element is correctly specified: |
62 | 0 | if (dom_node().view_box().has_value()) { |
63 | | // 1. let viewbox be the viewbox defined by the ‘viewBox’ attribute on the ‘svg’ element |
64 | 0 | auto const& viewbox = dom_node().view_box().value(); |
65 | | |
66 | | // 2. return viewbox.width / viewbox.height |
67 | 0 | auto viewbox_width = CSSPixels::nearest_value_for(viewbox.width); |
68 | 0 | auto viewbox_height = CSSPixels::nearest_value_for(viewbox.height); |
69 | 0 | if (viewbox_width != 0 && viewbox_height != 0) |
70 | 0 | return viewbox_width / viewbox_height; |
71 | | |
72 | 0 | return {}; |
73 | 0 | } |
74 | | |
75 | | // 4. return null |
76 | 0 | return {}; |
77 | 0 | }(); |
78 | |
|
79 | 0 | set_natural_width(natural_width); |
80 | 0 | set_natural_height(natural_height); |
81 | 0 | set_natural_aspect_ratio(natural_aspect_ratio); |
82 | 0 | } |
83 | | |
84 | | } |