/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/SVGEllipseElement.h" #include "mozilla/dom/SVGEllipseElementBinding.h" #include "mozilla/gfx/2D.h" #include "mozilla/gfx/PathHelpers.h" #include "mozilla/RefPtr.h" NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Ellipse) using namespace mozilla::gfx; namespace mozilla { namespace dom { JSObject* SVGEllipseElement::WrapNode(JSContext *aCx) { return SVGEllipseElementBinding::Wrap(aCx, this); } nsSVGElement::LengthInfo SVGEllipseElement::sLengthInfo[4] = { { &nsGkAtoms::cx, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X }, { &nsGkAtoms::cy, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }, { &nsGkAtoms::rx, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X }, { &nsGkAtoms::ry, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }, }; //---------------------------------------------------------------------- // Implementation SVGEllipseElement::SVGEllipseElement(already_AddRefed& aNodeInfo) : SVGEllipseElementBase(aNodeInfo) { } //---------------------------------------------------------------------- // nsIDOMNode methods NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGEllipseElement) //---------------------------------------------------------------------- // nsIDOMSVGEllipseElement methods already_AddRefed SVGEllipseElement::Cx() { return mLengthAttributes[CX].ToDOMAnimatedLength(this); } already_AddRefed SVGEllipseElement::Cy() { return mLengthAttributes[CY].ToDOMAnimatedLength(this); } already_AddRefed SVGEllipseElement::Rx() { return mLengthAttributes[RX].ToDOMAnimatedLength(this); } already_AddRefed SVGEllipseElement::Ry() { return mLengthAttributes[RY].ToDOMAnimatedLength(this); } //---------------------------------------------------------------------- // nsSVGElement methods /* virtual */ bool SVGEllipseElement::HasValidDimensions() const { return mLengthAttributes[RX].IsExplicitlySet() && mLengthAttributes[RX].GetAnimValInSpecifiedUnits() > 0 && mLengthAttributes[RY].IsExplicitlySet() && mLengthAttributes[RY].GetAnimValInSpecifiedUnits() > 0; } nsSVGElement::LengthAttributesInfo SVGEllipseElement::GetLengthInfo() { return LengthAttributesInfo(mLengthAttributes, sLengthInfo, ArrayLength(sLengthInfo)); } //---------------------------------------------------------------------- // nsSVGPathGeometryElement methods bool SVGEllipseElement::GetGeometryBounds( Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform) { float x, y, rx, ry; GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr); if (rx <= 0.f || ry <= 0.f) { // Rendering of the element is disabled *aBounds = Rect(aTransform * Point(x, y), Size()); return true; } if (aTransform.IsRectilinear()) { // Optimize the case where we can treat the ellipse as a rectangle and // still get tight bounds. if (aStrokeOptions.mLineWidth > 0.f) { rx += aStrokeOptions.mLineWidth / 2.f; ry += aStrokeOptions.mLineWidth / 2.f; } Rect rect(x - rx, y - ry, 2 * rx, 2 * ry); *aBounds = aTransform.TransformBounds(rect); return true; } return false; } TemporaryRef SVGEllipseElement::BuildPath(PathBuilder* aBuilder) { float x, y, rx, ry; GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr); if (rx <= 0.0f || ry <= 0.0f) { return nullptr; } EllipseToBezier(aBuilder, Point(x, y), Size(rx, ry)); return aBuilder->Finish(); } } // namespace dom } // namespace mozilla