14f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
24f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/*
34f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * Copyright 2011 Google Inc.
44f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger *
54f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
64f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * found in the LICENSE file.
74f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */
84f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
94f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkDeferredCanvas.h"
104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkPaint.h"
124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkShader.h"
134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkColorFilter.h"
144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkDrawFilter.h"
154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergernamespace {
174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool isPaintOpaque(const SkPaint* paint,
194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                   const SkBitmap* bmpReplacesShader = NULL) {
204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // TODO: SkXfermode should have a virtual isOpaque method, which would
214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // make it possible to test modes that do not have a Coeff representation.
224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (!paint) {
244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        return bmpReplacesShader ? bmpReplacesShader->isOpaque() : true;
254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkXfermode::Coeff srcCoeff, dstCoeff;
284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (SkXfermode::AsCoeff(paint->getXfermode(), &srcCoeff, &dstCoeff)){
294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        switch (dstCoeff) {
304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkXfermode::kZero_Coeff:
314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return true;
324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkXfermode::kISA_Coeff:
334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (paint->getAlpha() != 255) {
344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (bmpReplacesShader) {
374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                if (!bmpReplacesShader->isOpaque()) {
384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    break;
394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                }
404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            } else if (paint->getShader() && !paint->getShader()->isOpaque()) {
414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (paint->getColorFilter() &&
444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                ((paint->getColorFilter()->getFlags() &
454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return true;
494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkXfermode::kSA_Coeff:
504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (paint->getAlpha() != 0) {
514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (paint->getColorFilter() &&
544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                ((paint->getColorFilter()->getFlags() &
554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return true;
594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkXfermode::kSC_Coeff:
604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (paint->getColor() != 0) { // all components must be 0
614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (bmpReplacesShader || paint->getShader()) {
644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (paint->getColorFilter() && (
674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                (paint->getColorFilter()->getFlags() &
684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return true;
724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        default:
734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return false;
774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} // unnamed namespace
804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
814f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDeferredCanvas::SkDeferredCanvas() {
824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    init();
834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
854f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDeferredCanvas::SkDeferredCanvas(SkDevice* device) {
864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    init();
874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    setDevice(device);
884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
904f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDeferredCanvas::SkDeferredCanvas(SkDevice* device,
914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                   DeviceContext* deviceContext) {
924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    init();
934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    setDevice(device);
944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    setDeviceContext(deviceContext);
954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::init() {
984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fDeferredDrawing = true; // On by default
994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::validate() const {
1024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkASSERT(getDevice());
1034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1054f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkCanvas* SkDeferredCanvas::drawingCanvas() const {
1064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    validate();
1074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return fDeferredDrawing ? getDeferredDevice()->recordingCanvas() :
1084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        getDeferredDevice()->immediateCanvas();
1094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::flushIfNeeded(const SkBitmap& bitmap) {
1124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    validate();
1134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fDeferredDrawing) {
1144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        getDeferredDevice()->flushIfNeeded(bitmap);
1154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
1164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1184f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDeferredCanvas::DeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
1194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return static_cast<SkDeferredCanvas::DeferredDevice*>(getDevice());
1204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::setDeferredDrawing(bool val) {
1234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    validate(); // Must set device before calling this method
1244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkASSERT(drawingCanvas()->getSaveCount() == 1);
1254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (val != fDeferredDrawing) {
1264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (fDeferredDrawing) {
1274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // Going live.
1284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            getDeferredDevice()->flushPending();
1294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
1304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        fDeferredDrawing = val;
1314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
1324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1344f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDeferredCanvas::~SkDeferredCanvas() {
1354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1374f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDevice* SkDeferredCanvas::setDevice(SkDevice* device) {
1384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    INHERITED::setDevice(SkNEW_ARGS(DeferredDevice, (device)))->unref();
1394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return device;
1404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1424f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDeferredCanvas::DeviceContext* SkDeferredCanvas::setDeviceContext(
1434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    DeviceContext* deviceContext) {
1444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    DeferredDevice* deferredDevice = getDeferredDevice();
1464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkASSERT(deferredDevice);
1474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (deferredDevice) {
1484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        deferredDevice->setDeviceContext(deviceContext);
1494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
1504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return deviceContext;
1514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
1524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::isFullFrame(const SkRect* rect,
1544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                   const SkPaint* paint) const {
1554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkCanvas* canvas = drawingCanvas();
1564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkISize canvasSize = getDeviceSize();
1574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (rect) {
1584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (!canvas->getTotalMatrix().rectStaysRect()) {
1594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return false; // conservative
1604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
1614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkRect transformedRect;
1634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        canvas->getTotalMatrix().mapRect(&transformedRect, *rect);
1644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (paint) {
1664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkPaint::Style paintStyle = paint->getStyle();
1674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (!(paintStyle == SkPaint::kFill_Style ||
1684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                paintStyle == SkPaint::kStrokeAndFill_Style)) {
1694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                return false;
1704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
1714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (paint->getMaskFilter() || paint->getLooper()
1724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                || paint->getPathEffect() || paint->getImageFilter()) {
1734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                return false; // conservative
1744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
1754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
1764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // The following test holds with AA enabled, and is conservative
1784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // by a 0.5 pixel margin with AA disabled
1794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (transformedRect.fLeft > SkIntToScalar(0) ||
1804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            transformedRect.fTop > SkIntToScalar(0) ||
1814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            transformedRect.fRight < SkIntToScalar(canvasSize.fWidth) ||
1824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            transformedRect.fBottom < SkIntToScalar(canvasSize.fHeight)) {
1834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return false;
1844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
1854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
1864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    switch (canvas->getClipType()) {
1884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkCanvas::kRect_ClipType :
1894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            {
1904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                SkIRect bounds;
1914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                canvas->getClipDeviceBounds(&bounds);
1924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                if (bounds.fLeft > 0 || bounds.fTop > 0 ||
1934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    bounds.fRight < canvasSize.fWidth ||
1944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    bounds.fBottom < canvasSize.fHeight)
1954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    return false;
1964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
1974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
1984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkCanvas::kComplex_ClipType :
1994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return false; // conservative
2004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkCanvas::kEmpty_ClipType:
2014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        default:
2024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
2034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    };
2044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return true;
2064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerint SkDeferredCanvas::save(SaveFlags flags) {
2094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->save(flags);
2104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::save(flags);
2114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerint SkDeferredCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
2144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                SaveFlags flags) {
2154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->saveLayer(bounds, paint, flags);
2164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int count = this->INHERITED::save(flags);
2174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    this->clipRectBounds(bounds, flags, NULL);
2184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return count;
2194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::restore() {
2224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->restore();
2234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    this->INHERITED::restore();
2244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::isDrawingToLayer() const {
2274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return drawingCanvas()->isDrawingToLayer();
2284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::translate(SkScalar dx, SkScalar dy) {
2314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->translate(dx, dy);
2324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::translate(dx, dy);
2334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::scale(SkScalar sx, SkScalar sy) {
2364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->scale(sx, sy);
2374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::scale(sx, sy);
2384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::rotate(SkScalar degrees) {
2414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->rotate(degrees);
2424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::rotate(degrees);
2434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::skew(SkScalar sx, SkScalar sy) {
2464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->skew(sx, sy);
2474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::skew(sx, sy);
2484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::concat(const SkMatrix& matrix) {
2514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->concat(matrix);
2524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::concat(matrix);
2534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::setMatrix(const SkMatrix& matrix) {
2564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->setMatrix(matrix);
2574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    this->INHERITED::setMatrix(matrix);
2584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::clipRect(const SkRect& rect,
2614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                SkRegion::Op op,
2624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                bool doAntiAlias) {
2634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->clipRect(rect, op, doAntiAlias);
2644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::clipRect(rect, op, doAntiAlias);
2654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::clipPath(const SkPath& path,
2684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                SkRegion::Op op,
2694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                bool doAntiAlias) {
2704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->clipPath(path, op, doAntiAlias);
2714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::clipPath(path, op, doAntiAlias);
2724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::clipRegion(const SkRegion& deviceRgn,
2754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  SkRegion::Op op) {
2764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->clipRegion(deviceRgn, op);
2774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return this->INHERITED::clipRegion(deviceRgn, op);
2784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::clear(SkColor color) {
2814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // purge pending commands
2824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fDeferredDrawing) {
2834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        getDeferredDevice()->contentsCleared();
2844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
2854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->clear(color);
2874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawPaint(const SkPaint& paint) {
2904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fDeferredDrawing && isFullFrame(NULL, &paint) &&
2914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        isPaintOpaque(&paint)) {
2924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        getDeferredDevice()->contentsCleared();
2934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
2944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawPaint(paint);
2964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
2974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawPoints(PointMode mode, size_t count,
2994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  const SkPoint pts[], const SkPaint& paint) {
3004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawPoints(mode, count, pts, paint);
3014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
3044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fDeferredDrawing && isFullFrame(&rect, &paint) &&
3054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        isPaintOpaque(&paint)) {
3064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        getDeferredDevice()->contentsCleared();
3074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
3084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawRect(rect, paint);
3104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
3134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawPath(path, paint);
3144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
3174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  SkScalar top, const SkPaint* paint) {
3184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkRect bitmapRect = SkRect::MakeXYWH(left, top,
3194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
3204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fDeferredDrawing &&
3214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        isFullFrame(&bitmapRect, paint) &&
3224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        isPaintOpaque(paint, &bitmap)) {
3234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        getDeferredDevice()->contentsCleared();
3244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
3254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawBitmap(bitmap, left, top, paint);
3274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushIfNeeded(bitmap);
3284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawBitmapRect(const SkBitmap& bitmap,
3314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      const SkIRect* src,
3324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      const SkRect& dst,
3334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      const SkPaint* paint) {
3344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fDeferredDrawing &&
3354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        isFullFrame(&dst, paint) &&
3364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        isPaintOpaque(paint, &bitmap)) {
3374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        getDeferredDevice()->contentsCleared();
3384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
3394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawBitmapRect(bitmap, src,
3414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    dst, paint);
3424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushIfNeeded(bitmap);
3434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
3474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        const SkMatrix& m,
3484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                        const SkPaint* paint) {
3494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
3504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // covers canvas entirely and transformed bitmap covers canvas entirely
3514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawBitmapMatrix(bitmap, m, paint);
3524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushIfNeeded(bitmap);
3534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap,
3564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      const SkIRect& center, const SkRect& dst,
3574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      const SkPaint* paint) {
3584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
3594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // covers canvas entirely and dst covers canvas entirely
3604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawBitmapNine(bitmap, center,
3614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    dst, paint);
3624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushIfNeeded(bitmap);
3634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
3664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  const SkPaint* paint) {
3674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkRect bitmapRect = SkRect::MakeXYWH(
3684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkIntToScalar(left),
3694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkIntToScalar(top),
3704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkIntToScalar(bitmap.width()),
3714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkIntToScalar(bitmap.height()));
3724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fDeferredDrawing &&
3734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        isFullFrame(&bitmapRect, paint) &&
3744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        isPaintOpaque(paint, &bitmap)) {
3754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        getDeferredDevice()->contentsCleared();
3764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
3774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawSprite(bitmap, left, top,
3794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                paint);
3804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushIfNeeded(bitmap);
3814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawText(const void* text, size_t byteLength,
3844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                SkScalar x, SkScalar y, const SkPaint& paint) {
3854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawText(text, byteLength, x, y, paint);
3864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawPosText(const void* text, size_t byteLength,
3894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                   const SkPoint pos[], const SkPaint& paint) {
3904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawPosText(text, byteLength, pos, paint);
3914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawPosTextH(const void* text, size_t byteLength,
3944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    const SkScalar xpos[], SkScalar constY,
3954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    const SkPaint& paint) {
3964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint);
3974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
3984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
3994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength,
4004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      const SkPath& path,
4014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      const SkMatrix* matrix,
4024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                      const SkPaint& paint) {
4034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawTextOnPath(text, byteLength,
4044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    path, matrix,
4054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    paint);
4064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawPicture(SkPicture& picture) {
4094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawPicture(picture);
4104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount,
4134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    const SkPoint vertices[],
4144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    const SkPoint texs[],
4154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    const SkColor colors[], SkXfermode* xmode,
4164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    const uint16_t indices[], int indexCount,
4174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    const SkPaint& paint) {
4184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->drawVertices(vmode, vertexCount,
4194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  vertices, texs,
4204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  colors, xmode,
4214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  indices, indexCount,
4224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                  paint);
4234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4254f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) {
4264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->setBounder(bounder);
4274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return INHERITED::setBounder(bounder);
4284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4304f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
4314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    drawingCanvas()->setDrawFilter(filter);
4324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return INHERITED::setDrawFilter(filter);
4334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4354f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkCanvas* SkDeferredCanvas::canvasForDrawIter() {
4364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return drawingCanvas();
4374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger// SkDeferredCanvas::DeferredDevice
4404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger//------------------------------------
4414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4424f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDeferredCanvas::DeferredDevice::DeferredDevice(
4434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDevice* immediateDevice, DeviceContext* deviceContext) :
4444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDevice(SkBitmap::kNo_Config, immediateDevice->width(),
4454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger             immediateDevice->height(), immediateDevice->isOpaque())
4464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    , fFreshFrame(true) {
4474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fDeviceContext = deviceContext;
4494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkSafeRef(fDeviceContext);
4504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fImmediateDevice = immediateDevice; // ref counted via fImmediateCanvas
4514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fImmediateCanvas = SkNEW_ARGS(SkCanvas, (fImmediateDevice));
4524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fRecordingCanvas = fPicture.beginRecording(fImmediateDevice->width(),
4534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        fImmediateDevice->height(), 0);
4544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4564f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDeferredCanvas::DeferredDevice::~DeferredDevice() {
4574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkSafeUnref(fImmediateCanvas);
4584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkSafeUnref(fDeviceContext);
4594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::DeferredDevice::setDeviceContext(
4624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    DeviceContext* deviceContext) {
4634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkRefCnt_SafeAssign(fDeviceContext, deviceContext);
4644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
4654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::DeferredDevice::contentsCleared() {
4674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (!fRecordingCanvas->isDrawingToLayer()) {
4684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        fFreshFrame = true;
4694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // TODO: find a way to transfer the state stack and layers
4714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // to the new recording canvas.  For now, purging only works
4724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // with an empty stack.
4734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (fRecordingCanvas->getSaveCount() == 0) {
4744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // Save state that is trashed by the purge
4764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkDrawFilter* drawFilter = fRecordingCanvas->getDrawFilter();
4774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkSafeRef(drawFilter); // So that it survives the purge
4784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkMatrix matrix = fRecordingCanvas->getTotalMatrix();
4794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkRegion clipRegion = fRecordingCanvas->getTotalClip();
4804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // beginRecording creates a new recording canvas and discards the
4824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // old one, hence purging deferred draw ops.
4834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            fRecordingCanvas = fPicture.beginRecording(
4844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fImmediateDevice->width(),
4854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fImmediateDevice->height(), 0);
4864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
4874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // Restore pre-purge state
4884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (!clipRegion.isEmpty()) {
4894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fRecordingCanvas->clipRegion(clipRegion,
4904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    SkRegion::kReplace_Op);
4914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
4924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (!matrix.isIdentity()) {
4934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fRecordingCanvas->setMatrix(matrix);
4944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
4954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (drawFilter) {
4964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fRecordingCanvas->setDrawFilter(drawFilter)->unref();
4974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
4984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
4994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::DeferredDevice::isFreshFrame() {
5034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool ret = fFreshFrame;
5044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fFreshFrame = false;
5054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return ret;
5064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::DeferredDevice::flushPending() {
5094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (fDeviceContext) {
5104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        fDeviceContext->prepareForDraw();
5114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fPicture.draw(fImmediateCanvas);
5134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fRecordingCanvas = fPicture.beginRecording(fImmediateDevice->width(),
5144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        fImmediateDevice->height(), 0);
5154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::DeferredDevice::flush() {
5184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushPending();
5194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fImmediateCanvas->flush();
5204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::DeferredDevice::flushIfNeeded(const SkBitmap& bitmap) {
5234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (bitmap.isImmutable()) {
5244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        return; // safe to deffer without registering a dependency
5254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // For now, drawing a writable bitmap triggers a flush
5284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // TODO: implement read-only semantics and auto buffer duplication on write
5294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // in SkBitmap/SkPixelRef, which will make deferral possible in this case.
5304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushPending();
5314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergeruint32_t SkDeferredCanvas::DeferredDevice::getDeviceCapabilities() {
5344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return fImmediateDevice->getDeviceCapabilities();
5354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerint SkDeferredCanvas::DeferredDevice::width() const {
5384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return fImmediateDevice->width();
5394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerint SkDeferredCanvas::DeferredDevice::height() const {
5424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return fImmediateDevice->height();
5434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5454f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkGpuRenderTarget* SkDeferredCanvas::DeferredDevice::accessRenderTarget() {
5464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushPending();
5474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return fImmediateDevice->accessRenderTarget();
5484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkDeferredCanvas::DeferredDevice::writePixels(const SkBitmap& bitmap,
5514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int x, int y, SkCanvas::Config8888 config8888) {
5524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() &&
5544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        (y + bitmap.height()) >= height()) {
5554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        contentsCleared();
5564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
5594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkCanvas::kNative_Premul_Config8888 != config8888 &&
5604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        kPMColorAlias != config8888) {
5614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        //Special case config: no deferral
5624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        flushPending();
5634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        fImmediateDevice->writePixels(bitmap, x, y, config8888);
5644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkPaint paint;
5674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
5684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fRecordingCanvas->drawSprite(bitmap, x, y, &paint);
5694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushIfNeeded(bitmap);
5704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerconst SkBitmap& SkDeferredCanvas::DeferredDevice::onAccessBitmap(SkBitmap*) {
5734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushPending();
5744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return fImmediateDevice->accessBitmap(false);
5754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5774f1dae40e24d57d647db01443b8bf2410514b8b5Derek SollenbergerSkDevice* SkDeferredCanvas::DeferredDevice::onCreateCompatibleDevice(
5784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkBitmap::Config config, int width, int height, bool isOpaque,
5794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    Usage usage) {
5804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // Save layer usage not supported, and not required by SkDeferredCanvas.
5824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkASSERT(usage != kSaveLayer_Usage);
5834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // Create a compatible non-deferred device.
5844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDevice* compatibleDevice =
5854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        fImmediateDevice->createCompatibleDevice(config, width, height,
5864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            isOpaque);
5874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return SkNEW_ARGS(DeferredDevice, (compatibleDevice, fDeviceContext));
5884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkDeferredCanvas::DeferredDevice::onReadPixels(
5914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
5924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    flushPending();
5934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap),
5944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                                   x, y, config8888);
5954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
596