1 /* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef GraphicsOperation_h 27 #define GraphicsOperation_h 28 29 #include "Color.h" 30 #include "FloatRect.h" 31 #include "GlyphBuffer.h" 32 #include "Font.h" 33 #include "IntRect.h" 34 #include "PlatformGraphicsContext.h" 35 #include "PlatformGraphicsContextSkia.h" 36 #include "SkCanvas.h" 37 #include "SkShader.h" 38 #include "SkRefCnt.h" 39 40 #include <utils/threads.h> 41 #include <wtf/text/CString.h> 42 43 #define TYPE_CASE(type) case type: return #type; 44 45 #define DEBUG_GRAPHICS_OPERATIONS false 46 47 #if DEBUG_GRAPHICS_OPERATIONS 48 #define TYPE(x) virtual OperationType type() { return x; } 49 #else 50 #define TYPE(x) 51 #endif 52 53 namespace android { 54 class LinearAllocator; 55 } 56 57 namespace WebCore { 58 59 class CanvasState; 60 61 namespace GraphicsOperation { 62 63 class Operation { 64 public: 65 Operation() 66 : m_state(0) 67 , m_canvasState(0) 68 {} 69 70 void* operator new(size_t size, android::LinearAllocator* allocator); 71 72 // Purposely not implemented - use a LinearAllocator please 73 void* operator new(size_t size); 74 void operator delete(void* ptr); 75 76 // This m_state is applied by ourselves 77 PlatformGraphicsContext::State* m_state; 78 // This is the canvas state that this operation needs 79 // Only used for drawing operations, state operations will be undefined 80 CanvasState* m_canvasState; 81 82 bool apply(PlatformGraphicsContext* context) { 83 if (m_state) 84 context->setRawState(m_state); 85 return applyImpl(context); 86 } 87 virtual bool applyImpl(PlatformGraphicsContext* context) = 0; 88 virtual ~Operation() {} 89 90 virtual const IntRect* opaqueRect() { return 0; } 91 virtual bool isOpaque() { return false; } 92 virtual void setOpaqueRect(const IntRect& bounds) {} 93 94 #if DEBUG_GRAPHICS_OPERATIONS 95 typedef enum { UndefinedOperation 96 // Matrix operations 97 , ConcatCTMOperation 98 , ScaleOperation 99 , RotateOperation 100 , TranslateOperation 101 // Clipping 102 , InnerRoundedRectClipOperation 103 , ClipOperation 104 , ClipPathOperation 105 , ClipOutOperation 106 , ClearRectOperation 107 // Drawing 108 , DrawBitmapPatternOperation 109 , DrawBitmapRectOperation 110 , DrawConvexPolygonQuadOperation 111 , DrawEllipseOperation 112 , DrawFocusRingOperation 113 , DrawLineOperation 114 , DrawLineForTextOperation 115 , DrawLineForTextCheckingOperation 116 , DrawRectOperation 117 , FillPathOperation 118 , FillRectOperation 119 , FillRoundedRectOperation 120 , StrokeArcOperation 121 , StrokePathOperation 122 , StrokeRectOperation 123 , DrawMediaButtonOperation 124 // Text 125 , DrawPosTextOperation 126 } OperationType; 127 128 const char* name() 129 { 130 switch (type()) { 131 TYPE_CASE(UndefinedOperation) 132 // Matrix operations 133 TYPE_CASE(ConcatCTMOperation) 134 TYPE_CASE(ScaleOperation) 135 TYPE_CASE(RotateOperation) 136 TYPE_CASE(TranslateOperation) 137 // Clipping 138 TYPE_CASE(InnerRoundedRectClipOperation) 139 TYPE_CASE(ClipOperation) 140 TYPE_CASE(ClipPathOperation) 141 TYPE_CASE(ClipOutOperation) 142 TYPE_CASE(ClearRectOperation) 143 // Drawing 144 TYPE_CASE(DrawBitmapPatternOperation) 145 TYPE_CASE(DrawBitmapRectOperation) 146 TYPE_CASE(DrawConvexPolygonQuadOperation) 147 TYPE_CASE(DrawEllipseOperation) 148 TYPE_CASE(DrawFocusRingOperation) 149 TYPE_CASE(DrawLineOperation) 150 TYPE_CASE(DrawLineForTextOperation) 151 TYPE_CASE(DrawLineForTextCheckingOperation) 152 TYPE_CASE(DrawRectOperation) 153 TYPE_CASE(FillPathOperation) 154 TYPE_CASE(FillRectOperation) 155 TYPE_CASE(FillRoundedRectOperation) 156 TYPE_CASE(StrokeArcOperation) 157 TYPE_CASE(StrokePathOperation) 158 TYPE_CASE(StrokeRectOperation) 159 TYPE_CASE(DrawMediaButtonOperation) 160 // Text 161 TYPE_CASE(DrawPosTextOperation) 162 } 163 return "Undefined"; 164 } 165 #endif 166 TYPE(UndefinedOperation) 167 }; 168 169 class PossiblyOpaqueOperation : public Operation { 170 public: 171 virtual const IntRect* opaqueRect() { return &m_absoluteOpaqueRect; } 172 virtual void setOpaqueRect(const IntRect& bounds) { m_absoluteOpaqueRect = bounds; } 173 174 private: 175 IntRect m_absoluteOpaqueRect; 176 }; 177 178 //************************************** 179 // Matrix operations 180 //************************************** 181 182 class ConcatCTM : public Operation { 183 public: 184 ConcatCTM(const AffineTransform& affine) : m_matrix(affine) {} 185 virtual bool applyImpl(PlatformGraphicsContext* context) { 186 context->concatCTM(m_matrix); 187 return true; 188 } 189 TYPE(ConcatCTMOperation) 190 private: 191 AffineTransform m_matrix; 192 }; 193 194 class Rotate : public Operation { 195 public: 196 Rotate(float angleInRadians) : m_angle(angleInRadians) {} 197 virtual bool applyImpl(PlatformGraphicsContext* context) { 198 context->rotate(m_angle); 199 return true; 200 } 201 TYPE(RotateOperation) 202 private: 203 float m_angle; 204 }; 205 206 class Scale : public Operation { 207 public: 208 Scale(const FloatSize& size) : m_scale(size) {} 209 virtual bool applyImpl(PlatformGraphicsContext* context) { 210 context->scale(m_scale); 211 return true; 212 } 213 TYPE(ScaleOperation) 214 private: 215 FloatSize m_scale; 216 }; 217 218 class Translate : public Operation { 219 public: 220 Translate(float x, float y) : m_x(x), m_y(y) {} 221 virtual bool applyImpl(PlatformGraphicsContext* context) { 222 context->translate(m_x, m_y); 223 return true; 224 } 225 TYPE(TranslateOperation) 226 private: 227 float m_x; 228 float m_y; 229 }; 230 231 //************************************** 232 // Clipping 233 //************************************** 234 235 class InnerRoundedRectClip : public Operation { 236 public: 237 InnerRoundedRectClip(const IntRect& rect, int thickness) 238 : m_rect(rect), m_thickness(thickness) {} 239 virtual bool applyImpl(PlatformGraphicsContext* context) { 240 context->addInnerRoundedRectClip(m_rect, m_thickness); 241 return true; 242 } 243 TYPE(InnerRoundedRectClipOperation) 244 private: 245 IntRect m_rect; 246 int m_thickness; 247 }; 248 249 class Clip : public Operation { 250 public: 251 Clip(const FloatRect& rect) : m_rect(rect) {} 252 virtual bool applyImpl(PlatformGraphicsContext* context) { 253 return context->clip(m_rect); 254 } 255 TYPE(ClipOperation) 256 private: 257 const FloatRect m_rect; 258 }; 259 260 class ClipPath : public Operation { 261 public: 262 ClipPath(const Path& path, bool clipout = false) 263 : m_path(path), m_clipOut(clipout), m_hasWindRule(false) {} 264 void setWindRule(WindRule rule) { m_windRule = rule; m_hasWindRule = true; } 265 virtual bool applyImpl(PlatformGraphicsContext* context) { 266 if (m_hasWindRule) { 267 return context->clipPath(m_path, m_windRule); 268 } 269 if (m_clipOut) 270 return context->clipOut(m_path); 271 else 272 return context->clip(m_path); 273 } 274 TYPE(ClipPathOperation) 275 private: 276 const Path m_path; 277 bool m_clipOut; 278 WindRule m_windRule; 279 bool m_hasWindRule; 280 }; 281 282 class ClipOut : public Operation { 283 public: 284 ClipOut(const IntRect& rect) : m_rect(rect) {} 285 virtual bool applyImpl(PlatformGraphicsContext* context) { 286 return context->clipOut(m_rect); 287 } 288 TYPE(ClipOutOperation) 289 private: 290 const IntRect m_rect; 291 }; 292 293 class ClearRect : public Operation { 294 public: 295 ClearRect(const FloatRect& rect) : m_rect(rect) {} 296 virtual bool applyImpl(PlatformGraphicsContext* context) { 297 context->clearRect(m_rect); 298 return true; 299 } 300 TYPE(ClearRectOperation) 301 private: 302 FloatRect m_rect; 303 }; 304 305 //************************************** 306 // Drawing 307 //************************************** 308 309 class DrawBitmapPattern : public PossiblyOpaqueOperation { 310 public: 311 DrawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix, 312 CompositeOperator op, const FloatRect& destRect) 313 : m_bitmap(bitmap), m_matrix(matrix), m_operator(op), m_destRect(destRect) {} 314 virtual bool applyImpl(PlatformGraphicsContext* context) { 315 context->drawBitmapPattern(m_bitmap, m_matrix, m_operator, m_destRect); 316 return true; 317 } 318 virtual bool isOpaque() { return m_bitmap.isOpaque(); } 319 TYPE(DrawBitmapPatternOperation) 320 321 private: 322 SkBitmap m_bitmap; 323 SkMatrix m_matrix; 324 CompositeOperator m_operator; 325 FloatRect m_destRect; 326 }; 327 328 class DrawBitmapRect : public PossiblyOpaqueOperation { 329 public: 330 DrawBitmapRect(const SkBitmap& bitmap, const SkIRect& srcR, 331 const SkRect& dstR, CompositeOperator op) 332 : m_bitmap(bitmap), m_srcR(srcR), m_dstR(dstR), m_operator(op) {} 333 virtual bool applyImpl(PlatformGraphicsContext* context) { 334 context->drawBitmapRect(m_bitmap, &m_srcR, m_dstR, m_operator); 335 return true; 336 } 337 virtual bool isOpaque() { return m_bitmap.isOpaque(); } 338 TYPE(DrawBitmapRectOperation) 339 private: 340 SkBitmap m_bitmap; 341 SkIRect m_srcR; 342 SkRect m_dstR; 343 CompositeOperator m_operator; 344 }; 345 346 class DrawConvexPolygonQuad : public Operation { 347 public: 348 DrawConvexPolygonQuad(const FloatPoint* points, bool shouldAntiAlias) 349 : m_shouldAntiAlias(shouldAntiAlias) 350 { 351 memcpy(m_points, points, 4 * sizeof(FloatPoint)); 352 } 353 virtual bool applyImpl(PlatformGraphicsContext* context) { 354 context->drawConvexPolygon(4, m_points, m_shouldAntiAlias); 355 return true; 356 } 357 TYPE(DrawConvexPolygonQuadOperation) 358 private: 359 bool m_shouldAntiAlias; 360 FloatPoint m_points[4]; 361 }; 362 363 class DrawEllipse : public Operation { 364 public: 365 DrawEllipse(const IntRect& rect) : m_rect(rect) {} 366 virtual bool applyImpl(PlatformGraphicsContext* context) { 367 context->drawEllipse(m_rect); 368 return true; 369 } 370 TYPE(DrawEllipseOperation) 371 private: 372 IntRect m_rect; 373 }; 374 375 class DrawFocusRing : public Operation { 376 public: 377 DrawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) 378 : m_rects(rects) 379 , m_width(width) 380 , m_offset(offset) 381 , m_color(color) 382 {} 383 virtual bool applyImpl(PlatformGraphicsContext* context) { 384 context->drawFocusRing(m_rects, m_width, m_offset, m_color); 385 return true; 386 } 387 TYPE(DrawFocusRingOperation) 388 private: 389 Vector<IntRect> m_rects; 390 int m_width; 391 int m_offset; 392 Color m_color; 393 }; 394 395 class DrawLine : public Operation { 396 public: 397 DrawLine(const IntPoint& point1, const IntPoint& point2) 398 : m_point1(point1), m_point2(point2) {} 399 virtual bool applyImpl(PlatformGraphicsContext* context) { 400 context->drawLine(m_point1, m_point2); 401 return true; 402 } 403 TYPE(DrawLineOperation) 404 private: 405 IntPoint m_point1; 406 IntPoint m_point2; 407 }; 408 409 class DrawLineForText : public Operation { 410 public: 411 DrawLineForText(const FloatPoint& pt, float width) 412 : m_point(pt), m_width(width) {} 413 virtual bool applyImpl(PlatformGraphicsContext* context) { 414 context->drawLineForText(m_point, m_width); 415 return true; 416 } 417 TYPE(DrawLineForTextOperation) 418 private: 419 FloatPoint m_point; 420 float m_width; 421 }; 422 423 class DrawLineForTextChecking : public Operation { 424 public: 425 DrawLineForTextChecking(const FloatPoint& pt, float width, 426 GraphicsContext::TextCheckingLineStyle lineStyle) 427 : m_point(pt), m_width(width), m_lineStyle(lineStyle) {} 428 virtual bool applyImpl(PlatformGraphicsContext* context) { 429 context->drawLineForTextChecking(m_point, m_width, m_lineStyle); 430 return true; 431 } 432 TYPE(DrawLineForTextCheckingOperation) 433 private: 434 FloatPoint m_point; 435 float m_width; 436 GraphicsContext::TextCheckingLineStyle m_lineStyle; 437 }; 438 439 class DrawRect : public Operation { 440 public: 441 DrawRect(const IntRect& rect) : m_rect(rect) {} 442 virtual bool applyImpl(PlatformGraphicsContext* context) { 443 context->drawRect(m_rect); 444 return true; 445 } 446 TYPE(DrawRectOperation) 447 private: 448 IntRect m_rect; 449 }; 450 451 class FillPath : public Operation { 452 public: 453 FillPath(const Path& pathToFill, WindRule fillRule) 454 : m_path(pathToFill), m_fillRule(fillRule) {} 455 virtual bool applyImpl(PlatformGraphicsContext* context) { 456 context->fillPath(m_path, m_fillRule); 457 return true; 458 } 459 TYPE(FillPathOperation) 460 private: 461 Path m_path; 462 WindRule m_fillRule; 463 }; 464 465 class FillRect : public PossiblyOpaqueOperation { 466 public: 467 FillRect(const FloatRect& rect) : m_rect(rect), m_hasColor(false) {} 468 void setColor(Color c) { m_color = c; m_hasColor = true; } 469 virtual bool applyImpl(PlatformGraphicsContext* context) { 470 if (m_hasColor) 471 context->fillRect(m_rect, m_color); 472 else 473 context->fillRect(m_rect); 474 return true; 475 } 476 virtual bool isOpaque() { return (m_hasColor && !m_color.hasAlpha()) 477 || (!m_hasColor && SkColorGetA(m_state->fillColor) == 0xFF); } 478 TYPE(FillRectOperation) 479 private: 480 FloatRect m_rect; 481 Color m_color; 482 bool m_hasColor; 483 }; 484 485 class FillRoundedRect : public Operation { 486 public: 487 FillRoundedRect(const IntRect& rect, 488 const IntSize& topLeft, 489 const IntSize& topRight, 490 const IntSize& bottomLeft, 491 const IntSize& bottomRight, 492 const Color& color) 493 : m_rect(rect) 494 , m_topLeft(topLeft) 495 , m_topRight(topRight) 496 , m_bottomLeft(bottomLeft) 497 , m_bottomRight(bottomRight) 498 , m_color(color) 499 {} 500 virtual bool applyImpl(PlatformGraphicsContext* context) { 501 context->fillRoundedRect(m_rect, m_topLeft, m_topRight, 502 m_bottomLeft, m_bottomRight, 503 m_color); 504 return true; 505 } 506 TYPE(FillRoundedRectOperation) 507 private: 508 IntRect m_rect; 509 IntSize m_topLeft; 510 IntSize m_topRight; 511 IntSize m_bottomLeft; 512 IntSize m_bottomRight; 513 Color m_color; 514 }; 515 516 class StrokeArc : public Operation { 517 public: 518 StrokeArc(const IntRect& r, int startAngle, int angleSpan) 519 : m_rect(r) 520 , m_startAngle(startAngle) 521 , m_angleSpan(angleSpan) 522 {} 523 virtual bool applyImpl(PlatformGraphicsContext* context) { 524 context->strokeArc(m_rect, m_startAngle, m_angleSpan); 525 return true; 526 } 527 TYPE(StrokeArcOperation) 528 private: 529 IntRect m_rect; 530 int m_startAngle; 531 int m_angleSpan; 532 }; 533 534 class StrokePath : public Operation { 535 public: 536 StrokePath(const Path& path) : m_path(path) {} 537 virtual bool applyImpl(PlatformGraphicsContext* context) { 538 context->strokePath(m_path); 539 return true; 540 } 541 TYPE(StrokePathOperation) 542 private: 543 Path m_path; 544 }; 545 546 547 class StrokeRect : public Operation { 548 public: 549 StrokeRect(const FloatRect& rect, float lineWidth) 550 : m_rect(rect), m_lineWidth(lineWidth) {} 551 virtual bool applyImpl(PlatformGraphicsContext* context) { 552 context->strokeRect(m_rect, m_lineWidth); 553 return true; 554 } 555 TYPE(StrokeRectOperation) 556 private: 557 FloatRect m_rect; 558 float m_lineWidth; 559 }; 560 561 class DrawMediaButton : public Operation { 562 public: 563 DrawMediaButton(const IntRect& rect, RenderSkinMediaButton::MediaButton buttonType, 564 bool translucent, bool drawBackground, 565 const IntRect& thumb) 566 : m_rect(rect) 567 , m_thumb(thumb) 568 , m_buttonType(buttonType) 569 , m_translucent(translucent) 570 , m_drawBackground(drawBackground) 571 {} 572 virtual bool applyImpl(PlatformGraphicsContext* context) { 573 context->drawMediaButton(m_rect, m_buttonType, m_translucent, m_drawBackground, m_thumb); 574 return true; 575 } 576 TYPE(DrawMediaButtonOperation) 577 private: 578 IntRect m_rect; 579 IntRect m_thumb; 580 RenderSkinMediaButton::MediaButton m_buttonType; 581 bool m_translucent : 1; 582 bool m_drawBackground : 1; 583 }; 584 585 //************************************** 586 // Text 587 //************************************** 588 589 class DrawPosText : public Operation { 590 public: 591 DrawPosText(const void* text, size_t byteLength, 592 const SkPoint pos[], const SkPaint* paint) 593 : m_text(text) 594 , m_byteLength(byteLength) 595 , m_pos(pos) 596 , m_paint(paint) 597 {} 598 virtual bool applyImpl(PlatformGraphicsContext* context) { 599 context->drawPosText(m_text, m_byteLength, m_pos, *m_paint); 600 return true; 601 } 602 TYPE(DrawPosTextOperation) 603 private: 604 const void* m_text; 605 size_t m_byteLength; 606 const SkPoint* m_pos; 607 const SkPaint* m_paint; 608 }; 609 610 } 611 612 } 613 614 #endif // GraphicsOperation_h 615