Serenity Operating System
at master 112 lines 4.2 kB view raw
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/SVG/AttributeNames.h> 9#include <LibWeb/SVG/AttributeParser.h> 10#include <LibWeb/SVG/SVGCircleElement.h> 11 12namespace Web::SVG { 13 14SVGCircleElement::SVGCircleElement(DOM::Document& document, DOM::QualifiedName qualified_name) 15 : SVGGeometryElement(document, qualified_name) 16{ 17} 18 19JS::ThrowCompletionOr<void> SVGCircleElement::initialize(JS::Realm& realm) 20{ 21 MUST_OR_THROW_OOM(Base::initialize(realm)); 22 set_prototype(&Bindings::ensure_web_prototype<Bindings::SVGCircleElementPrototype>(realm, "SVGCircleElement")); 23 24 return {}; 25} 26 27void SVGCircleElement::parse_attribute(DeprecatedFlyString const& name, DeprecatedString const& value) 28{ 29 SVGGeometryElement::parse_attribute(name, value); 30 31 if (name == SVG::AttributeNames::cx) { 32 m_center_x = AttributeParser::parse_coordinate(value); 33 m_path.clear(); 34 } else if (name == SVG::AttributeNames::cy) { 35 m_center_y = AttributeParser::parse_coordinate(value); 36 m_path.clear(); 37 } else if (name == SVG::AttributeNames::r) { 38 m_radius = AttributeParser::parse_positive_length(value); 39 m_path.clear(); 40 } 41} 42 43Gfx::Path& SVGCircleElement::get_path() 44{ 45 if (m_path.has_value()) 46 return m_path.value(); 47 48 float cx = m_center_x.value_or(0); 49 float cy = m_center_y.value_or(0); 50 float r = m_radius.value_or(0); 51 52 Gfx::Path path; 53 54 // A zero radius disables rendering. 55 if (r == 0) { 56 m_path = move(path); 57 return m_path.value(); 58 } 59 60 bool large_arc = false; 61 bool sweep = true; 62 63 // 1. A move-to command to the point cx+r,cy; 64 path.move_to({ cx + r, cy }); 65 66 // 2. arc to cx,cy+r; 67 path.arc_to({ cx, cy + r }, r, large_arc, sweep); 68 69 // 3. arc to cx-r,cy; 70 path.arc_to({ cx - r, cy }, r, large_arc, sweep); 71 72 // 4. arc to cx,cy-r; 73 path.arc_to({ cx, cy - r }, r, large_arc, sweep); 74 75 // 5. arc with a segment-completing close path operation. 76 path.arc_to({ cx + r, cy }, r, large_arc, sweep); 77 78 m_path = move(path); 79 return m_path.value(); 80} 81 82// https://www.w3.org/TR/SVG11/shapes.html#CircleElementCXAttribute 83JS::NonnullGCPtr<SVGAnimatedLength> SVGCircleElement::cx() const 84{ 85 // FIXME: Populate the unit type when it is parsed (0 here is "unknown"). 86 // FIXME: Create a proper animated value when animations are supported. 87 auto base_length = SVGLength::create(realm(), 0, m_center_x.value_or(0)).release_value_but_fixme_should_propagate_errors(); 88 auto anim_length = SVGLength::create(realm(), 0, m_center_x.value_or(0)).release_value_but_fixme_should_propagate_errors(); 89 return SVGAnimatedLength::create(realm(), move(base_length), move(anim_length)).release_value_but_fixme_should_propagate_errors(); 90} 91 92// https://www.w3.org/TR/SVG11/shapes.html#CircleElementCYAttribute 93JS::NonnullGCPtr<SVGAnimatedLength> SVGCircleElement::cy() const 94{ 95 // FIXME: Populate the unit type when it is parsed (0 here is "unknown"). 96 // FIXME: Create a proper animated value when animations are supported. 97 auto base_length = SVGLength::create(realm(), 0, m_center_y.value_or(0)).release_value_but_fixme_should_propagate_errors(); 98 auto anim_length = SVGLength::create(realm(), 0, m_center_y.value_or(0)).release_value_but_fixme_should_propagate_errors(); 99 return SVGAnimatedLength::create(realm(), move(base_length), move(anim_length)).release_value_but_fixme_should_propagate_errors(); 100} 101 102// https://www.w3.org/TR/SVG11/shapes.html#CircleElementRAttribute 103JS::NonnullGCPtr<SVGAnimatedLength> SVGCircleElement::r() const 104{ 105 // FIXME: Populate the unit type when it is parsed (0 here is "unknown"). 106 // FIXME: Create a proper animated value when animations are supported. 107 auto base_length = SVGLength::create(realm(), 0, m_radius.value_or(0)).release_value_but_fixme_should_propagate_errors(); 108 auto anim_length = SVGLength::create(realm(), 0, m_radius.value_or(0)).release_value_but_fixme_should_propagate_errors(); 109 return SVGAnimatedLength::create(realm(), move(base_length), move(anim_length)).release_value_but_fixme_should_propagate_errors(); 110} 111 112}