[BlackBerry] GraphicsContext: add fillRule parameter to clip() and canvasClip()
[WebKit-https.git] / Source / WebCore / platform / graphics / blackberry / PathBlackBerry.cpp
1 /*
2  * Copyright (C) 2012 Research In Motion Limited. 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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include "config.h"
20 #include "Path.h"
21
22 #include "AffineTransform.h"
23 #include "FloatRect.h"
24 #include "GraphicsContext.h"
25 #include "NotImplemented.h"
26 #include "StrokeStyleApplier.h"
27
28 #include <BlackBerryPlatformGraphics.h>
29 #include <BlackBerryPlatformGraphicsContext.h>
30 #include <stdio.h>
31 #include <wtf/MathExtras.h>
32
33 namespace WebCore {
34
35 static GraphicsContext* scratchContext()
36 {
37     static BlackBerry::Platform::Graphics::Buffer* buffer = BlackBerry::Platform::Graphics::createBuffer(IntSize(), BlackBerry::Platform::Graphics::NeverBacked);
38     static PlatformGraphicsContext* pgc = lockBufferDrawable(buffer);
39     static GraphicsContext gc(pgc);
40     return &gc;
41 }
42
43 Path::Path() : m_path(new BlackBerry::Platform::Graphics::Path)
44 {
45 }
46
47 Path::Path(const PlatformPath& path)
48     : m_path(new BlackBerry::Platform::Graphics::Path(path))
49 {
50 }
51
52 Path::~Path()
53 {
54     if (m_path) {
55         delete m_path;
56         m_path = 0;
57     }
58 }
59
60 Path::Path(const Path& other)
61 {
62     m_path = new BlackBerry::Platform::Graphics::Path(*other.m_path);
63 }
64
65 Path& Path::operator=(const Path& other)
66 {
67     if (m_path) {
68         delete m_path;
69         m_path = 0;
70     }
71     m_path = new BlackBerry::Platform::Graphics::Path(*other.m_path);
72     return *this;
73 }
74
75 FloatPoint Path::currentPoint() const
76 {
77     return m_path->currentPoint();
78 }
79
80 bool Path::contains(const FloatPoint& point, WindRule rule) const
81 {
82     return m_path->contains(point, (BlackBerry::Platform::Graphics::WindRule)(rule));
83 }
84
85 bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const
86 {
87     GraphicsContext* scratch = scratchContext();
88     scratch->save();
89
90     if (applier)
91         applier->strokeStyle(scratch);
92
93     bool result = scratchContext()->platformContext()->strokeContains(*m_path, point);
94     scratch->restore();
95     return result;
96 }
97
98 void Path::translate(const FloatSize& size)
99 {
100     AffineTransform transformation;
101     transformation.translate(size.width(), size.height());
102     transform(transformation);
103 }
104
105 FloatRect Path::boundingRect() const
106 {
107     return m_path->getBounds();
108 }
109
110 FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
111 {
112     GraphicsContext* scratch = scratchContext();
113     scratch->save();
114
115     if (applier)
116         applier->strokeStyle(scratch);
117
118     FloatRect result = scratch->platformContext()->getStrokeBounds(*m_path);
119
120     scratch->restore();
121     return result;
122 }
123
124 void Path::moveTo(const FloatPoint& point)
125 {
126     m_path->moveTo(point);
127 }
128
129 void Path::addLineTo(const FloatPoint& point)
130 {
131     m_path->addLineTo(point);
132 }
133
134 void Path::addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endPoint)
135 {
136     m_path->addQuadCurveTo(controlPoint, endPoint);
137 }
138
139 void Path::addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint)
140 {
141     m_path->addBezierCurveTo(controlPoint1, controlPoint2, endPoint);
142 }
143
144 void Path::addArcTo(const FloatPoint& point1, const FloatPoint& point2, float radius)
145 {
146     m_path->addArcTo(point1, point2, radius);
147 }
148
149 void Path::closeSubpath()
150 {
151     m_path->closeSubpath();
152 }
153
154 void Path::addArc(const FloatPoint& center, float radius, float startAngle, float endAngle, bool anticlockwise)
155 {
156     m_path->addArc(center, radius, startAngle, endAngle, anticlockwise);
157 }
158
159 void Path::addRect(const FloatRect& rect)
160 {
161     m_path->addRect(rect);
162 }
163
164 void Path::addEllipse(const FloatRect& rect)
165 {
166     m_path->addEllipse(rect);
167 }
168
169 void Path::platformAddPathForRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
170 {
171     if (rect.isEmpty())
172         return;
173
174     if (rect.width() < topLeftRadius.width() + topRightRadius.width()
175         || rect.width() < bottomLeftRadius.width() + bottomRightRadius.width()
176         || rect.height() < topLeftRadius.height() + bottomLeftRadius.height()
177         || rect.height() < topRightRadius.height() + bottomRightRadius.height()) {
178         // If all the radii cannot be accommodated, return a rect.
179         addRect(rect);
180         return;
181     }
182
183     BlackBerry::Platform::FloatRoundedRect rr(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
184     // Make sure the generic path reflects the contents of the rounded rects
185     m_path->addRoundedRect(rr);
186 }
187
188 void Path::clear()
189 {
190     m_path->reset();
191 }
192
193 bool Path::isEmpty() const
194 {
195     return m_path->isEmpty();
196 }
197
198 bool Path::hasCurrentPoint() const
199 {
200     return m_path->hasCurrentPoint();
201 }
202
203 void Path::apply(void* info, PathApplierFunction function) const
204 {
205     m_path->apply(info, (void*)function);
206 }
207
208 void Path::transform(const AffineTransform& transformation)
209 {
210     m_path->transform(reinterpret_cast<const double*>(&transformation));
211 }
212
213 void GraphicsContext::fillPath(const Path& path)
214 {
215     BlackBerry::Platform::Graphics::Path* pp = path.platformPath();
216     if (!pp->isEmpty()) {
217         BlackBerry::Platform::Graphics::Gradient* platformGradient = fillGradient() ? fillGradient()->platformGradient() : 0;
218         BlackBerry::Platform::Graphics::Pattern* platformPattern = fillPattern() ? fillPattern()->platformPattern(AffineTransform()) : 0;
219         platformContext()->addFillPath(*pp, (BlackBerry::Platform::Graphics::WindRule)m_state.fillRule, platformGradient, platformPattern);
220     }
221 }
222
223 void GraphicsContext::strokePath(const Path& path)
224 {
225     BlackBerry::Platform::Graphics::Path* pp = path.platformPath();
226     if (!pp->isEmpty()) {
227         BlackBerry::Platform::Graphics::Gradient* gradient = strokeGradient() ? strokeGradient()->platformGradient() : 0;
228         BlackBerry::Platform::Graphics::Pattern* pattern = strokePattern() ? strokePattern()->platformPattern(AffineTransform()) : 0;
229         platformContext()->addStrokePath(*pp, gradient, pattern);
230     }
231 }
232
233 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
234 {
235     notImplemented();
236 }
237
238 void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
239 {
240     notImplemented();
241 }
242
243 void GraphicsContext::drawLine(const IntPoint& from, const IntPoint& to)
244 {
245     platformContext()->addDrawLine(from, to);
246 }
247
248 void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float width, DocumentMarkerLineStyle style)
249 {
250     platformContext()->addDrawLineForDocumentMarker(pt, width, (BlackBerry::Platform::Graphics::DocumentMarkerLineStyle)style);
251 }
252
253 void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool printing)
254 {
255     platformContext()->addDrawLineForText(pt, width, printing);
256 }
257
258 // FIXME: don't ignore the winding rule. https://bugs.webkit.org/show_bug.cgi?id=107064
259 void GraphicsContext::clip(const Path& path, WindRule)
260 {
261     BlackBerry::Platform::Graphics::Path* pp = path.platformPath();
262     pp->applyAsClip(platformContext());
263 }
264
265 void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
266 {
267     if (path.platformPath()->isRectangular())
268         platformContext()->clip(path.boundingRect());
269     else
270         clip(path);
271 }
272
273 void GraphicsContext::canvasClip(const Path& path, WindRule fillRule)
274 {
275     clip(path, fillRule);
276 }
277
278 void GraphicsContext::clipOut(const Path& path)
279 {
280     BlackBerry::Platform::Graphics::Path* pp = path.platformPath();
281     pp->applyAsClipOut(platformContext());
282 }
283
284 }