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