• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) Research In Motion Limited 2011. 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 #include "config.h"
21 #include "core/rendering/svg/SVGPathData.h"
22 
23 #include "SVGNames.h"
24 #include "core/svg/SVGCircleElement.h"
25 #include "core/svg/SVGEllipseElement.h"
26 #include "core/svg/SVGLineElement.h"
27 #include "core/svg/SVGPathElement.h"
28 #include "core/svg/SVGPathUtilities.h"
29 #include "core/svg/SVGPolygonElement.h"
30 #include "core/svg/SVGPolylineElement.h"
31 #include "core/svg/SVGRectElement.h"
32 #include "platform/graphics/Path.h"
33 #include "wtf/HashMap.h"
34 
35 namespace WebCore {
36 
updatePathFromCircleElement(SVGElement * element,Path & path)37 static void updatePathFromCircleElement(SVGElement* element, Path& path)
38 {
39     SVGCircleElement* circle = toSVGCircleElement(element);
40 
41     SVGLengthContext lengthContext(element);
42     float r = circle->rCurrentValue().value(lengthContext);
43     if (r > 0)
44         path.addEllipse(FloatRect(circle->cxCurrentValue().value(lengthContext) - r, circle->cyCurrentValue().value(lengthContext) - r, r * 2, r * 2));
45 }
46 
updatePathFromEllipseElement(SVGElement * element,Path & path)47 static void updatePathFromEllipseElement(SVGElement* element, Path& path)
48 {
49     SVGEllipseElement* ellipse = toSVGEllipseElement(element);
50 
51     SVGLengthContext lengthContext(element);
52     float rx = ellipse->rxCurrentValue().value(lengthContext);
53     if (rx <= 0)
54         return;
55     float ry = ellipse->ryCurrentValue().value(lengthContext);
56     if (ry <= 0)
57         return;
58     path.addEllipse(FloatRect(ellipse->cxCurrentValue().value(lengthContext) - rx, ellipse->cyCurrentValue().value(lengthContext) - ry, rx * 2, ry * 2));
59 }
60 
updatePathFromLineElement(SVGElement * element,Path & path)61 static void updatePathFromLineElement(SVGElement* element, Path& path)
62 {
63     SVGLineElement* line = toSVGLineElement(element);
64 
65     SVGLengthContext lengthContext(element);
66     path.moveTo(FloatPoint(line->x1CurrentValue().value(lengthContext), line->y1CurrentValue().value(lengthContext)));
67     path.addLineTo(FloatPoint(line->x2CurrentValue().value(lengthContext), line->y2CurrentValue().value(lengthContext)));
68 }
69 
updatePathFromPathElement(SVGElement * element,Path & path)70 static void updatePathFromPathElement(SVGElement* element, Path& path)
71 {
72     buildPathFromByteStream(toSVGPathElement(element)->pathByteStream(), path);
73 }
74 
updatePathFromPolygonElement(SVGElement * element,Path & path)75 static void updatePathFromPolygonElement(SVGElement* element, Path& path)
76 {
77     SVGPointList& points = toSVGPolygonElement(element)->pointsCurrentValue();
78     if (points.isEmpty())
79         return;
80 
81     path.moveTo(points.first());
82 
83     unsigned size = points.size();
84     for (unsigned i = 1; i < size; ++i)
85         path.addLineTo(points.at(i));
86 
87     path.closeSubpath();
88 }
89 
updatePathFromPolylineElement(SVGElement * element,Path & path)90 static void updatePathFromPolylineElement(SVGElement* element, Path& path)
91 {
92     SVGPointList& points = toSVGPolylineElement(element)->pointsCurrentValue();
93     if (points.isEmpty())
94         return;
95 
96     path.moveTo(points.first());
97 
98     unsigned size = points.size();
99     for (unsigned i = 1; i < size; ++i)
100         path.addLineTo(points.at(i));
101 }
102 
updatePathFromRectElement(SVGElement * element,Path & path)103 static void updatePathFromRectElement(SVGElement* element, Path& path)
104 {
105     SVGRectElement* rect = toSVGRectElement(element);
106 
107     SVGLengthContext lengthContext(element);
108     float width = rect->widthCurrentValue().value(lengthContext);
109     if (width <= 0)
110         return;
111     float height = rect->heightCurrentValue().value(lengthContext);
112     if (height <= 0)
113         return;
114     float x = rect->xCurrentValue().value(lengthContext);
115     float y = rect->yCurrentValue().value(lengthContext);
116     bool hasRx = rect->rxCurrentValue().value(lengthContext) > 0;
117     bool hasRy = rect->ryCurrentValue().value(lengthContext) > 0;
118     if (hasRx || hasRy) {
119         float rx = rect->rxCurrentValue().value(lengthContext);
120         float ry = rect->ryCurrentValue().value(lengthContext);
121         if (!hasRx)
122             rx = ry;
123         else if (!hasRy)
124             ry = rx;
125 
126         path.addRoundedRect(FloatRect(x, y, width, height), FloatSize(rx, ry));
127         return;
128     }
129 
130     path.addRect(FloatRect(x, y, width, height));
131 }
132 
updatePathFromGraphicsElement(SVGElement * element,Path & path)133 void updatePathFromGraphicsElement(SVGElement* element, Path& path)
134 {
135     ASSERT(element);
136     ASSERT(path.isEmpty());
137 
138     typedef void (*PathUpdateFunction)(SVGElement*, Path&);
139     static HashMap<StringImpl*, PathUpdateFunction>* map = 0;
140     if (!map) {
141         map = new HashMap<StringImpl*, PathUpdateFunction>;
142         map->set(SVGNames::circleTag.localName().impl(), updatePathFromCircleElement);
143         map->set(SVGNames::ellipseTag.localName().impl(), updatePathFromEllipseElement);
144         map->set(SVGNames::lineTag.localName().impl(), updatePathFromLineElement);
145         map->set(SVGNames::pathTag.localName().impl(), updatePathFromPathElement);
146         map->set(SVGNames::polygonTag.localName().impl(), updatePathFromPolygonElement);
147         map->set(SVGNames::polylineTag.localName().impl(), updatePathFromPolylineElement);
148         map->set(SVGNames::rectTag.localName().impl(), updatePathFromRectElement);
149     }
150 
151     if (PathUpdateFunction pathUpdateFunction = map->get(element->localName().impl()))
152         (*pathUpdateFunction)(element, path);
153 }
154 
155 } // namespace WebCore
156