/src/serenity/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <LibWeb/Bindings/Intrinsics.h> |
8 | | #include <LibWeb/Bindings/SVGCircleElementPrototype.h> |
9 | | #include <LibWeb/CSS/Parser/Parser.h> |
10 | | #include <LibWeb/Layout/Node.h> |
11 | | #include <LibWeb/SVG/AttributeNames.h> |
12 | | #include <LibWeb/SVG/AttributeParser.h> |
13 | | #include <LibWeb/SVG/SVGCircleElement.h> |
14 | | #include <LibWeb/SVG/SVGViewport.h> |
15 | | |
16 | | namespace Web::SVG { |
17 | | |
18 | | JS_DEFINE_ALLOCATOR(SVGCircleElement); |
19 | | |
20 | | SVGCircleElement::SVGCircleElement(DOM::Document& document, DOM::QualifiedName qualified_name) |
21 | 0 | : SVGGeometryElement(document, qualified_name) |
22 | 0 | { |
23 | 0 | } |
24 | | |
25 | | void SVGCircleElement::initialize(JS::Realm& realm) |
26 | 0 | { |
27 | 0 | Base::initialize(realm); |
28 | 0 | WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGCircleElement); |
29 | 0 | } |
30 | | |
31 | | void SVGCircleElement::apply_presentational_hints(CSS::StyleProperties& style) const |
32 | 0 | { |
33 | 0 | Base::apply_presentational_hints(style); |
34 | 0 | auto parsing_context = CSS::Parser::ParsingContext { document(), CSS::Parser::ParsingContext::Mode::SVGPresentationAttribute }; |
35 | |
|
36 | 0 | auto cx_attribute = attribute(SVG::AttributeNames::cx); |
37 | 0 | if (auto cx_value = parse_css_value(parsing_context, cx_attribute.value_or(String {}), CSS::PropertyID::Cx)) |
38 | 0 | style.set_property(CSS::PropertyID::Cx, cx_value.release_nonnull()); |
39 | |
|
40 | 0 | auto cy_attribute = attribute(SVG::AttributeNames::cy); |
41 | 0 | if (auto cy_value = parse_css_value(parsing_context, cy_attribute.value_or(String {}), CSS::PropertyID::Cy)) |
42 | 0 | style.set_property(CSS::PropertyID::Cy, cy_value.release_nonnull()); |
43 | |
|
44 | 0 | auto r_attribute = attribute(SVG::AttributeNames::r); |
45 | 0 | if (auto r_value = parse_css_value(parsing_context, r_attribute.value_or(String {}), CSS::PropertyID::R)) |
46 | 0 | style.set_property(CSS::PropertyID::R, r_value.release_nonnull()); |
47 | 0 | } |
48 | | |
49 | | Gfx::Path SVGCircleElement::get_path(CSSPixelSize viewport_size) |
50 | 0 | { |
51 | 0 | auto node = layout_node(); |
52 | 0 | auto cx = float(node->computed_values().cx().to_px(*node, viewport_size.width())); |
53 | 0 | auto cy = float(node->computed_values().cy().to_px(*node, viewport_size.height())); |
54 | | // Percentages refer to the normalized diagonal of the current SVG viewport |
55 | | // (see Units: https://svgwg.org/svg2-draft/coords.html#Units) |
56 | 0 | auto r = float(node->computed_values().r().to_px(*node, normalized_diagonal_length(viewport_size))); |
57 | | |
58 | | // A zero radius disables rendering. |
59 | 0 | if (r == 0) |
60 | 0 | return {}; |
61 | | |
62 | 0 | Gfx::Path path; |
63 | 0 | bool large_arc = false; |
64 | 0 | bool sweep = true; |
65 | | |
66 | | // 1. A move-to command to the point cx+r,cy; |
67 | 0 | path.move_to({ cx + r, cy }); |
68 | | |
69 | | // 2. arc to cx,cy+r; |
70 | 0 | path.arc_to({ cx, cy + r }, r, large_arc, sweep); |
71 | | |
72 | | // 3. arc to cx-r,cy; |
73 | 0 | path.arc_to({ cx - r, cy }, r, large_arc, sweep); |
74 | | |
75 | | // 4. arc to cx,cy-r; |
76 | 0 | path.arc_to({ cx, cy - r }, r, large_arc, sweep); |
77 | | |
78 | | // 5. arc with a segment-completing close path operation. |
79 | 0 | path.arc_to({ cx + r, cy }, r, large_arc, sweep); |
80 | |
|
81 | 0 | return path; |
82 | 0 | } |
83 | | |
84 | | // https://www.w3.org/TR/SVG11/shapes.html#CircleElementCXAttribute |
85 | | JS::NonnullGCPtr<SVGAnimatedLength> SVGCircleElement::cx() const |
86 | 0 | { |
87 | 0 | return svg_animated_length_for_property(CSS::PropertyID::Cx); |
88 | 0 | } |
89 | | |
90 | | // https://www.w3.org/TR/SVG11/shapes.html#CircleElementCYAttribute |
91 | | JS::NonnullGCPtr<SVGAnimatedLength> SVGCircleElement::cy() const |
92 | 0 | { |
93 | 0 | return svg_animated_length_for_property(CSS::PropertyID::Cy); |
94 | 0 | } |
95 | | |
96 | | // https://www.w3.org/TR/SVG11/shapes.html#CircleElementRAttribute |
97 | | JS::NonnullGCPtr<SVGAnimatedLength> SVGCircleElement::r() const |
98 | 0 | { |
99 | 0 | return svg_animated_length_for_property(CSS::PropertyID::R); |
100 | 0 | } |
101 | | |
102 | | } |