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: 45 GraphicsContextPlatformPrivate(SurfaceOpenVG* surface) 46 : PainterOpenVG(surface) 47 { 48 } 49 }; 50 51 void GraphicsContext::platformInit(SurfaceOpenVG* surface) 52 { 53 m_data = surface ? new GraphicsContextPlatformPrivate(surface) : 0; 54 setPaintingDisabled(!surface); 55 } 56 57 void GraphicsContext::platformDestroy() 58 { 59 delete m_data; 60 } 61 62 PlatformGraphicsContext* GraphicsContext::platformContext() const 63 { 64 if (paintingDisabled()) 65 return 0; 66 67 return m_data->baseSurface(); 68 } 69 70 AffineTransform GraphicsContext::getCTM() const 71 { 72 if (paintingDisabled()) 73 return AffineTransform(); 74 75 return m_data->transformation(); 76 } 77 78 void GraphicsContext::savePlatformState() 79 { 80 if (paintingDisabled()) 81 return; 82 83 m_data->save(); 84 } 85 86 void GraphicsContext::restorePlatformState() 87 { 88 if (paintingDisabled()) 89 return; 90 91 m_data->restore(); 92 } 93 94 void GraphicsContext::drawRect(const IntRect& rect) 95 { 96 if (paintingDisabled()) 97 return; 98 99 m_data->drawRect(rect); 100 } 101 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 */ 113 void GraphicsContext::drawEllipse(const IntRect& rect) 114 { 115 if (paintingDisabled()) 116 return; 117 118 m_data->drawEllipse(rect); 119 } 120 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 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 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 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 155 void GraphicsContext::fillRect(const FloatRect& rect) 156 { 157 if (paintingDisabled()) 158 return; 159 160 m_data->drawRect(rect, VG_FILL_PATH); 161 } 162 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 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 189 void GraphicsContext::clip(const FloatRect& rect) 190 { 191 if (paintingDisabled()) 192 return; 193 194 m_data->intersectClipRect(rect); 195 } 196 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 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 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 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 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 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 280 void GraphicsContext::clearPlatformShadow() 281 { 282 if (paintingDisabled()) 283 return; 284 285 notImplemented(); 286 } 287 288 void GraphicsContext::beginTransparencyLayer(float opacity) 289 { 290 if (paintingDisabled()) 291 return; 292 293 notImplemented(); 294 UNUSED_PARAM(opacity); 295 } 296 297 void GraphicsContext::endTransparencyLayer() 298 { 299 if (paintingDisabled()) 300 return; 301 302 notImplemented(); 303 } 304 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 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 327 void GraphicsContext::setLineCap(LineCap lc) 328 { 329 if (paintingDisabled()) 330 return; 331 332 m_data->setLineCap(lc); 333 } 334 335 void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) 336 { 337 if (paintingDisabled()) 338 return; 339 340 m_data->setLineDash(dashes, dashOffset); 341 } 342 343 void GraphicsContext::setLineJoin(LineJoin lj) 344 { 345 if (paintingDisabled()) 346 return; 347 348 m_data->setLineJoin(lj); 349 } 350 351 void GraphicsContext::setMiterLimit(float limit) 352 { 353 if (paintingDisabled()) 354 return; 355 356 m_data->setMiterLimit(limit); 357 } 358 359 void GraphicsContext::setAlpha(float opacity) 360 { 361 if (paintingDisabled()) 362 return; 363 364 m_data->setOpacity(opacity); 365 } 366 367 void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op) 368 { 369 if (paintingDisabled()) 370 return; 371 372 m_data->setCompositeOperation(op); 373 } 374 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 383 void GraphicsContext::canvasClip(const Path& path) 384 { 385 clip(path); 386 } 387 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 396 void GraphicsContext::scale(const FloatSize& scaleFactors) 397 { 398 if (paintingDisabled()) 399 return; 400 401 m_data->scale(scaleFactors); 402 } 403 404 void GraphicsContext::rotate(float radians) 405 { 406 if (paintingDisabled()) 407 return; 408 409 m_data->rotate(radians); 410 } 411 412 void GraphicsContext::translate(float dx, float dy) 413 { 414 if (paintingDisabled()) 415 return; 416 417 m_data->translate(dx, dy); 418 } 419 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 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 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 453 void GraphicsContext::concatCTM(const AffineTransform& transformation) 454 { 455 if (paintingDisabled()) 456 return; 457 458 m_data->concatTransformation(transformation); 459 } 460 461 void GraphicsContext::setCTM(const AffineTransform& transformation) 462 { 463 if (paintingDisabled()) 464 return; 465 466 m_data->setTransformation(transformation); 467 } 468 469 void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) 470 { 471 notImplemented(); 472 UNUSED_PARAM(link); 473 UNUSED_PARAM(destRect); 474 } 475 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 486 void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle) 487 { 488 if (paintingDisabled()) 489 return; 490 491 m_data->setStrokeStyle(strokeStyle); 492 } 493 494 void GraphicsContext::setPlatformStrokeThickness(float thickness) 495 { 496 if (paintingDisabled()) 497 return; 498 499 m_data->setStrokeThickness(thickness); 500 } 501 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 512 void GraphicsContext::setPlatformShouldAntialias(bool enable) 513 { 514 if (paintingDisabled()) 515 return; 516 517 m_data->setAntialiasingEnabled(enable); 518 } 519 520 void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) 521 { 522 notImplemented(); 523 } 524 525 InterpolationQuality GraphicsContext::imageInterpolationQuality() const 526 { 527 notImplemented(); 528 return InterpolationDefault; 529 } 530 531 } 532