Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / svg / SVGMarkerElement.cpp
blob6b2e5499c6bbae096fe8deb97353eae0cd29fad8
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 "mozilla/dom/SVGMarkerElement.h"
9 #include "nsGkAtoms.h"
10 #include "DOMSVGAngle.h"
11 #include "SVGAnimatedPreserveAspectRatio.h"
12 #include "nsError.h"
13 #include "mozilla/ArrayUtils.h"
14 #include "mozilla/dom/SVGGeometryElement.h"
15 #include "mozilla/dom/SVGLengthBinding.h"
16 #include "mozilla/dom/SVGMarkerElementBinding.h"
17 #include "mozilla/gfx/Matrix.h"
18 #include "mozilla/FloatingPoint.h"
19 #include "mozilla/RefPtr.h"
20 #include "SVGContentUtils.h"
22 using namespace mozilla::gfx;
23 using namespace mozilla::dom::SVGMarkerElement_Binding;
25 NS_IMPL_NS_NEW_SVG_ELEMENT(Marker)
27 namespace mozilla::dom {
29 using namespace SVGAngle_Binding;
31 JSObject* SVGMarkerElement::WrapNode(JSContext* aCx,
32 JS::Handle<JSObject*> aGivenProto) {
33 return SVGMarkerElement_Binding::Wrap(aCx, this, aGivenProto);
36 SVGElement::LengthInfo SVGMarkerElement::sLengthInfo[4] = {
37 {nsGkAtoms::refX, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
38 SVGContentUtils::X},
39 {nsGkAtoms::refY, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
40 SVGContentUtils::Y},
41 {nsGkAtoms::markerWidth, 3, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
42 SVGContentUtils::X},
43 {nsGkAtoms::markerHeight, 3, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER,
44 SVGContentUtils::Y},
47 SVGEnumMapping SVGMarkerElement::sUnitsMap[] = {
48 {nsGkAtoms::strokeWidth, SVG_MARKERUNITS_STROKEWIDTH},
49 {nsGkAtoms::userSpaceOnUse, SVG_MARKERUNITS_USERSPACEONUSE},
50 {nullptr, 0}};
52 SVGElement::EnumInfo SVGMarkerElement::sEnumInfo[1] = {
53 {nsGkAtoms::markerUnits, sUnitsMap, SVG_MARKERUNITS_STROKEWIDTH}};
55 //----------------------------------------------------------------------
56 // Implementation
58 SVGMarkerElement::SVGMarkerElement(
59 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
60 : SVGMarkerElementBase(std::move(aNodeInfo)), mCoordCtx(nullptr) {}
62 //----------------------------------------------------------------------
63 // nsINode methods
65 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMarkerElement)
67 //----------------------------------------------------------------------
69 already_AddRefed<SVGAnimatedRect> SVGMarkerElement::ViewBox() {
70 return mViewBox.ToSVGAnimatedRect(this);
73 already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
74 SVGMarkerElement::PreserveAspectRatio() {
75 return mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(this);
78 //----------------------------------------------------------------------
80 already_AddRefed<DOMSVGAnimatedLength> SVGMarkerElement::RefX() {
81 return mLengthAttributes[REFX].ToDOMAnimatedLength(this);
84 already_AddRefed<DOMSVGAnimatedLength> SVGMarkerElement::RefY() {
85 return mLengthAttributes[REFY].ToDOMAnimatedLength(this);
88 already_AddRefed<DOMSVGAnimatedEnumeration> SVGMarkerElement::MarkerUnits() {
89 return mEnumAttributes[MARKERUNITS].ToDOMAnimatedEnum(this);
92 already_AddRefed<DOMSVGAnimatedLength> SVGMarkerElement::MarkerWidth() {
93 return mLengthAttributes[MARKERWIDTH].ToDOMAnimatedLength(this);
96 already_AddRefed<DOMSVGAnimatedLength> SVGMarkerElement::MarkerHeight() {
97 return mLengthAttributes[MARKERHEIGHT].ToDOMAnimatedLength(this);
100 already_AddRefed<DOMSVGAnimatedEnumeration> SVGMarkerElement::OrientType() {
101 return mOrient.ToDOMAnimatedEnum(this);
104 already_AddRefed<DOMSVGAnimatedAngle> SVGMarkerElement::OrientAngle() {
105 return mOrient.ToDOMAnimatedAngle(this);
108 void SVGMarkerElement::SetOrientToAuto() {
109 mOrient.SetBaseType(SVG_MARKER_ORIENT_AUTO, this, IgnoreErrors());
112 void SVGMarkerElement::SetOrientToAngle(DOMSVGAngle& aAngle) {
113 nsAutoString angle;
114 aAngle.GetValueAsString(angle);
115 mOrient.SetBaseValueString(angle, this, true);
118 //----------------------------------------------------------------------
119 // SVGElement methods
121 void SVGMarkerElement::SetParentCoordCtxProvider(SVGViewportElement* aContext) {
122 mCoordCtx = aContext;
123 mViewBoxToViewportTransform = nullptr;
126 /* virtual */
127 bool SVGMarkerElement::HasValidDimensions() const {
128 return (!mLengthAttributes[MARKERWIDTH].IsExplicitlySet() ||
129 mLengthAttributes[MARKERWIDTH].GetAnimValInSpecifiedUnits() > 0) &&
130 (!mLengthAttributes[MARKERHEIGHT].IsExplicitlySet() ||
131 mLengthAttributes[MARKERHEIGHT].GetAnimValInSpecifiedUnits() > 0);
134 SVGElement::LengthAttributesInfo SVGMarkerElement::GetLengthInfo() {
135 return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
136 std::size(sLengthInfo));
139 SVGElement::EnumAttributesInfo SVGMarkerElement::GetEnumInfo() {
140 return EnumAttributesInfo(mEnumAttributes, sEnumInfo, std::size(sEnumInfo));
143 SVGAnimatedOrient* SVGMarkerElement::GetAnimatedOrient() { return &mOrient; }
145 SVGAnimatedViewBox* SVGMarkerElement::GetAnimatedViewBox() { return &mViewBox; }
147 SVGAnimatedPreserveAspectRatio*
148 SVGMarkerElement::GetAnimatedPreserveAspectRatio() {
149 return &mPreserveAspectRatio;
152 //----------------------------------------------------------------------
153 // public helpers
155 gfx::Matrix SVGMarkerElement::GetMarkerTransform(float aStrokeWidth,
156 const SVGMark& aMark) {
157 float scale =
158 mEnumAttributes[MARKERUNITS].GetAnimValue() == SVG_MARKERUNITS_STROKEWIDTH
159 ? aStrokeWidth
160 : 1.0f;
162 float angle;
163 switch (mOrient.GetAnimType()) {
164 case SVG_MARKER_ORIENT_AUTO:
165 angle = aMark.angle;
166 break;
167 case SVG_MARKER_ORIENT_AUTO_START_REVERSE:
168 angle = aMark.angle + (aMark.type == SVGMark::eStart ? M_PI : 0.0f);
169 break;
170 default: // SVG_MARKER_ORIENT_ANGLE
171 angle = mOrient.GetAnimValue() * M_PI / 180.0f;
172 break;
175 return gfx::Matrix(cos(angle) * scale, sin(angle) * scale,
176 -sin(angle) * scale, cos(angle) * scale, aMark.x, aMark.y);
179 SVGViewBox SVGMarkerElement::GetViewBox() {
180 if (mViewBox.HasRect()) {
181 float zoom = UserSpaceMetrics::GetZoom(this);
182 return mViewBox.GetAnimValue() * zoom;
184 return SVGViewBox(
185 0, 0, mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx),
186 mLengthAttributes[MARKERHEIGHT].GetAnimValueWithZoom(mCoordCtx));
189 gfx::Matrix SVGMarkerElement::GetViewBoxTransform() {
190 if (!mViewBoxToViewportTransform) {
191 float viewportWidth =
192 mLengthAttributes[MARKERWIDTH].GetAnimValueWithZoom(mCoordCtx);
193 float viewportHeight =
194 mLengthAttributes[MARKERHEIGHT].GetAnimValueWithZoom(mCoordCtx);
196 SVGViewBox viewbox = GetViewBox();
198 MOZ_ASSERT(viewbox.width > 0.0f && viewbox.height > 0.0f,
199 "Rendering should be disabled");
201 gfx::Matrix viewBoxTM = SVGContentUtils::GetViewBoxTransform(
202 viewportWidth, viewportHeight, viewbox.x, viewbox.y, viewbox.width,
203 viewbox.height, mPreserveAspectRatio);
205 float refX = mLengthAttributes[REFX].GetAnimValueWithZoom(mCoordCtx);
206 float refY = mLengthAttributes[REFY].GetAnimValueWithZoom(mCoordCtx);
208 gfx::Point ref = viewBoxTM.TransformPoint(gfx::Point(refX, refY));
210 Matrix TM = viewBoxTM;
211 TM.PostTranslate(-ref.x, -ref.y);
213 mViewBoxToViewportTransform = MakeUnique<gfx::Matrix>(TM);
216 return *mViewBoxToViewportTransform;
219 } // namespace mozilla::dom