• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifndef SVGMarkerData_h
21 #define SVGMarkerData_h
22 
23 #include "platform/FloatConversion.h"
24 #include "platform/graphics/Path.h"
25 #include "wtf/MathExtras.h"
26 
27 namespace WebCore {
28 
29 enum SVGMarkerType {
30     StartMarker,
31     MidMarker,
32     EndMarker
33 };
34 
35 struct MarkerPosition {
MarkerPositionMarkerPosition36     MarkerPosition(SVGMarkerType useType, const FloatPoint& useOrigin, float useAngle)
37         : type(useType)
38         , origin(useOrigin)
39         , angle(useAngle)
40     {
41     }
42 
43     SVGMarkerType type;
44     FloatPoint origin;
45     float angle;
46 };
47 
48 class SVGMarkerData {
49 public:
SVGMarkerData(Vector<MarkerPosition> & positions)50     SVGMarkerData(Vector<MarkerPosition>& positions)
51         : m_positions(positions)
52         , m_elementIndex(0)
53     {
54     }
55 
updateFromPathElement(void * info,const PathElement * element)56     static void updateFromPathElement(void* info, const PathElement* element)
57     {
58         SVGMarkerData* markerData = static_cast<SVGMarkerData*>(info);
59 
60         // First update the outslope for the previous element.
61         markerData->updateOutslope(element->points[0]);
62 
63         // Record the marker for the previous element.
64         if (markerData->m_elementIndex > 0) {
65             SVGMarkerType markerType = markerData->m_elementIndex == 1 ? StartMarker : MidMarker;
66             markerData->m_positions.append(MarkerPosition(markerType, markerData->m_origin, markerData->currentAngle(markerType)));
67         }
68 
69         // Update our marker data for this element.
70         markerData->updateMarkerDataForPathElement(element);
71         ++markerData->m_elementIndex;
72     }
73 
pathIsDone()74     void pathIsDone()
75     {
76         m_positions.append(MarkerPosition(EndMarker, m_origin, currentAngle(EndMarker)));
77     }
78 
79 private:
currentAngle(SVGMarkerType type)80     float currentAngle(SVGMarkerType type) const
81     {
82         // For details of this calculation, see: http://www.w3.org/TR/SVG/single-page.html#painting-MarkerElement
83         FloatPoint inSlope(m_inslopePoints[1] - m_inslopePoints[0]);
84         FloatPoint outSlope(m_outslopePoints[1] - m_outslopePoints[0]);
85 
86         double inAngle = rad2deg(inSlope.slopeAngleRadians());
87         double outAngle = rad2deg(outSlope.slopeAngleRadians());
88 
89         switch (type) {
90         case StartMarker:
91             return narrowPrecisionToFloat(outAngle);
92         case MidMarker:
93             // WK193015: Prevent bugs due to angles being non-continuous.
94             if (fabs(inAngle - outAngle) > 180)
95                 inAngle += 360;
96             return narrowPrecisionToFloat((inAngle + outAngle) / 2);
97         case EndMarker:
98             return narrowPrecisionToFloat(inAngle);
99         }
100 
101         ASSERT_NOT_REACHED();
102         return 0;
103     }
104 
updateOutslope(const FloatPoint & point)105     void updateOutslope(const FloatPoint& point)
106     {
107         m_outslopePoints[0] = m_origin;
108         m_outslopePoints[1] = point;
109     }
110 
updateMarkerDataForPathElement(const PathElement * element)111     void updateMarkerDataForPathElement(const PathElement* element)
112     {
113         FloatPoint* points = element->points;
114 
115         switch (element->type) {
116         case PathElementAddQuadCurveToPoint:
117             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=33115 (PathElementAddQuadCurveToPoint not handled for <marker>)
118             m_origin = points[1];
119             break;
120         case PathElementAddCurveToPoint:
121             m_inslopePoints[0] = points[1];
122             m_inslopePoints[1] = points[2];
123             m_origin = points[2];
124             break;
125         case PathElementMoveToPoint:
126             m_subpathStart = points[0];
127         case PathElementAddLineToPoint:
128             updateInslope(points[0]);
129             m_origin = points[0];
130             break;
131         case PathElementCloseSubpath:
132             updateInslope(points[0]);
133             m_origin = m_subpathStart;
134             m_subpathStart = FloatPoint();
135         }
136     }
137 
updateInslope(const FloatPoint & point)138     void updateInslope(const FloatPoint& point)
139     {
140         m_inslopePoints[0] = m_origin;
141         m_inslopePoints[1] = point;
142     }
143 
144     Vector<MarkerPosition>& m_positions;
145     unsigned m_elementIndex;
146     FloatPoint m_origin;
147     FloatPoint m_subpathStart;
148     FloatPoint m_inslopePoints[2];
149     FloatPoint m_outslopePoints[2];
150 };
151 
152 }
153 
154 #endif // SVGMarkerData_h
155