Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / svg / SVGEllipseElement.cpp
blobb81d4659159e9f20e701893044e64a4d16c599e0
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/SVGEllipseElement.h"
9 #include "mozilla/dom/SVGEllipseElementBinding.h"
10 #include "mozilla/dom/SVGLengthBinding.h"
11 #include "mozilla/gfx/2D.h"
12 #include "mozilla/gfx/PathHelpers.h"
13 #include "mozilla/RefPtr.h"
14 #include "SVGGeometryProperty.h"
16 NS_IMPL_NS_NEW_SVG_ELEMENT(Ellipse)
18 using namespace mozilla::gfx;
20 namespace mozilla::dom {
22 JSObject* SVGEllipseElement::WrapNode(JSContext* aCx,
23 JS::Handle<JSObject*> aGivenProto) {
24 return SVGEllipseElement_Binding::Wrap(aCx, this, aGivenProto);
27 SVGElement::LengthInfo SVGEllipseElement::sLengthInfo[4] = {
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::rx, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
33 SVGContentUtils::X},
34 {nsGkAtoms::ry, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
35 SVGContentUtils::Y},
38 //----------------------------------------------------------------------
39 // Implementation
41 SVGEllipseElement::SVGEllipseElement(
42 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
43 : SVGEllipseElementBase(std::move(aNodeInfo)) {}
45 bool SVGEllipseElement::IsAttributeMapped(const nsAtom* aAttribute) const {
46 return IsInLengthInfo(aAttribute, sLengthInfo) ||
47 SVGEllipseElementBase::IsAttributeMapped(aAttribute);
50 namespace SVGT = SVGGeometryProperty::Tags;
52 //----------------------------------------------------------------------
53 // nsINode methods
55 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGEllipseElement)
57 //----------------------------------------------------------------------
58 // nsIDOMSVGEllipseElement methods
60 already_AddRefed<DOMSVGAnimatedLength> SVGEllipseElement::Cx() {
61 return mLengthAttributes[CX].ToDOMAnimatedLength(this);
64 already_AddRefed<DOMSVGAnimatedLength> SVGEllipseElement::Cy() {
65 return mLengthAttributes[CY].ToDOMAnimatedLength(this);
68 already_AddRefed<DOMSVGAnimatedLength> SVGEllipseElement::Rx() {
69 return mLengthAttributes[RX].ToDOMAnimatedLength(this);
72 already_AddRefed<DOMSVGAnimatedLength> SVGEllipseElement::Ry() {
73 return mLengthAttributes[RY].ToDOMAnimatedLength(this);
76 //----------------------------------------------------------------------
77 // SVGElement methods
79 /* virtual */
80 bool SVGEllipseElement::HasValidDimensions() const {
81 float rx, ry;
83 if (SVGGeometryProperty::ResolveAll<SVGT::Rx, SVGT::Ry>(this, &rx, &ry)) {
84 return rx > 0 && ry > 0;
86 // This function might be called for an element in display:none subtree
87 // (e.g. SMIL animateMotion), we fall back to use SVG attributes.
88 bool hasRx = mLengthAttributes[RX].IsExplicitlySet();
89 bool hasRy = mLengthAttributes[RY].IsExplicitlySet();
90 if ((hasRx && mLengthAttributes[RX].GetAnimValInSpecifiedUnits() <= 0) ||
91 (hasRy && mLengthAttributes[RY].GetAnimValInSpecifiedUnits() <= 0)) {
92 return false;
94 return hasRx || hasRy;
97 SVGElement::LengthAttributesInfo SVGEllipseElement::GetLengthInfo() {
98 return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
99 ArrayLength(sLengthInfo));
102 //----------------------------------------------------------------------
103 // SVGGeometryElement methods
105 bool SVGEllipseElement::GetGeometryBounds(
106 Rect* aBounds, const StrokeOptions& aStrokeOptions,
107 const Matrix& aToBoundsSpace, const Matrix* aToNonScalingStrokeSpace) {
108 float x, y, rx, ry;
110 DebugOnly<bool> ok =
111 SVGGeometryProperty::ResolveAll<SVGT::Cx, SVGT::Cy, SVGT::Rx, SVGT::Ry>(
112 this, &x, &y, &rx, &ry);
113 MOZ_ASSERT(ok, "SVGGeometryProperty::ResolveAll failed");
115 if (rx <= 0.f || ry <= 0.f) {
116 // Rendering of the element is disabled
117 *aBounds = Rect(aToBoundsSpace.TransformPoint(Point(x, y)), Size());
118 return true;
121 if (aToBoundsSpace.IsRectilinear()) {
122 // Optimize the case where we can treat the ellipse as a rectangle and
123 // still get tight bounds.
124 if (aStrokeOptions.mLineWidth > 0.f) {
125 if (aToNonScalingStrokeSpace) {
126 if (aToNonScalingStrokeSpace->IsRectilinear()) {
127 MOZ_ASSERT(!aToNonScalingStrokeSpace->IsSingular());
128 Rect userBounds(x - rx, y - ry, 2 * rx, 2 * ry);
129 SVGContentUtils::RectilinearGetStrokeBounds(
130 userBounds, aToBoundsSpace, *aToNonScalingStrokeSpace,
131 aStrokeOptions.mLineWidth, aBounds);
132 return true;
134 return false;
136 rx += aStrokeOptions.mLineWidth / 2.f;
137 ry += aStrokeOptions.mLineWidth / 2.f;
139 Rect rect(x - rx, y - ry, 2 * rx, 2 * ry);
140 *aBounds = aToBoundsSpace.TransformBounds(rect);
141 return true;
144 return false;
147 already_AddRefed<Path> SVGEllipseElement::BuildPath(PathBuilder* aBuilder) {
148 float x, y, rx, ry;
150 if (!SVGGeometryProperty::ResolveAll<SVGT::Cx, SVGT::Cy, SVGT::Rx, SVGT::Ry>(
151 this, &x, &y, &rx, &ry)) {
152 // This function might be called for element in display:none subtree
153 // (e.g. getTotalLength), we fall back to use SVG attributes.
154 GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
157 if (rx <= 0.0f || ry <= 0.0f) {
158 return nullptr;
161 EllipseToBezier(aBuilder, Point(x, y), Size(rx, ry));
163 return aBuilder->Finish();
166 bool SVGEllipseElement::IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
167 const ComputedStyle& aOldStyle) {
168 const auto& newSVGReset = *aNewStyle.StyleSVGReset();
169 const auto& oldSVGReset = *aOldStyle.StyleSVGReset();
170 return newSVGReset.mCx != oldSVGReset.mCx ||
171 newSVGReset.mCy != oldSVGReset.mCy ||
172 newSVGReset.mRx != oldSVGReset.mRx ||
173 newSVGReset.mRy != oldSVGReset.mRy;
176 nsCSSPropertyID SVGEllipseElement::GetCSSPropertyIdForAttrEnum(
177 uint8_t aAttrEnum) {
178 switch (aAttrEnum) {
179 case CX:
180 return eCSSProperty_cx;
181 case CY:
182 return eCSSProperty_cy;
183 case RX:
184 return eCSSProperty_rx;
185 case RY:
186 return eCSSProperty_ry;
187 default:
188 MOZ_ASSERT_UNREACHABLE("Unknown attr enum");
189 return eCSSProperty_UNKNOWN;
193 } // namespace mozilla::dom