Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2011 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 #ifndef InstrumentedPlatformCanvas_h
     20 #define InstrumentedPlatformCanvas_h
     21 
     22 #include "SkCanvas.h"
     23 
     24 #define DEBUG_SKIA_DRAWING 0
     25 #if DEBUG_SKIA_DRAWING
     26 #include "AndroidLog.h" // NOTE: AndroidLog.h normally shouldn't be included in a header
     27 #include "FloatRect.h"
     28 #define WRAPCANVAS_LOG_ENTRY(...) {ALOGD("non-rect %s, m_isSolidColor %d", __FUNCTION__, m_isSolidColor);}
     29 #else
     30 #define WRAPCANVAS_LOG_ENTRY(...) ((void)0)
     31 #endif
     32 
     33 namespace WebCore {
     34 
     35 class InstrumentedPlatformCanvas : public SkCanvas {
     36 public:
     37     InstrumentedPlatformCanvas(int width, int height, Color initialColor)
     38         : m_size(width, height)
     39         , m_isSolidColor(true)
     40         , m_solidColor(initialColor)
     41     {
     42     }
     43 
     44     virtual ~InstrumentedPlatformCanvas() { }
     45 
     46     bool isSolidColor() const { return m_isSolidColor; }
     47     Color solidColor() const { return m_solidColor; }
     48 
     49     // overrides from SkCanvas
     50     virtual int save(SaveFlags flags = kMatrixClip_SaveFlag)
     51     {
     52         WRAPCANVAS_LOG_ENTRY("");
     53         return SkCanvas::save(flags);
     54     }
     55 
     56     virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags)
     57     {
     58         WRAPCANVAS_LOG_ENTRY("");
     59         m_isSolidColor = false;
     60         return SkCanvas::saveLayer(bounds, paint, flags);
     61     }
     62 
     63     virtual void restore()
     64     {
     65         WRAPCANVAS_LOG_ENTRY("");
     66         SkCanvas::restore();
     67     }
     68 
     69     virtual bool translate(SkScalar dx, SkScalar dy)
     70     {
     71         WRAPCANVAS_LOG_ENTRY("");
     72         return SkCanvas::translate(dx, dy);
     73     }
     74 
     75     virtual bool scale(SkScalar sx, SkScalar sy)
     76     {
     77         WRAPCANVAS_LOG_ENTRY("");
     78         return SkCanvas::scale(sx, sy);
     79     }
     80 
     81     virtual bool rotate(SkScalar degrees)
     82     {
     83         WRAPCANVAS_LOG_ENTRY("");
     84         return SkCanvas::rotate(degrees);
     85     }
     86 
     87     virtual bool skew(SkScalar sx, SkScalar sy)
     88     {
     89         WRAPCANVAS_LOG_ENTRY("");
     90         return SkCanvas::skew(sx, sy);
     91     }
     92 
     93     virtual bool concat(const SkMatrix& matrix)
     94     {
     95         WRAPCANVAS_LOG_ENTRY("");
     96         return SkCanvas::concat(matrix);
     97     }
     98 
     99     virtual void setMatrix(const SkMatrix& matrix)
    100     {
    101         WRAPCANVAS_LOG_ENTRY("");
    102         SkCanvas::setMatrix(matrix);
    103     }
    104 
    105     virtual bool clipRect(const SkRect& rect, SkRegion::Op op)
    106     {
    107         WRAPCANVAS_LOG_ENTRY("");
    108         return SkCanvas::clipRect(rect, op);
    109     }
    110 
    111     virtual bool clipPath(const SkPath& path, SkRegion::Op op)
    112     {
    113         WRAPCANVAS_LOG_ENTRY("");
    114         m_isSolidColor = false;
    115         return SkCanvas::clipPath(path, op);
    116     }
    117 
    118     virtual bool clipRegion(const SkRegion& region, SkRegion::Op op)
    119     {
    120         WRAPCANVAS_LOG_ENTRY("");
    121         if (!region.isRect())
    122             m_isSolidColor = false;
    123         return SkCanvas::clipRegion(region, op);
    124     }
    125 
    126     virtual void clear(SkColor color)
    127     {
    128         WRAPCANVAS_LOG_ENTRY("");
    129         m_isSolidColor = true;
    130         m_solidColor = Color(color);
    131         SkCanvas::clear(color);
    132     }
    133 
    134     virtual void drawPaint(const SkPaint& paint)
    135     {
    136         WRAPCANVAS_LOG_ENTRY("");
    137         m_isSolidColor = false;
    138         SkCanvas::drawPaint(paint);
    139     }
    140 
    141     virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
    142             const SkPaint& paint)
    143     {
    144         WRAPCANVAS_LOG_ENTRY("");
    145         m_isSolidColor = false;
    146         SkCanvas::drawPoints(mode, count, pts, paint);
    147     }
    148 
    149     bool rectFullyOverlaps(const SkRect& rect)
    150     {
    151         IntRect canvasRect(IntPoint(), m_size);
    152         if (getTotalMatrix().rectStaysRect()
    153             && getTotalClip().contains(canvasRect)) {
    154             const SkMatrix& matrix = getTotalMatrix();
    155             SkRect mapped;
    156             matrix.mapRect(&mapped, rect);
    157             return mapped.contains(canvasRect);
    158         }
    159         return false;
    160     }
    161 
    162     virtual void drawRect(const SkRect& rect, const SkPaint& paint)
    163     {
    164 
    165 #if DEBUG_SKIA_DRAWING
    166         FloatRect rectToDraw = rect;
    167         ALOGD("drawrect " FLOAT_RECT_FORMAT ", is solid %d", FLOAT_RECT_ARGS(rectToDraw), m_isSolidColor);
    168 #endif
    169 
    170         if (m_isSolidColor) {
    171             Color color = solidColor(paint);
    172             if (color != m_solidColor) {
    173                 if (color.isValid() && rectFullyOverlaps(rect))
    174                     m_solidColor = color;
    175                 else
    176                     m_isSolidColor = false;
    177             }
    178         }
    179 
    180         SkCanvas::drawRect(rect, paint);
    181     }
    182 
    183     virtual void drawPath(const SkPath& path, const SkPaint& paint)
    184     {
    185         WRAPCANVAS_LOG_ENTRY("");
    186         m_isSolidColor = false;
    187         SkCanvas::drawPath(path, paint);
    188     }
    189 
    190     virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
    191             SkScalar top, const SkPaint* paint)
    192     {
    193         WRAPCANVAS_LOG_ENTRY("");
    194         m_isSolidColor = false;
    195         SkCanvas::drawBitmap(bitmap, left, top, paint);
    196     }
    197 
    198     virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
    199             const SkRect& dst, const SkPaint* paint)
    200     {
    201         WRAPCANVAS_LOG_ENTRY("");
    202         m_isSolidColor = false;
    203         SkCanvas::drawBitmapRectToRect(bitmap, src, dst, paint);
    204     }
    205 
    206     virtual void drawBitmapMatrix(const SkBitmap& bitmap,
    207             const SkMatrix& matrix, const SkPaint* paint)
    208     {
    209         WRAPCANVAS_LOG_ENTRY("");
    210         m_isSolidColor = false;
    211         SkCanvas::drawBitmapMatrix(bitmap, matrix, paint);
    212     }
    213 
    214     virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
    215                                 const SkRect& dst, const SkPaint* paint = 0)
    216     {
    217         WRAPCANVAS_LOG_ENTRY("");
    218         m_isSolidColor = false;
    219         SkCanvas::drawBitmapNine(bitmap, center, dst, paint);
    220     }
    221 
    222     virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
    223             const SkPaint* paint)
    224     {
    225         WRAPCANVAS_LOG_ENTRY("");
    226         m_isSolidColor = false;
    227         SkCanvas::drawSprite(bitmap, left, top, paint);
    228     }
    229 
    230     virtual void drawText(const void* text, size_t byteLength, SkScalar x,
    231             SkScalar y, const SkPaint& paint)
    232     {
    233         WRAPCANVAS_LOG_ENTRY("");
    234         m_isSolidColor = false;
    235         SkCanvas::drawText(text, byteLength, x, y, paint);
    236     }
    237 
    238     virtual void drawPosText(const void* text, size_t byteLength,
    239             const SkPoint pos[], const SkPaint& paint)
    240     {
    241         WRAPCANVAS_LOG_ENTRY("");
    242         m_isSolidColor = false;
    243         SkCanvas::drawPosText(text, byteLength, pos, paint);
    244     }
    245 
    246     virtual void drawPosTextH(const void* text, size_t byteLength,
    247             const SkScalar xpos[], SkScalar constY, const SkPaint& paint)
    248     {
    249         WRAPCANVAS_LOG_ENTRY("");
    250         m_isSolidColor = false;
    251         SkCanvas::drawPosTextH(text, byteLength, xpos, constY, paint);
    252     }
    253 
    254     virtual void drawTextOnPath(const void* text, size_t byteLength,
    255             const SkPath& path, const SkMatrix* matrix, const SkPaint& paint)
    256     {
    257         WRAPCANVAS_LOG_ENTRY("");
    258         m_isSolidColor = false;
    259         SkCanvas::drawTextOnPath(text, byteLength, path, matrix, paint);
    260     }
    261 
    262     virtual void drawPicture(SkPicture& picture)
    263     {
    264         WRAPCANVAS_LOG_ENTRY("");
    265         m_isSolidColor = false;
    266         SkCanvas::drawPicture(picture);
    267     }
    268 
    269     virtual void drawVertices(VertexMode mode, int vertexCount,
    270             const SkPoint vertices[], const SkPoint texs[],
    271             const SkColor colors[], SkXfermode* xfermode,
    272             const uint16_t indices[], int indexCount, const SkPaint& paint)
    273     {
    274         WRAPCANVAS_LOG_ENTRY("");
    275         m_isSolidColor = false;
    276         SkCanvas::drawVertices(mode, vertexCount, vertices, texs,
    277                                colors, xfermode, indices, indexCount, paint);
    278     }
    279 
    280     virtual void drawData(const void* data, size_t size)
    281     {
    282         WRAPCANVAS_LOG_ENTRY("");
    283         m_isSolidColor = false;
    284         SkCanvas::drawData(data, size);
    285     }
    286 
    287 private:
    288     Color solidColor(const SkPaint& paint)
    289     {
    290         if (paint.getStyle() != SkPaint::kFill_Style)
    291             return Color();
    292         if (paint.getLooper() || paint.getShader())
    293             return Color();
    294 
    295         SkXfermode::Mode mode;
    296         SkXfermode::AsMode(paint.getXfermode(), &mode);
    297         if (mode == SkXfermode::kClear_Mode)
    298             return Color(0, 0, 0, 0);
    299 
    300         if ((mode == SkXfermode::kSrcOver_Mode && paint.getAlpha() == 255)
    301             || mode == SkXfermode::kSrc_Mode)
    302             return Color(paint.getColor());
    303         return Color();
    304     }
    305 
    306     IntSize m_size;
    307     bool m_isSolidColor;
    308     Color m_solidColor;
    309     SkPaint m_solidPaint;
    310 };
    311 
    312 } // namespace WebCore
    313 
    314 #endif // InstrumentedPlatformCanvas_h
    315