1 /*
2  * Copyright (C) Research In Motion Limited 2009-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 #include "config.h"
21 #include "GraphicsContext.h"
22 
23 #include "AffineTransform.h"
24 #include "KURL.h"
25 #include "NotImplemented.h"
26 #include "PainterOpenVG.h"
27 #include "SurfaceOpenVG.h"
28 
29 #include <wtf/Assertions.h>
30 #include <wtf/MathExtras.h>
31 #include <wtf/UnusedParam.h>
32 #include <wtf/Vector.h>
33 
34 #if PLATFORM(EGL)
35 #include "EGLDisplayOpenVG.h"
36 #include "EGLUtils.h"
37 #include <egl.h>
38 #endif
39 
40 namespace WebCore {
41 
42 // typedef'ing doesn't work, let's inherit from PainterOpenVG instead
43 class GraphicsContextPlatformPrivate : public PainterOpenVG {
44 public:
GraphicsContextPlatformPrivate(SurfaceOpenVG * surface)45     GraphicsContextPlatformPrivate(SurfaceOpenVG* surface)
46         : PainterOpenVG(surface)
47     {
48     }
49 };
50 
platformInit(SurfaceOpenVG * surface)51 void GraphicsContext::platformInit(SurfaceOpenVG* surface)
52 {
53     m_data = surface ? new GraphicsContextPlatformPrivate(surface) : 0;
54     setPaintingDisabled(!surface);
55 }
56 
platformDestroy()57 void GraphicsContext::platformDestroy()
58 {
59     delete m_data;
60 }
61 
platformContext() const62 PlatformGraphicsContext* GraphicsContext::platformContext() const
63 {
64     if (paintingDisabled())
65         return 0;
66 
67     return m_data->baseSurface();
68 }
69 
getCTM() const70 AffineTransform GraphicsContext::getCTM() const
71 {
72     if (paintingDisabled())
73         return AffineTransform();
74 
75     return m_data->transformation();
76 }
77 
savePlatformState()78 void GraphicsContext::savePlatformState()
79 {
80     if (paintingDisabled())
81         return;
82 
83     m_data->save();
84 }
85 
restorePlatformState()86 void GraphicsContext::restorePlatformState()
87 {
88     if (paintingDisabled())
89         return;
90 
91     m_data->restore();
92 }
93 
drawRect(const IntRect & rect)94 void GraphicsContext::drawRect(const IntRect& rect)
95 {
96     if (paintingDisabled())
97         return;
98 
99     m_data->drawRect(rect);
100 }
101 
drawLine(const IntPoint & from,const IntPoint & to)102 void GraphicsContext::drawLine(const IntPoint& from, const IntPoint& to)
103 {
104     if (paintingDisabled())
105         return;
106 
107     m_data->drawLine(from, to);
108 }
109 
110 /**
111  * Draw the largest ellipse that fits into the given rectangle.
112  */
drawEllipse(const IntRect & rect)113 void GraphicsContext::drawEllipse(const IntRect& rect)
114 {
115     if (paintingDisabled())
116         return;
117 
118     m_data->drawEllipse(rect);
119 }
120 
strokeArc(const IntRect & rect,int startAngle,int angleSpan)121 void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
122 {
123     if (paintingDisabled())
124         return;
125 
126     m_data->drawArc(rect, startAngle, angleSpan, VG_STROKE_PATH);
127 }
128 
drawConvexPolygon(size_t numPoints,const FloatPoint * points,bool shouldAntialias)129 void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias)
130 {
131     if (paintingDisabled())
132         return;
133 
134     m_data->drawPolygon(numPoints, points);
135 
136     UNUSED_PARAM(shouldAntialias); // FIXME
137 }
138 
fillPath(const Path & path)139 void GraphicsContext::fillPath(const Path& path)
140 {
141     if (paintingDisabled())
142         return;
143 
144     m_data->drawPath(path, VG_FILL_PATH, m_state.fillRule);
145 }
146 
strokePath(const Path & path)147 void GraphicsContext::strokePath(const Path& path)
148 {
149     if (paintingDisabled())
150         return;
151 
152     m_data->drawPath(path, VG_STROKE_PATH, m_state.fillRule);
153 }
154 
fillRect(const FloatRect & rect)155 void GraphicsContext::fillRect(const FloatRect& rect)
156 {
157     if (paintingDisabled())
158         return;
159 
160     m_data->drawRect(rect, VG_FILL_PATH);
161 }
162 
fillRect(const FloatRect & rect,const Color & color,ColorSpace colorSpace)163 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
164 {
165     if (paintingDisabled())
166         return;
167 
168     Color oldColor = m_data->fillColor();
169     m_data->setFillColor(color);
170     m_data->drawRect(rect, VG_FILL_PATH);
171     m_data->setFillColor(oldColor);
172 
173     UNUSED_PARAM(colorSpace); // FIXME
174 }
175 
fillRoundedRect(const IntRect & rect,const IntSize & topLeft,const IntSize & topRight,const IntSize & bottomLeft,const IntSize & bottomRight,const Color & color,ColorSpace colorSpace)176 void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
177 {
178     if (paintingDisabled())
179         return;
180 
181     Color oldColor = m_data->fillColor();
182     m_data->setFillColor(color);
183     m_data->drawRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, VG_FILL_PATH);
184     m_data->setFillColor(oldColor);
185 
186     UNUSED_PARAM(colorSpace); // FIXME
187 }
188 
clip(const FloatRect & rect)189 void GraphicsContext::clip(const FloatRect& rect)
190 {
191     if (paintingDisabled())
192         return;
193 
194     m_data->intersectClipRect(rect);
195 }
196 
clipPath(const Path & path,WindRule clipRule)197 void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
198 {
199     if (paintingDisabled())
200         return;
201 
202     m_data->clipPath(path, PainterOpenVG::IntersectClip, clipRule);
203 }
204 
drawFocusRing(const Vector<IntRect> & rects,int width,int offset,const Color & color)205 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
206 {
207     if (paintingDisabled())
208         return;
209 
210     if (rects.isEmpty())
211         return;
212 
213     // FIXME: We just unite all focus ring rects into one for now.
214     // We should outline the edge of the full region.
215     offset += (width - 1) / 2;
216     IntRect finalFocusRect;
217 
218     for (unsigned i = 0; i < rects.size(); i++) {
219         IntRect focusRect = rects[i];
220         focusRect.inflate(offset);
221         finalFocusRect.unite(focusRect);
222     }
223 
224     StrokeStyle oldStyle = m_data->strokeStyle();
225     Color oldStrokeColor = m_data->strokeColor();
226     m_data->setStrokeStyle(DashedStroke);
227     m_data->setStrokeColor(color);
228     strokeRect(FloatRect(finalFocusRect), 1.f);
229     m_data->setStrokeStyle(oldStyle);
230     m_data->setStrokeColor(oldStrokeColor);
231 }
232 
drawLineForText(const IntPoint & origin,int width,bool printing)233 void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
234 {
235     if (paintingDisabled())
236         return;
237 
238     if (width <= 0)
239         return;
240 
241     StrokeStyle oldStyle = m_data->strokeStyle();
242     m_data->setStrokeStyle(SolidStroke);
243     drawLine(origin, origin + IntSize(width, 0));
244     m_data->setStrokeStyle(oldStyle);
245 
246     UNUSED_PARAM(printing);
247 }
248 
drawLineForTextChecking(const IntPoint & origin,int width,TextCheckingLineStyle style)249 void GraphicsContext::drawLineForTextChecking(const IntPoint& origin, int width, TextCheckingLineStyle style)
250 {
251     if (paintingDisabled())
252         return;
253 
254     notImplemented();
255     UNUSED_PARAM(origin);
256     UNUSED_PARAM(width);
257     UNUSED_PARAM(style);
258 }
259 
roundToDevicePixels(const FloatRect & rect,RoundingMode)260 FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode)
261 {
262     if (paintingDisabled())
263         return FloatRect();
264 
265     return FloatRect(enclosingIntRect(m_data->transformation().mapRect(rect)));
266 }
267 
setPlatformShadow(const FloatSize & size,float blur,const Color & color,ColorSpace colorSpace)268 void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace colorSpace)
269 {
270     if (paintingDisabled())
271         return;
272 
273     notImplemented();
274     UNUSED_PARAM(size);
275     UNUSED_PARAM(blur);
276     UNUSED_PARAM(color);
277     UNUSED_PARAM(colorSpace);
278 }
279 
clearPlatformShadow()280 void GraphicsContext::clearPlatformShadow()
281 {
282     if (paintingDisabled())
283         return;
284 
285     notImplemented();
286 }
287 
beginTransparencyLayer(float opacity)288 void GraphicsContext::beginTransparencyLayer(float opacity)
289 {
290     if (paintingDisabled())
291         return;
292 
293     notImplemented();
294     UNUSED_PARAM(opacity);
295 }
296 
endTransparencyLayer()297 void GraphicsContext::endTransparencyLayer()
298 {
299     if (paintingDisabled())
300         return;
301 
302     notImplemented();
303 }
304 
clearRect(const FloatRect & rect)305 void GraphicsContext::clearRect(const FloatRect& rect)
306 {
307     if (paintingDisabled())
308         return;
309 
310     CompositeOperator op = m_data->compositeOperation();
311     m_data->setCompositeOperation(CompositeClear);
312     m_data->drawRect(rect, VG_FILL_PATH);
313     m_data->setCompositeOperation(op);
314 }
315 
strokeRect(const FloatRect & rect,float lineWidth)316 void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
317 {
318     if (paintingDisabled())
319         return;
320 
321     float oldThickness = m_data->strokeThickness();
322     m_data->setStrokeThickness(lineWidth);
323     m_data->drawRect(rect, VG_STROKE_PATH);
324     m_data->setStrokeThickness(oldThickness);
325 }
326 
setLineCap(LineCap lc)327 void GraphicsContext::setLineCap(LineCap lc)
328 {
329     if (paintingDisabled())
330         return;
331 
332     m_data->setLineCap(lc);
333 }
334 
setLineDash(const DashArray & dashes,float dashOffset)335 void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
336 {
337     if (paintingDisabled())
338         return;
339 
340     m_data->setLineDash(dashes, dashOffset);
341 }
342 
setLineJoin(LineJoin lj)343 void GraphicsContext::setLineJoin(LineJoin lj)
344 {
345     if (paintingDisabled())
346         return;
347 
348     m_data->setLineJoin(lj);
349 }
350 
setMiterLimit(float limit)351 void GraphicsContext::setMiterLimit(float limit)
352 {
353     if (paintingDisabled())
354         return;
355 
356     m_data->setMiterLimit(limit);
357 }
358 
setAlpha(float opacity)359 void GraphicsContext::setAlpha(float opacity)
360 {
361     if (paintingDisabled())
362         return;
363 
364     m_data->setOpacity(opacity);
365 }
366 
setPlatformCompositeOperation(CompositeOperator op)367 void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
368 {
369     if (paintingDisabled())
370         return;
371 
372     m_data->setCompositeOperation(op);
373 }
374 
clip(const Path & path)375 void GraphicsContext::clip(const Path& path)
376 {
377     if (paintingDisabled())
378         return;
379 
380     m_data->clipPath(path, PainterOpenVG::IntersectClip, m_state.fillRule);
381 }
382 
canvasClip(const Path & path)383 void GraphicsContext::canvasClip(const Path& path)
384 {
385     clip(path);
386 }
387 
clipOut(const Path & path)388 void GraphicsContext::clipOut(const Path& path)
389 {
390     if (paintingDisabled())
391         return;
392 
393     m_data->clipPath(path, PainterOpenVG::SubtractClip, m_state.fillRule);
394 }
395 
scale(const FloatSize & scaleFactors)396 void GraphicsContext::scale(const FloatSize& scaleFactors)
397 {
398     if (paintingDisabled())
399         return;
400 
401     m_data->scale(scaleFactors);
402 }
403 
rotate(float radians)404 void GraphicsContext::rotate(float radians)
405 {
406     if (paintingDisabled())
407         return;
408 
409     m_data->rotate(radians);
410 }
411 
translate(float dx,float dy)412 void GraphicsContext::translate(float dx, float dy)
413 {
414     if (paintingDisabled())
415         return;
416 
417     m_data->translate(dx, dy);
418 }
419 
clipOut(const IntRect & rect)420 void GraphicsContext::clipOut(const IntRect& rect)
421 {
422     if (paintingDisabled())
423         return;
424 
425     Path path;
426     path.addRect(rect);
427     m_data->clipPath(path, PainterOpenVG::SubtractClip, m_state.fillRule);
428 }
429 
clipToImageBuffer(const FloatRect & rect,const ImageBuffer * imageBuffer)430 void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
431 {
432     if (paintingDisabled())
433         return;
434 
435     notImplemented();
436     UNUSED_PARAM(rect);
437     UNUSED_PARAM(imageBuffer);
438 }
439 
addInnerRoundedRectClip(const IntRect & rect,int thickness)440 void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
441 {
442     if (paintingDisabled())
443         return;
444 
445     Path path;
446     path.addEllipse(rect);
447     path.addEllipse(FloatRect(rect.x() + thickness, rect.y() + thickness,
448         rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
449 
450     m_data->clipPath(path, PainterOpenVG::IntersectClip, m_state.fillRule);
451 }
452 
concatCTM(const AffineTransform & transformation)453 void GraphicsContext::concatCTM(const AffineTransform& transformation)
454 {
455     if (paintingDisabled())
456         return;
457 
458     m_data->concatTransformation(transformation);
459 }
460 
setCTM(const AffineTransform & transformation)461 void GraphicsContext::setCTM(const AffineTransform& transformation)
462 {
463     if (paintingDisabled())
464         return;
465 
466     m_data->setTransformation(transformation);
467 }
468 
setURLForRect(const KURL & link,const IntRect & destRect)469 void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
470 {
471     notImplemented();
472     UNUSED_PARAM(link);
473     UNUSED_PARAM(destRect);
474 }
475 
setPlatformStrokeColor(const Color & color,ColorSpace colorSpace)476 void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
477 {
478     if (paintingDisabled())
479         return;
480 
481     m_data->setStrokeColor(color);
482 
483     UNUSED_PARAM(colorSpace); // FIXME
484 }
485 
setPlatformStrokeStyle(StrokeStyle strokeStyle)486 void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle)
487 {
488     if (paintingDisabled())
489         return;
490 
491     m_data->setStrokeStyle(strokeStyle);
492 }
493 
setPlatformStrokeThickness(float thickness)494 void GraphicsContext::setPlatformStrokeThickness(float thickness)
495 {
496     if (paintingDisabled())
497         return;
498 
499     m_data->setStrokeThickness(thickness);
500 }
501 
setPlatformFillColor(const Color & color,ColorSpace colorSpace)502 void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
503 {
504     if (paintingDisabled())
505         return;
506 
507     m_data->setFillColor(color);
508 
509     UNUSED_PARAM(colorSpace); // FIXME
510 }
511 
setPlatformShouldAntialias(bool enable)512 void GraphicsContext::setPlatformShouldAntialias(bool enable)
513 {
514     if (paintingDisabled())
515         return;
516 
517     m_data->setAntialiasingEnabled(enable);
518 }
519 
setImageInterpolationQuality(InterpolationQuality)520 void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
521 {
522     notImplemented();
523 }
524 
imageInterpolationQuality() const525 InterpolationQuality GraphicsContext::imageInterpolationQuality() const
526 {
527     notImplemented();
528     return InterpolationDefault;
529 }
530 
531 }
532