Home | History | Annotate | Download | only in context
      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