SkDeferredCanvas.cpp revision 5e5a095a94281167056da707b03930f135748d71
14370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
24370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com/*
34370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com * Copyright 2011 Google Inc.
44370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com *
54370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com * Use of this source code is governed by a BSD-style license that can be
64370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com * found in the LICENSE file.
74370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com */
84370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
94370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com#include "SkDeferredCanvas.h"
104370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com#include "SkPaint.h"
124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com#include "SkShader.h"
134370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com#include "SkColorFilter.h"
144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com#include "SkDrawFilter.h"
154370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
164370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comnamespace {
174370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
18c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool isPaintOpaque(const SkPaint* paint,
19c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                   const SkBitmap* bmpReplacesShader = NULL) {
204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // TODO: SkXfermode should have a virtual isOpaque method, which would
214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // make it possible to test modes that do not have a Coeff representation.
2287f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org
2387f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org    if (!paint) {
2487f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org        return bmpReplacesShader ? bmpReplacesShader->isOpaque() : true;
2587f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org    }
2687f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org
274370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkXfermode::Coeff srcCoeff, dstCoeff;
2887f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org    if (SkXfermode::AsCoeff(paint->getXfermode(), &srcCoeff, &dstCoeff)){
294370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        switch (dstCoeff) {
304370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkXfermode::kZero_Coeff:
314370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return true;
324370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkXfermode::kISA_Coeff:
3387f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            if (paint->getAlpha() != 255) {
344370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
354370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
364370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            if (bmpReplacesShader) {
374370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                if (!bmpReplacesShader->isOpaque()) {
384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                    break;
394370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                }
4087f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            } else if (paint->getShader() && !paint->getShader()->isOpaque()) {
414370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
43c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org            if (paint->getColorFilter() &&
44c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                ((paint->getColorFilter()->getFlags() &
454370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
464370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
474370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return true;
494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkXfermode::kSA_Coeff:
5087f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            if (paint->getAlpha() != 0) {
514370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
524370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
53c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org            if (paint->getColorFilter() &&
54c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                ((paint->getColorFilter()->getFlags() &
554370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
564370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
574370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
584370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return true;
594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkXfermode::kSC_Coeff:
6087f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            if (paint->getColor() != 0) { // all components must be 0
614370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
624370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
6387f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org            if (bmpReplacesShader || paint->getShader()) {
644370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
654370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
66c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org            if (paint->getColorFilter() && (
67c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                (paint->getColorFilter()->getFlags() &
684370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
694370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                break;
704370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
714370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return true;
724370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        default:
734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            break;
744370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
754370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
764370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return false;
774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
784370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
794370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com} // unnamed namespace
804370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
81c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDeferredCanvas::SkDeferredCanvas() {
824370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    init();
834370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
844370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
85c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDeferredCanvas::SkDeferredCanvas(SkDevice* device) {
864370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    init();
874370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    setDevice(device);
884370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
894370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
904370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkDeferredCanvas::SkDeferredCanvas(SkDevice* device,
91c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                   DeviceContext* deviceContext) {
924370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    init();
934370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    setDevice(device);
944370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    setDeviceContext(deviceContext);
954370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
964370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
97c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::init() {
985e5a095a94281167056da707b03930f135748d71junov@chromium.org    fDeferredDrawing = true; // On by default
994370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1004370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
101c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::validate() const {
1024370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkASSERT(getDevice());
1034370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1044370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1055e5a095a94281167056da707b03930f135748d71junov@chromium.orgSkCanvas* SkDeferredCanvas::drawingCanvas() const {
1065e5a095a94281167056da707b03930f135748d71junov@chromium.org    validate();
1075e5a095a94281167056da707b03930f135748d71junov@chromium.org    return fDeferredDrawing ? getDeferredDevice()->recordingCanvas() :
1085e5a095a94281167056da707b03930f135748d71junov@chromium.org        getDeferredDevice()->immediateCanvas();
1095e5a095a94281167056da707b03930f135748d71junov@chromium.org}
1105e5a095a94281167056da707b03930f135748d71junov@chromium.org
111c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::flushIfNeeded(const SkBitmap& bitmap) {
1124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    validate();
1134370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (fDeferredDrawing) {
1144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        getDeferredDevice()->flushIfNeeded(bitmap);
1154370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
1164370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1174370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
118c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDeferredCanvas::DeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
1194370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return static_cast<SkDeferredCanvas::DeferredDevice*>(getDevice());
1204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
122c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::setDeferredDrawing(bool val) {
1234370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    validate(); // Must set device before calling this method
1245e5a095a94281167056da707b03930f135748d71junov@chromium.org    SkASSERT(drawingCanvas()->getSaveCount() == 1);
1254370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (val != fDeferredDrawing) {
1264370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        if (fDeferredDrawing) {
1275e5a095a94281167056da707b03930f135748d71junov@chromium.org            // Going live.
1284370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            getDeferredDevice()->flushPending();
1294370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
1304370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        fDeferredDrawing = val;
1314370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
1324370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1334370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
134c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDeferredCanvas::~SkDeferredCanvas() {
1354370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1364370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
137c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDevice* SkDeferredCanvas::setDevice(SkDevice* device) {
1384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    INHERITED::setDevice(SkNEW_ARGS(DeferredDevice, (device)))->unref();
1394370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return device;
1404370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1414370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkDeferredCanvas::DeviceContext* SkDeferredCanvas::setDeviceContext(
143c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    DeviceContext* deviceContext) {
144c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org
1454370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    DeferredDevice* deferredDevice = getDeferredDevice();
1464370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkASSERT(deferredDevice);
1474370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (deferredDevice) {
1484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        deferredDevice->setDeviceContext(deviceContext);
1494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
1504370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return deviceContext;
1514370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
1524370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1534370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::isFullFrame(const SkRect* rect,
154c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                   const SkPaint* paint) const {
1555e5a095a94281167056da707b03930f135748d71junov@chromium.org    SkCanvas* canvas = drawingCanvas();
1564370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkISize canvasSize = getDeviceSize();
1574370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (rect) {
1584370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        if (!canvas->getTotalMatrix().rectStaysRect()) {
1594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return false; // conservative
1604370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
1614370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1624370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        SkRect transformedRect;
1634370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas->getTotalMatrix().mapRect(&transformedRect, *rect);
1644370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1654370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        if (paint) {
1664370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            SkPaint::Style paintStyle = paint->getStyle();
1674370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            if (!(paintStyle == SkPaint::kFill_Style ||
1684370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                paintStyle == SkPaint::kStrokeAndFill_Style)) {
1694370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                return false;
1704370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
1714370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            if (paint->getMaskFilter() || paint->getLooper()
1724370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                || paint->getPathEffect() || paint->getImageFilter()) {
1734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                return false; // conservative
1744370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
1754370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
1764370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        // The following test holds with AA enabled, and is conservative
1784370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        // by a 0.5 pixel margin with AA disabled
179b1e218e782261304440199642f1b98e7ba96b525junov@chromium.org        if (transformedRect.fLeft > SkIntToScalar(0) ||
180b1e218e782261304440199642f1b98e7ba96b525junov@chromium.org            transformedRect.fTop > SkIntToScalar(0) ||
181b1e218e782261304440199642f1b98e7ba96b525junov@chromium.org            transformedRect.fRight < SkIntToScalar(canvasSize.fWidth) ||
182b1e218e782261304440199642f1b98e7ba96b525junov@chromium.org            transformedRect.fBottom < SkIntToScalar(canvasSize.fHeight)) {
1834370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return false;
1844370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        }
1854370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
1864370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
1874370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    switch (canvas->getClipType()) {
1884370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkCanvas::kRect_ClipType :
1894370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            {
1904370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                SkIRect bounds;
1914370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                canvas->getClipDeviceBounds(&bounds);
1924370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                if (bounds.fLeft > 0 || bounds.fTop > 0 ||
1934370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                    bounds.fRight < canvasSize.fWidth ||
1944370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                    bounds.fBottom < canvasSize.fHeight)
1954370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                    return false;
1964370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            }
1974370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            break;
1984370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkCanvas::kComplex_ClipType :
1994370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            return false; // conservative
2004370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        case SkCanvas::kEmpty_ClipType:
2014370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        default:
2024370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com            break;
2034370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    };
2044370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
2054370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return true;
2064370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2074370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
208c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgint SkDeferredCanvas::save(SaveFlags flags) {
2095e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->save(flags);
210a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::save(flags);
2114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
2134370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comint SkDeferredCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
214c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                SaveFlags flags) {
2155e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->saveLayer(bounds, paint, flags);
216a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    int count = this->INHERITED::save(flags);
217a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    this->clipRectBounds(bounds, flags, NULL);
218a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return count;
2194370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
221c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::restore() {
2225e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->restore();
223a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    this->INHERITED::restore();
2244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2254370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
226c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::isDrawingToLayer() const {
2275e5a095a94281167056da707b03930f135748d71junov@chromium.org    return drawingCanvas()->isDrawingToLayer();
2284370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2294370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
230c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::translate(SkScalar dx, SkScalar dy) {
2315e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->translate(dx, dy);
232a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::translate(dx, dy);
2334370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2344370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
235c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::scale(SkScalar sx, SkScalar sy) {
2365e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->scale(sx, sy);
237a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::scale(sx, sy);
2384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2394370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
240c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::rotate(SkScalar degrees) {
2415e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->rotate(degrees);
242a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::rotate(degrees);
2434370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2444370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
245c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::skew(SkScalar sx, SkScalar sy) {
2465e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->skew(sx, sy);
247a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::skew(sx, sy);
2484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
250c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgbool SkDeferredCanvas::concat(const SkMatrix& matrix) {
2515e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->concat(matrix);
252a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::concat(matrix);
2534370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2544370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
255c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::setMatrix(const SkMatrix& matrix) {
2565e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->setMatrix(matrix);
257a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    this->INHERITED::setMatrix(matrix);
2584370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
2604370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::clipRect(const SkRect& rect,
2614370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                SkRegion::Op op,
262c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                bool doAntiAlias) {
2635e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->clipRect(rect, op, doAntiAlias);
264a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::clipRect(rect, op, doAntiAlias);
2654370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2664370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
2674370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::clipPath(const SkPath& path,
2684370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                SkRegion::Op op,
269c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                bool doAntiAlias) {
2705e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->clipPath(path, op, doAntiAlias);
271a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::clipPath(path, op, doAntiAlias);
2724370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
2744370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::clipRegion(const SkRegion& deviceRgn,
275c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                  SkRegion::Op op) {
2765e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->clipRegion(deviceRgn, op);
277a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return this->INHERITED::clipRegion(deviceRgn, op);
2784370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2794370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
280c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::clear(SkColor color) {
2814370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // purge pending commands
2824370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (fDeferredDrawing) {
2838f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        getDeferredDevice()->contentsCleared();
2844370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
2854370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
2865e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->clear(color);
2874370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2884370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
289c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::drawPaint(const SkPaint& paint) {
290c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    if (fDeferredDrawing && isFullFrame(NULL, &paint) &&
291c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org        isPaintOpaque(&paint)) {
2928f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        getDeferredDevice()->contentsCleared();
2934370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
2944370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
2955e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawPaint(paint);
2964370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
2974370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
2984370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawPoints(PointMode mode, size_t count,
299c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                  const SkPoint pts[], const SkPaint& paint) {
3005e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawPoints(mode, count, pts, paint);
3014370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3024370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
303c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
304c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    if (fDeferredDrawing && isFullFrame(&rect, &paint) &&
305c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org        isPaintOpaque(&paint)) {
3068f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        getDeferredDevice()->contentsCleared();
3074370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
3084370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3095e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawRect(rect, paint);
3104370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
312c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
3135e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawPath(path, paint);
3144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3154370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3164370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
317c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                  SkScalar top, const SkPaint* paint) {
3188f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org    SkRect bitmapRect = SkRect::MakeXYWH(left, top,
3198f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
3204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (fDeferredDrawing &&
3214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        isFullFrame(&bitmapRect, paint) &&
32287f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org        isPaintOpaque(paint, &bitmap)) {
3238f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        getDeferredDevice()->contentsCleared();
3244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
3254370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3265e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawBitmap(bitmap, left, top, paint);
3274370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushIfNeeded(bitmap);
3284370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3294370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3304370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawBitmapRect(const SkBitmap& bitmap,
3314370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                      const SkIRect* src,
332c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                      const SkRect& dst,
333c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                      const SkPaint* paint) {
3344370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (fDeferredDrawing &&
3354370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        isFullFrame(&dst, paint) &&
33687f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org        isPaintOpaque(paint, &bitmap)) {
3378f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        getDeferredDevice()->contentsCleared();
3384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
3394370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3405e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawBitmapRect(bitmap, src,
3414370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    dst, paint);
3424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushIfNeeded(bitmap);
3434370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3444370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3454370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3464370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
3474370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                        const SkMatrix& m,
348c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                        const SkPaint* paint) {
3494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
3504370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // covers canvas entirely and transformed bitmap covers canvas entirely
3515e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawBitmapMatrix(bitmap, m, paint);
3524370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushIfNeeded(bitmap);
3534370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3544370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3554370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap,
3564370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                      const SkIRect& center, const SkRect& dst,
357c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                      const SkPaint* paint) {
3584370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
3594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // covers canvas entirely and dst covers canvas entirely
3605e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawBitmapNine(bitmap, center,
3614370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    dst, paint);
3624370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushIfNeeded(bitmap);
3634370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3644370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3654370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
366c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                  const SkPaint* paint) {
3678f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org    SkRect bitmapRect = SkRect::MakeXYWH(
3688f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(left),
3698f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(top),
3708f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(bitmap.width()),
3718f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        SkIntToScalar(bitmap.height()));
3724370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (fDeferredDrawing &&
3734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        isFullFrame(&bitmapRect, paint) &&
37487f982c80833eeebf541becec8e27b96c8c889f7junov@chromium.org        isPaintOpaque(paint, &bitmap)) {
3758f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        getDeferredDevice()->contentsCleared();
3764370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
3774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3785e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawSprite(bitmap, left, top,
3794370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                paint);
3804370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushIfNeeded(bitmap);
3814370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3824370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3834370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawText(const void* text, size_t byteLength,
384c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                SkScalar x, SkScalar y, const SkPaint& paint) {
3855e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawText(text, byteLength, x, y, paint);
3864370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3874370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3884370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawPosText(const void* text, size_t byteLength,
389c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                   const SkPoint pos[], const SkPaint& paint) {
3905e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawPosText(text, byteLength, pos, paint);
3914370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3924370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3934370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawPosTextH(const void* text, size_t byteLength,
3944370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const SkScalar xpos[], SkScalar constY,
395c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                    const SkPaint& paint) {
3965e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint);
3974370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
3984370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
3994370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength,
4004370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                      const SkPath& path,
4014370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                      const SkMatrix* matrix,
402c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                      const SkPaint& paint) {
4035e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawTextOnPath(text, byteLength,
4044370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    path, matrix,
4054370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    paint);
4064370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4074370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
408c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::drawPicture(SkPicture& picture) {
4095e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawPicture(picture);
4104370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
4124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount,
4134370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const SkPoint vertices[],
4144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const SkPoint texs[],
4154370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const SkColor colors[], SkXfermode* xmode,
4164370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                    const uint16_t indices[], int indexCount,
417c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                                    const SkPaint& paint) {
4185e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->drawVertices(vmode, vertexCount,
4194370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                  vertices, texs,
4204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                  colors, xmode,
4214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                  indices, indexCount,
4224370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                  paint);
4234370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
425c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) {
4265e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->setBounder(bounder);
427a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return INHERITED::setBounder(bounder);
4284370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4294370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
430c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
4315e5a095a94281167056da707b03930f135748d71junov@chromium.org    drawingCanvas()->setDrawFilter(filter);
432c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    return INHERITED::setDrawFilter(filter);
4334370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4344370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
4354370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkDeferredCanvas::canvasForDrawIter() {
4365e5a095a94281167056da707b03930f135748d71junov@chromium.org    return drawingCanvas();
4374370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
4394370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com// SkDeferredCanvas::DeferredDevice
4404370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com//------------------------------------
4414370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
4424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkDeferredCanvas::DeferredDevice::DeferredDevice(
4434370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkDevice* immediateDevice, DeviceContext* deviceContext) :
4444370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkDevice(SkBitmap::kNo_Config, immediateDevice->width(),
4454370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com             immediateDevice->height(), immediateDevice->isOpaque())
446c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    , fFreshFrame(true) {
447c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org
4484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    fDeviceContext = deviceContext;
4494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkSafeRef(fDeviceContext);
4504370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    fImmediateDevice = immediateDevice; // ref counted via fImmediateCanvas
4514370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    fImmediateCanvas = SkNEW_ARGS(SkCanvas, (fImmediateDevice));
4524370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    fRecordingCanvas = fPicture.beginRecording(fImmediateDevice->width(),
453a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        fImmediateDevice->height(), 0);
4544370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4554370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
456c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkDeferredCanvas::DeferredDevice::~DeferredDevice() {
4574370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkSafeUnref(fImmediateCanvas);
4584370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkSafeUnref(fDeviceContext);
4594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4604370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
4614370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::DeferredDevice::setDeviceContext(
462c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    DeviceContext* deviceContext) {
4634370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkRefCnt_SafeAssign(fDeviceContext, deviceContext);
4644370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
4654370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
466c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::DeferredDevice::contentsCleared() {
4678f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org    if (!fRecordingCanvas->isDrawingToLayer()) {
4688f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        fFreshFrame = true;
4694370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
4708f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        // TODO: find a way to transfer the state stack and layers
4718f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        // to the new recording canvas.  For now, purging only works
4728f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        // with an empty stack.
4738f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        if (fRecordingCanvas->getSaveCount() == 0) {
4744370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
4758f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            // Save state that is trashed by the purge
4768f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            SkDrawFilter* drawFilter = fRecordingCanvas->getDrawFilter();
4778f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            SkSafeRef(drawFilter); // So that it survives the purge
4788f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            SkMatrix matrix = fRecordingCanvas->getTotalMatrix();
4798f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            SkRegion clipRegion = fRecordingCanvas->getTotalClip();
4804370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
4818f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            // beginRecording creates a new recording canvas and discards the
4828f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            // old one, hence purging deferred draw ops.
4838f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            fRecordingCanvas = fPicture.beginRecording(
4848f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org                fImmediateDevice->width(),
485a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org                fImmediateDevice->height(), 0);
4868f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org
4878f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            // Restore pre-purge state
4888f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            if (!clipRegion.isEmpty()) {
489c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                fRecordingCanvas->clipRegion(clipRegion,
490c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org                    SkRegion::kReplace_Op);
4918f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            }
4928f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            if (!matrix.isIdentity()) {
4938f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org                fRecordingCanvas->setMatrix(matrix);
4948f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            }
4958f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            if (drawFilter) {
4968f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org                fRecordingCanvas->setDrawFilter(drawFilter)->unref();
4978f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org            }
4988f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        }
4994370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
5004370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5014370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
5028f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.orgbool SkDeferredCanvas::DeferredDevice::isFreshFrame() {
5038f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org    bool ret = fFreshFrame;
5048f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org    fFreshFrame = false;
5058f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org    return ret;
5068f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org}
5078f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org
508c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::DeferredDevice::flushPending() {
5094370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (fDeviceContext) {
5104370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        fDeviceContext->prepareForDraw();
5114370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
5124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    fPicture.draw(fImmediateCanvas);
5134370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    fRecordingCanvas = fPicture.beginRecording(fImmediateDevice->width(),
514a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        fImmediateDevice->height(), 0);
5154370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5164370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
517c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::DeferredDevice::flush() {
5184370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushPending();
519bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    fImmediateCanvas->flush();
5204370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
522c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgvoid SkDeferredCanvas::DeferredDevice::flushIfNeeded(const SkBitmap& bitmap) {
5234370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (bitmap.isImmutable()) {
5244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        return; // safe to deffer without registering a dependency
5254370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
5264370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
5274370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // For now, drawing a writable bitmap triggers a flush
5284370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // TODO: implement read-only semantics and auto buffer duplication on write
5294370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // in SkBitmap/SkPixelRef, which will make deferral possible in this case.
5304370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushPending();
5314370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5324370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
533c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orguint32_t SkDeferredCanvas::DeferredDevice::getDeviceCapabilities() {
5344370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return fImmediateDevice->getDeviceCapabilities();
5354370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5364370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
537c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgint SkDeferredCanvas::DeferredDevice::width() const {
5384370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return fImmediateDevice->width();
5394370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5404370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
541c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgint SkDeferredCanvas::DeferredDevice::height() const {
5424370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return fImmediateDevice->height();
5434370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5444370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
545c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgSkGpuRenderTarget* SkDeferredCanvas::DeferredDevice::accessRenderTarget() {
5464370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushPending();
5474370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return fImmediateDevice->accessRenderTarget();
5484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
5504370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comvoid SkDeferredCanvas::DeferredDevice::writePixels(const SkBitmap& bitmap,
551c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    int x, int y, SkCanvas::Config8888 config8888) {
552c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org
5534370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() &&
5544370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        (y + bitmap.height()) >= height()) {
5558f9ecbd3466d4330886b4c23b06e75b468c795adjunov@chromium.org        contentsCleared();
5564370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
5574370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
5584370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
5594370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        SkCanvas::kNative_Premul_Config8888 != config8888 &&
5604370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        kPMColorAlias != config8888) {
5614370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        //Special case config: no deferral
5624370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        flushPending();
5634370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        fImmediateDevice->writePixels(bitmap, x, y, config8888);
5644370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    }
5654370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
5664370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkPaint paint;
5674370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
5684370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    fRecordingCanvas->drawSprite(bitmap, x, y, &paint);
5694370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushIfNeeded(bitmap);
5704370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5714370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
572c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.orgconst SkBitmap& SkDeferredCanvas::DeferredDevice::onAccessBitmap(SkBitmap*) {
5734370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushPending();
5741f9767c03bad1ef85e5388d84e23e4b5dff4bc1ajunov@chromium.org    return fImmediateDevice->accessBitmap(false);
5754370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5764370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
5774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkDevice* SkDeferredCanvas::DeferredDevice::onCreateCompatibleDevice(
578c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    SkBitmap::Config config, int width, int height, bool isOpaque,
579c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    Usage usage) {
580c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org
5814370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // Save layer usage not supported, and not required by SkDeferredCanvas.
5824370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    SkASSERT(usage != kSaveLayer_Usage);
5834370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    // Create a compatible non-deferred device.
584c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    SkDevice* compatibleDevice =
585c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org        fImmediateDevice->createCompatibleDevice(config, width, height,
586c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org            isOpaque);
5874370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return SkNEW_ARGS(DeferredDevice, (compatibleDevice, fDeviceContext));
5884370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
5894370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
5904370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.combool SkDeferredCanvas::DeferredDevice::onReadPixels(
591c16ca92fd1ca609eb2902d14727bec78848ba767junov@chromium.org    const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
5924370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    flushPending();
5934370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap),
5944370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com                                                   x, y, config8888);
5954370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
596