Line data Source code
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/. */
6 :
7 : #include "mozilla/dom/SVGEllipseElement.h"
8 : #include "mozilla/dom/SVGEllipseElementBinding.h"
9 : #include "mozilla/gfx/2D.h"
10 : #include "mozilla/gfx/PathHelpers.h"
11 : #include "mozilla/RefPtr.h"
12 :
13 0 : NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Ellipse)
14 :
15 : using namespace mozilla::gfx;
16 :
17 : namespace mozilla {
18 : namespace dom {
19 :
20 : JSObject*
21 0 : SVGEllipseElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
22 : {
23 0 : return SVGEllipseElementBinding::Wrap(aCx, this, aGivenProto);
24 : }
25 :
26 : nsSVGElement::LengthInfo SVGEllipseElement::sLengthInfo[4] =
27 : {
28 : { &nsGkAtoms::cx, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
29 : { &nsGkAtoms::cy, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
30 : { &nsGkAtoms::rx, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
31 : { &nsGkAtoms::ry, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
32 : };
33 :
34 : //----------------------------------------------------------------------
35 : // Implementation
36 :
37 0 : SVGEllipseElement::SVGEllipseElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
38 0 : : SVGEllipseElementBase(aNodeInfo)
39 : {
40 0 : }
41 :
42 : //----------------------------------------------------------------------
43 : // nsIDOMNode methods
44 :
45 0 : NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGEllipseElement)
46 :
47 : //----------------------------------------------------------------------
48 : // nsIDOMSVGEllipseElement methods
49 :
50 : already_AddRefed<SVGAnimatedLength>
51 0 : SVGEllipseElement::Cx()
52 : {
53 0 : return mLengthAttributes[CX].ToDOMAnimatedLength(this);
54 : }
55 :
56 : already_AddRefed<SVGAnimatedLength>
57 0 : SVGEllipseElement::Cy()
58 : {
59 0 : return mLengthAttributes[CY].ToDOMAnimatedLength(this);
60 : }
61 :
62 : already_AddRefed<SVGAnimatedLength>
63 0 : SVGEllipseElement::Rx()
64 : {
65 0 : return mLengthAttributes[RX].ToDOMAnimatedLength(this);
66 : }
67 :
68 : already_AddRefed<SVGAnimatedLength>
69 0 : SVGEllipseElement::Ry()
70 : {
71 0 : return mLengthAttributes[RY].ToDOMAnimatedLength(this);
72 : }
73 :
74 : //----------------------------------------------------------------------
75 : // nsSVGElement methods
76 :
77 : /* virtual */ bool
78 0 : SVGEllipseElement::HasValidDimensions() const
79 : {
80 0 : return mLengthAttributes[RX].IsExplicitlySet() &&
81 0 : mLengthAttributes[RX].GetAnimValInSpecifiedUnits() > 0 &&
82 0 : mLengthAttributes[RY].IsExplicitlySet() &&
83 0 : mLengthAttributes[RY].GetAnimValInSpecifiedUnits() > 0;
84 : }
85 :
86 : nsSVGElement::LengthAttributesInfo
87 0 : SVGEllipseElement::GetLengthInfo()
88 : {
89 : return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
90 0 : ArrayLength(sLengthInfo));
91 : }
92 :
93 : //----------------------------------------------------------------------
94 : // SVGGeometryElement methods
95 :
96 : bool
97 0 : SVGEllipseElement::GetGeometryBounds(Rect* aBounds,
98 : const StrokeOptions& aStrokeOptions,
99 : const Matrix& aToBoundsSpace,
100 : const Matrix* aToNonScalingStrokeSpace)
101 : {
102 : float x, y, rx, ry;
103 0 : GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
104 :
105 0 : if (rx <= 0.f || ry <= 0.f) {
106 : // Rendering of the element is disabled
107 0 : *aBounds = Rect(aToBoundsSpace.TransformPoint(Point(x, y)), Size());
108 0 : return true;
109 : }
110 :
111 0 : if (aToBoundsSpace.IsRectilinear()) {
112 : // Optimize the case where we can treat the ellipse as a rectangle and
113 : // still get tight bounds.
114 0 : if (aStrokeOptions.mLineWidth > 0.f) {
115 0 : if (aToNonScalingStrokeSpace) {
116 0 : if (aToNonScalingStrokeSpace->IsRectilinear()) {
117 0 : MOZ_ASSERT(!aToNonScalingStrokeSpace->IsSingular());
118 0 : Rect userBounds(x - rx, y - ry, 2 * rx, 2 * ry);
119 : SVGContentUtils::RectilinearGetStrokeBounds(
120 : userBounds, aToBoundsSpace, *aToNonScalingStrokeSpace,
121 0 : aStrokeOptions.mLineWidth, aBounds);
122 0 : return true;
123 : }
124 0 : return false;
125 : }
126 0 : rx += aStrokeOptions.mLineWidth / 2.f;
127 0 : ry += aStrokeOptions.mLineWidth / 2.f;
128 : }
129 0 : Rect rect(x - rx, y - ry, 2 * rx, 2 * ry);
130 0 : *aBounds = aToBoundsSpace.TransformBounds(rect);
131 0 : return true;
132 : }
133 :
134 0 : return false;
135 : }
136 :
137 : already_AddRefed<Path>
138 0 : SVGEllipseElement::BuildPath(PathBuilder* aBuilder)
139 : {
140 : float x, y, rx, ry;
141 0 : GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
142 :
143 0 : if (rx <= 0.0f || ry <= 0.0f) {
144 0 : return nullptr;
145 : }
146 :
147 0 : EllipseToBezier(aBuilder, Point(x, y), Size(rx, ry));
148 :
149 0 : return aBuilder->Finish();
150 : }
151 :
152 : } // namespace dom
153 : } // namespace mozilla
|