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 "SVGPolyElement.h"
8 : #include "DOMSVGPointList.h"
9 : #include "mozilla/gfx/2D.h"
10 : #include "SVGContentUtils.h"
11 :
12 : using namespace mozilla;
13 : using namespace mozilla::gfx;
14 :
15 : //----------------------------------------------------------------------
16 : // nsISupports methods
17 :
18 152 : NS_IMPL_ADDREF_INHERITED(SVGPolyElement,SVGPolyElementBase)
19 112 : NS_IMPL_RELEASE_INHERITED(SVGPolyElement,SVGPolyElementBase)
20 :
21 110 : NS_INTERFACE_MAP_BEGIN(SVGPolyElement)
22 110 : NS_INTERFACE_MAP_END_INHERITING(SVGPolyElementBase)
23 :
24 : //----------------------------------------------------------------------
25 : // Implementation
26 :
27 14 : SVGPolyElement::SVGPolyElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
28 14 : : SVGPolyElementBase(aNodeInfo)
29 : {
30 14 : }
31 :
32 0 : SVGPolyElement::~SVGPolyElement()
33 : {
34 0 : }
35 :
36 : already_AddRefed<DOMSVGPointList>
37 0 : SVGPolyElement::Points()
38 : {
39 0 : void *key = mPoints.GetBaseValKey();
40 0 : RefPtr<DOMSVGPointList> points = DOMSVGPointList::GetDOMWrapper(key, this, false);
41 0 : return points.forget();
42 : }
43 :
44 : already_AddRefed<DOMSVGPointList>
45 0 : SVGPolyElement::AnimatedPoints()
46 : {
47 0 : void *key = mPoints.GetAnimValKey();
48 0 : RefPtr<DOMSVGPointList> points = DOMSVGPointList::GetDOMWrapper(key, this, true);
49 0 : return points.forget();
50 : }
51 :
52 :
53 : //----------------------------------------------------------------------
54 : // nsIContent methods
55 :
56 : NS_IMETHODIMP_(bool)
57 112 : SVGPolyElement::IsAttributeMapped(const nsIAtom* name) const
58 : {
59 : static const MappedAttributeEntry* const map[] = {
60 : sMarkersMap
61 : };
62 :
63 224 : return FindAttributeDependence(name, map) ||
64 224 : SVGPolyElementBase::IsAttributeMapped(name);
65 : }
66 :
67 : //----------------------------------------------------------------------
68 : // nsSVGElement methods
69 :
70 : /* virtual */ bool
71 12 : SVGPolyElement::HasValidDimensions() const
72 : {
73 12 : return !mPoints.GetAnimValue().IsEmpty();
74 : }
75 :
76 : //----------------------------------------------------------------------
77 : // SVGGeometryElement methods
78 :
79 : bool
80 0 : SVGPolyElement::AttributeDefinesGeometry(const nsIAtom *aName)
81 : {
82 0 : if (aName == nsGkAtoms::points)
83 0 : return true;
84 :
85 0 : return false;
86 : }
87 :
88 : void
89 0 : SVGPolyElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
90 : {
91 0 : const SVGPointList &points = mPoints.GetAnimValue();
92 :
93 0 : if (!points.Length())
94 0 : return;
95 :
96 0 : float px = points[0].mX, py = points[0].mY, prevAngle = 0.0;
97 :
98 0 : aMarks->AppendElement(nsSVGMark(px, py, 0, nsSVGMark::eStart));
99 :
100 0 : for (uint32_t i = 1; i < points.Length(); ++i) {
101 0 : float x = points[i].mX;
102 0 : float y = points[i].mY;
103 0 : float angle = atan2(y-py, x-px);
104 :
105 : // Vertex marker.
106 0 : if (i == 1) {
107 0 : aMarks->ElementAt(0).angle = angle;
108 : } else {
109 0 : aMarks->ElementAt(aMarks->Length() - 1).angle =
110 0 : SVGContentUtils::AngleBisect(prevAngle, angle);
111 : }
112 :
113 0 : aMarks->AppendElement(nsSVGMark(x, y, 0, nsSVGMark::eMid));
114 :
115 0 : prevAngle = angle;
116 0 : px = x;
117 0 : py = y;
118 : }
119 :
120 0 : aMarks->LastElement().angle = prevAngle;
121 0 : aMarks->LastElement().type = nsSVGMark::eEnd;
122 : }
123 :
124 : bool
125 24 : SVGPolyElement::GetGeometryBounds(Rect* aBounds,
126 : const StrokeOptions& aStrokeOptions,
127 : const Matrix& aToBoundsSpace,
128 : const Matrix* aToNonScalingStrokeSpace)
129 : {
130 24 : const SVGPointList &points = mPoints.GetAnimValue();
131 :
132 24 : if (!points.Length()) {
133 : // Rendering of the element is disabled
134 0 : aBounds->SetEmpty();
135 0 : return true;
136 : }
137 :
138 24 : if (aStrokeOptions.mLineWidth > 0 || aToNonScalingStrokeSpace) {
139 : // We don't handle non-scaling-stroke or stroke-miterlimit etc. yet
140 0 : return false;
141 : }
142 :
143 24 : if (aToBoundsSpace.IsRectilinear()) {
144 : // We can avoid transforming each point and just transform the result.
145 : // Important for large point lists.
146 24 : Rect bounds(points[0], Size());
147 280 : for (uint32_t i = 1; i < points.Length(); ++i) {
148 256 : bounds.ExpandToEnclose(points[i]);
149 : }
150 24 : *aBounds = aToBoundsSpace.TransformBounds(bounds);
151 : } else {
152 0 : *aBounds = Rect(aToBoundsSpace.TransformPoint(points[0]), Size());
153 0 : for (uint32_t i = 1; i < points.Length(); ++i) {
154 0 : aBounds->ExpandToEnclose(aToBoundsSpace.TransformPoint(points[i]));
155 : }
156 : }
157 24 : return true;
158 : }
159 :
|