/* * Copyright (C) 2011 Research In Motion Limited. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef InstrumentedPlatformCanvas_h #define InstrumentedPlatformCanvas_h #include "SkCanvas.h" #define DEBUG_SKIA_DRAWING 0 #if DEBUG_SKIA_DRAWING #include "AndroidLog.h" // NOTE: AndroidLog.h normally shouldn't be included in a header #include "FloatRect.h" #define WRAPCANVAS_LOG_ENTRY(...) {ALOGD("non-rect %s, m_isSolidColor %d", __FUNCTION__, m_isSolidColor);} #else #define WRAPCANVAS_LOG_ENTRY(...) ((void)0) #endif namespace WebCore { class InstrumentedPlatformCanvas : public SkCanvas { public: InstrumentedPlatformCanvas(int width, int height, Color initialColor) : m_size(width, height) , m_isSolidColor(true) , m_solidColor(initialColor) { } virtual ~InstrumentedPlatformCanvas() { } bool isSolidColor() const { return m_isSolidColor; } Color solidColor() const { return m_solidColor; } // overrides from SkCanvas virtual int save(SaveFlags flags = kMatrixClip_SaveFlag) { WRAPCANVAS_LOG_ENTRY(""); return SkCanvas::save(flags); } virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; return SkCanvas::saveLayer(bounds, paint, flags); } virtual void restore() { WRAPCANVAS_LOG_ENTRY(""); SkCanvas::restore(); } virtual bool translate(SkScalar dx, SkScalar dy) { WRAPCANVAS_LOG_ENTRY(""); return SkCanvas::translate(dx, dy); } virtual bool scale(SkScalar sx, SkScalar sy) { WRAPCANVAS_LOG_ENTRY(""); return SkCanvas::scale(sx, sy); } virtual bool rotate(SkScalar degrees) { WRAPCANVAS_LOG_ENTRY(""); return SkCanvas::rotate(degrees); } virtual bool skew(SkScalar sx, SkScalar sy) { WRAPCANVAS_LOG_ENTRY(""); return SkCanvas::skew(sx, sy); } virtual bool concat(const SkMatrix& matrix) { WRAPCANVAS_LOG_ENTRY(""); return SkCanvas::concat(matrix); } virtual void setMatrix(const SkMatrix& matrix) { WRAPCANVAS_LOG_ENTRY(""); SkCanvas::setMatrix(matrix); } virtual bool clipRect(const SkRect& rect, SkRegion::Op op) { WRAPCANVAS_LOG_ENTRY(""); return SkCanvas::clipRect(rect, op); } virtual bool clipPath(const SkPath& path, SkRegion::Op op) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; return SkCanvas::clipPath(path, op); } virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) { WRAPCANVAS_LOG_ENTRY(""); if (!region.isRect()) m_isSolidColor = false; return SkCanvas::clipRegion(region, op); } virtual void clear(SkColor color) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = true; m_solidColor = Color(color); SkCanvas::clear(color); } virtual void drawPaint(const SkPaint& paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawPaint(paint); } virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawPoints(mode, count, pts, paint); } bool rectFullyOverlaps(const SkRect& rect) { IntRect canvasRect(IntPoint(), m_size); if (getTotalMatrix().rectStaysRect() && getTotalClip().contains(canvasRect)) { const SkMatrix& matrix = getTotalMatrix(); SkRect mapped; matrix.mapRect(&mapped, rect); return mapped.contains(canvasRect); } return false; } virtual void drawRect(const SkRect& rect, const SkPaint& paint) { #if DEBUG_SKIA_DRAWING FloatRect rectToDraw = rect; ALOGD("drawrect " FLOAT_RECT_FORMAT ", is solid %d", FLOAT_RECT_ARGS(rectToDraw), m_isSolidColor); #endif if (m_isSolidColor) { Color color = solidColor(paint); if (color != m_solidColor) { if (color.isValid() && rectFullyOverlaps(rect)) m_solidColor = color; else m_isSolidColor = false; } } SkCanvas::drawRect(rect, paint); } virtual void drawPath(const SkPath& path, const SkPaint& paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawPath(path, paint); } virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawBitmap(bitmap, left, top, paint); } virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, const SkRect& dst, const SkPaint* paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawBitmapRect(bitmap, src, dst, paint); } virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawBitmapMatrix(bitmap, matrix, paint); } virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint = 0) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawBitmapNine(bitmap, center, dst, paint); } virtual void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawSprite(bitmap, left, top, paint); } virtual void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawText(text, byteLength, x, y, paint); } virtual void drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawPosText(text, byteLength, pos, paint); } virtual void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawPosTextH(text, byteLength, xpos, constY, paint); } virtual void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawTextOnPath(text, byteLength, path, matrix, paint); } virtual void drawPicture(SkPicture& picture) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawPicture(picture); } virtual void drawVertices(VertexMode mode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], const SkColor colors[], SkXfermode* xfermode, const uint16_t indices[], int indexCount, const SkPaint& paint) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawVertices(mode, vertexCount, vertices, texs, colors, xfermode, indices, indexCount, paint); } virtual void drawData(const void* data, size_t size) { WRAPCANVAS_LOG_ENTRY(""); m_isSolidColor = false; SkCanvas::drawData(data, size); } private: Color solidColor(const SkPaint& paint) { if (paint.getStyle() != SkPaint::kFill_Style) return Color(); if (paint.getLooper() || paint.getShader()) return Color(); SkXfermode::Mode mode; SkXfermode::AsMode(paint.getXfermode(), &mode); if (mode == SkXfermode::kClear_Mode) return Color(0, 0, 0, 0); if ((mode == SkXfermode::kSrcOver_Mode && paint.getAlpha() == 255) || mode == SkXfermode::kSrc_Mode) return Color(paint.getColor()); return Color(); } IntSize m_size; bool m_isSolidColor; Color m_solidColor; SkPaint m_solidPaint; }; } // namespace WebCore #endif // InstrumentedPlatformCanvas_h