Bug 1700051: part 46) Const-qualify `mozInlineSpellStatus::mAnchorRange`. r=smaug
[gecko.git] / dom / svg / SVGCircleElement.cpp
blobb01fc342e47229bce0e84dd626508d0ee5bc326b
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ComputedStyle.h"
8 #include "mozilla/dom/SVGCircleElement.h"
9 #include "mozilla/gfx/2D.h"
10 #include "nsGkAtoms.h"
11 #include "mozilla/dom/SVGCircleElementBinding.h"
12 #include "mozilla/dom/SVGLengthBinding.h"
13 #include "SVGGeometryProperty.h"
15 NS_IMPL_NS_NEW_SVG_ELEMENT(Circle)
17 using namespace mozilla::gfx;
19 namespace mozilla {
20 namespace dom {
22 JSObject* SVGCircleElement::WrapNode(JSContext* aCx,
23 JS::Handle<JSObject*> aGivenProto) {
24 return SVGCircleElement_Binding::Wrap(aCx, this, aGivenProto);
27 SVGElement::LengthInfo SVGCircleElement::sLengthInfo[3] = {
28 {nsGkAtoms::cx, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
29 SVGContentUtils::X},
30 {nsGkAtoms::cy, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
31 SVGContentUtils::Y},
32 {nsGkAtoms::r, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
33 SVGContentUtils::XY}};
35 //----------------------------------------------------------------------
36 // Implementation
38 SVGCircleElement::SVGCircleElement(
39 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
40 : SVGCircleElementBase(std::move(aNodeInfo)) {}
42 bool SVGCircleElement::IsAttributeMapped(const nsAtom* aAttribute) const {
43 return IsInLengthInfo(aAttribute, sLengthInfo) ||
44 SVGCircleElementBase::IsAttributeMapped(aAttribute);
47 namespace SVGT = SVGGeometryProperty::Tags;
49 //----------------------------------------------------------------------
50 // nsINode methods
52 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGCircleElement)
54 //----------------------------------------------------------------------
56 already_AddRefed<DOMSVGAnimatedLength> SVGCircleElement::Cx() {
57 return mLengthAttributes[ATTR_CX].ToDOMAnimatedLength(this);
60 already_AddRefed<DOMSVGAnimatedLength> SVGCircleElement::Cy() {
61 return mLengthAttributes[ATTR_CY].ToDOMAnimatedLength(this);
64 already_AddRefed<DOMSVGAnimatedLength> SVGCircleElement::R() {
65 return mLengthAttributes[ATTR_R].ToDOMAnimatedLength(this);
68 //----------------------------------------------------------------------
69 // SVGElement methods
71 /* virtual */
72 bool SVGCircleElement::HasValidDimensions() const {
73 float r;
75 if (SVGGeometryProperty::ResolveAll<SVGT::R>(this, &r)) {
76 return r > 0;
78 // This function might be called for an element in display:none subtree
79 // (e.g. SMIL animateMotion), we fall back to use SVG attributes.
80 return mLengthAttributes[ATTR_R].IsExplicitlySet() &&
81 mLengthAttributes[ATTR_R].GetAnimValInSpecifiedUnits() > 0;
84 SVGElement::LengthAttributesInfo SVGCircleElement::GetLengthInfo() {
85 return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
86 ArrayLength(sLengthInfo));
89 //----------------------------------------------------------------------
90 // SVGGeometryElement methods
92 bool SVGCircleElement::GetGeometryBounds(
93 Rect* aBounds, const StrokeOptions& aStrokeOptions,
94 const Matrix& aToBoundsSpace, const Matrix* aToNonScalingStrokeSpace) {
95 float x, y, r;
97 DebugOnly<bool> ok =
98 SVGGeometryProperty::ResolveAll<SVGT::Cx, SVGT::Cy, SVGT::R>(this, &x, &y,
99 &r);
100 MOZ_ASSERT(ok, "SVGGeometryProperty::ResolveAll failed");
102 if (r <= 0.f) {
103 // Rendering of the element is disabled
104 *aBounds = Rect(aToBoundsSpace.TransformPoint(Point(x, y)), Size());
105 return true;
108 if (aToBoundsSpace.IsRectilinear()) {
109 // Optimize the case where we can treat the circle as a rectangle and
110 // still get tight bounds.
111 if (aStrokeOptions.mLineWidth > 0.f) {
112 if (aToNonScalingStrokeSpace) {
113 if (aToNonScalingStrokeSpace->IsRectilinear()) {
114 MOZ_ASSERT(!aToNonScalingStrokeSpace->IsSingular());
115 Rect userBounds(x - r, y - r, 2 * r, 2 * r);
116 SVGContentUtils::RectilinearGetStrokeBounds(
117 userBounds, aToBoundsSpace, *aToNonScalingStrokeSpace,
118 aStrokeOptions.mLineWidth, aBounds);
119 return true;
121 return false;
123 r += aStrokeOptions.mLineWidth / 2.f;
125 Rect rect(x - r, y - r, 2 * r, 2 * r);
126 *aBounds = aToBoundsSpace.TransformBounds(rect);
127 return true;
130 return false;
133 already_AddRefed<Path> SVGCircleElement::BuildPath(PathBuilder* aBuilder) {
134 float x, y, r;
135 if (!SVGGeometryProperty::ResolveAll<SVGT::Cx, SVGT::Cy, SVGT::R>(this, &x,
136 &y, &r)) {
137 // This function might be called for element in display:none subtree
138 // (e.g. getTotalLength), we fall back to use SVG attributes.
139 GetAnimatedLengthValues(&x, &y, &r, nullptr);
142 if (r <= 0.0f) {
143 return nullptr;
146 aBuilder->Arc(Point(x, y), r, 0, Float(2 * M_PI));
148 return aBuilder->Finish();
151 bool SVGCircleElement::IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
152 const ComputedStyle& aOldStyle) {
153 const auto& newSVGReset = *aNewStyle.StyleSVGReset();
154 const auto& oldSVGReset = *aOldStyle.StyleSVGReset();
156 return newSVGReset.mCx != oldSVGReset.mCx ||
157 newSVGReset.mCy != oldSVGReset.mCy || newSVGReset.mR != oldSVGReset.mR;
160 nsCSSPropertyID SVGCircleElement::GetCSSPropertyIdForAttrEnum(
161 uint8_t aAttrEnum) {
162 switch (aAttrEnum) {
163 case ATTR_CX:
164 return eCSSProperty_cx;
165 case ATTR_CY:
166 return eCSSProperty_cy;
167 case ATTR_R:
168 return eCSSProperty_r;
169 default:
170 MOZ_ASSERT_UNREACHABLE("Unknown attr enum");
171 return eCSSProperty_UNKNOWN;
175 } // namespace dom
176 } // namespace mozilla