SkCanvas.cpp revision f0090cb80ab10a49e511aa5450ae38917fa058d9
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
96a070dc06af4e9f305f9d08a69e34d18ade473cbreed#include "SkCanvasDrawable.h"
10d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h"
129c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org#include "SkDeviceImageFilterProxy.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
16b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
1774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
1845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h"
19b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
210017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
224ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
267ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
2752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
28a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
298f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
33644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
34644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
35644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
36da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
37da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
3815e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
622c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
632c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
6497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() {
6597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
66c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
6797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
6897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
6997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
724a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
734a8126e7f81384526629b1e21bf89b632ea13cd9reed    const uint32_t propFlags = props.flags();
744a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
754a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kDither_Flag;
764a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
774a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
784a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kAntiAlias_Flag;
794a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
804a8126e7f81384526629b1e21bf89b632ea13cd9reed    return flags;
814a8126e7f81384526629b1e21bf89b632ea13cd9reed}
824a8126e7f81384526629b1e21bf89b632ea13cd9reed
834a8126e7f81384526629b1e21bf89b632ea13cd9reed///////////////////////////////////////////////////////////////////////////////
844a8126e7f81384526629b1e21bf89b632ea13cd9reed
851f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
941f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
95045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix*     fMatrix;
976f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
99d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas,
100d954498c01ccf0417feacf89e45d0c62a06a813breed             bool conservativeRasterClip)
101d954498c01ccf0417feacf89e45d0c62a06a813breed        : fNext(NULL)
102d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
103d954498c01ccf0417feacf89e45d0c62a06a813breed    {
104d954498c01ccf0417feacf89e45d0c62a06a813breed        if (NULL != device) {
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
10640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1084b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
11088edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
11349f085dddff10473b6ebf832a974288300224e60bsalomon        if (fDevice) {
11440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
11888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1194b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
121045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
1226f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
1236f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
1264b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
1354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
139045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
1424b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
144045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1474b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1483fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
1493fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
157f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
158f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1600e354aacd84d3bede3f97cbde35a54ba62a89533bsalomon@google.com    SkMatrix    fMatrixStorage;
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1726f09709519b79a1159f3826645f1c5fbc101ee11reed    SkRasterClip    fRasterClip;
173d954498c01ccf0417feacf89e45d0c62a06a813breed    SkMatrix        fMatrix;
1741f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
175d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
18288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    DeviceCM*   fTopLayer;
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
184d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
185d954498c01ccf0417feacf89e45d0c62a06a813breed        fMatrix.reset();
186d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter     = NULL;
187d954498c01ccf0417feacf89e45d0c62a06a813breed        fLayer      = NULL;
188d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer   = NULL;
189b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
190d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
191d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
192d954498c01ccf0417feacf89e45d0c62a06a813breed    }
193d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip) {
194d954498c01ccf0417feacf89e45d0c62a06a813breed        fMatrix = prev.fMatrix;
195d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
197d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
198b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
20382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2118a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
2124370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
2138a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com        fClipStack = &canvas->fClipStack;
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
2188a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
229f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
230f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
233045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
234045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBitmap = &fDevice->accessBitmap(true);
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
238f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
242199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2474b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2481f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
2496f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
2506f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
2546f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2684a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
26978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
27078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
2714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
2734a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
2744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
2758926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        fDoClearImageFilter = false;
2764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
2798926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
2808926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            tmp.setImageFilter(fOrigPaint.getImageFilter());
281e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
282e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                            true, SkCanvas::kFullLayer_SaveLayerStrategy);
2838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // we'll clear the imageFilter for the actual draws in next(), so
2848926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // it will only be applied during the restore().
2858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fDoClearImageFilter = true;
2868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
2878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
28879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
28979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
29079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
29179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
292129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
293129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
29479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = NULL;
295129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
296129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = !fFilter && !fDoClearImageFilter;
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
298b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
2994a8126e7f81384526629b1e21bf89b632ea13cd9reed        uint32_t oldFlags = paint.getFlags();
3004a8126e7f81384526629b1e21bf89b632ea13cd9reed        fNewPaintFlags = filter_paint_flags(props, oldFlags);
3014a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (fIsSimple && (fNewPaintFlags != oldFlags)) {
3024a8126e7f81384526629b1e21bf89b632ea13cd9reed            SkPaint* paint = fLazyPaint.set(fOrigPaint);
3034a8126e7f81384526629b1e21bf89b632ea13cd9reed            paint->setFlags(fNewPaintFlags);
3044a8126e7f81384526629b1e21bf89b632ea13cd9reed            fPaint = paint;
3054a8126e7f81384526629b1e21bf89b632ea13cd9reed            // if we're not simple, doNext() will take care of calling setFlags()
3064a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
30874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
3108926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (fDoClearImageFilter) {
3118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
3128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
31574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
3174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
3184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
3194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
32074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
321129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
322129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
323129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
324129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
325129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
326129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
327129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
328129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
329129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
330fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
33174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3332c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazyPaint;
3342c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
3352c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
3362c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
3372c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
3382c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
3394a8126e7f81384526629b1e21bf89b632ea13cd9reed    uint32_t        fNewPaintFlags;
3408926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    bool            fDoClearImageFilter;
3412c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
342129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
34379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
34479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
345129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
346129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
349129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
350632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
351129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
35279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
353632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
354129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkPaint* paint = fLazyPaint.set(fOrigPaint);
3554a8126e7f81384526629b1e21bf89b632ea13cd9reed    paint->setFlags(fNewPaintFlags);
3568926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
357129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fDoClearImageFilter) {
358129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
359129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
3608926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
36179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
362129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
363129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
364129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
365129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
366971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
367971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
368971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
369971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
37079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (NULL == fLooperContext) {
371129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
372632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
373632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
374129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
375129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
3768926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
377129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
37879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
3794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
3804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
3814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
382632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
383632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
3844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
3854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
3864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
3874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
3884e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
3894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3928926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
39397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
3944a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, true);              \
3958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
3968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
3978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
39878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
39997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
4004a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
4014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
4034b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
4044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
408d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
409d954498c01ccf0417feacf89e45d0c62a06a813breed    fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
410c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
411c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
4128f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
41345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
414f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
415b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount = 0;
416210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    fCullCount = 0;
41774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
420d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
422d954498c01ccf0417feacf89e45d0c62a06a813breed    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservativeRasterClip));
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
426f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
427f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
428b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        device->initForRootLayer(fProps.pixelGeometry());
4294a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (device->forceConservativeRasterClip()) {
4304a8126e7f81384526629b1e21bf89b632ea13cd9reed            fConservativeRasterClip = true;
4314a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
432f92c86642a1875da54d54b447f006cb9dfbbb35creed        device->onAttachToCanvas(this);
433f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
43478e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
435f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
436f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
439cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
440e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
4414a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
442e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
4438d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
444ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
445d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(NULL, kDefault_InitFlags);
4468d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
4478d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
448d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
449d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
450d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
451d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
452d954498c01ccf0417feacf89e45d0c62a06a813breed}
453d954498c01ccf0417feacf89e45d0c62a06a813breed
454d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
455d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
45678e276889795454891cbba48ab11927968114953reed    SkNoPixelsBitmapDevice(const SkIRect& bounds)
45778e276889795454891cbba48ab11927968114953reed        : INHERITED(make_nopixels(bounds.width(), bounds.height()))
45878e276889795454891cbba48ab11927968114953reed    {
45978e276889795454891cbba48ab11927968114953reed        this->setOrigin(bounds.x(), bounds.y());
46078e276889795454891cbba48ab11927968114953reed    }
461d954498c01ccf0417feacf89e45d0c62a06a813breed
462d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
463b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
464d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
465d954498c01ccf0417feacf89e45d0c62a06a813breed};
466d954498c01ccf0417feacf89e45d0c62a06a813breed
467e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.orgSkCanvas::SkCanvas(int width, int height)
468e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
4694a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
470e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
471e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
472b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
47378e276889795454891cbba48ab11927968114953reed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice,
47478e276889795454891cbba48ab11927968114953reed                          (SkIRect::MakeWH(width, height))), kDefault_InitFlags)->unref();
475d954498c01ccf0417feacf89e45d0c62a06a813breed}
476e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
47778e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
478d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
4794a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
480d954498c01ccf0417feacf89e45d0c62a06a813breed{
481d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
482b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
48378e276889795454891cbba48ab11927968114953reed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (bounds)), flags)->unref();
48427a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4864a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags)
48727a5e656c3d6ef22f9cb34de18e1b960da3aa241reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
4884a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfacePropsCopyOrDefault(props))
48927a5e656c3d6ef22f9cb34de18e1b960da3aa241reed{
49027a5e656c3d6ef22f9cb34de18e1b960da3aa241reed    inc_canvas();
491b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
492d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, flags);
493d954498c01ccf0417feacf89e45d0c62a06a813breed}
4946f09709519b79a1159f3826645f1c5fbc101ee11reed
495d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
496d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
4974a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
498d954498c01ccf0417feacf89e45d0c62a06a813breed{
499d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
500b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
501d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5044a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
5053716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
5064a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
5073716fd067a5621bb94a6cb08d72afec8bf3acedareed{
5083716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
509b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
5104a8126e7f81384526629b1e21bf89b632ea13cd9reed    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
5114a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
5124a8126e7f81384526629b1e21bf89b632ea13cd9reed}
51329c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
5144a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap)
5154a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
5164a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
5174a8126e7f81384526629b1e21bf89b632ea13cd9reed{
5184a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
519b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
5204a8126e7f81384526629b1e21bf89b632ea13cd9reed    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
5214a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
527b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    SkASSERT(0 == fSaveLayerCount);
5287c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
532b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
54674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
54774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
54874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
54974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
55074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
55174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
55274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
55374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
556bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
5571f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
558bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
559bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
560bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
561bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
562bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
5634ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
5644ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
5654ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
5664ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
5674ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
5684ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
5694ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
5704ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
5714ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
5724ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
5734ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
5741f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
575210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
576210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
577210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
5781f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
580c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5851f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
5860b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
5870b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
5880b53d59a24f667350b4282f88470713902409030reed@google.com    }
5899266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
5909266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
5919266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
592403f8d7a052269583175e945689824838e5e0ef4commit-bot@chromium.orgSkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
5944c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    SkDeque::F2BIter iter(fMCStack);
5954c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    MCRec*           rec = (MCRec*)iter.next();
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
5971f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*    rootDevice = rec->fLayer->fDevice;
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice == device) {
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return device;
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6024b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (device) {
60440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        device->onAttachToCanvas(this);
605b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        device->initForRootLayer(fProps.pixelGeometry());
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice) {
60840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        rootDevice->onDetachFromCanvas();
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rootDevice = device;
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
6154b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Now we update our initial region to have the bounds of the new device,
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and then intersect all of the clips in our stack with these bounds,
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to ensure that we can't draw outside of the device's bounds (and trash
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                     memory).
6204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this is only a partial-fix, since if the new device is larger than
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the previous one, we don't know how to "enlarge" the clips in our stack,
6234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        so drawing may be artificially restricted. Without keeping a history of
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reconstruct the correct clips, so this approximation will have to do.
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The caller really needs to restore() back to the base if they want to
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        accurately take advantage of the new device bounds.
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
63042aea289cbf801997b653a906a37a7f7e948b645reed@google.com    SkIRect bounds;
63142aea289cbf801997b653a906a37a7f7e948b645reed@google.com    if (device) {
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bounds.set(0, 0, device->width(), device->height());
63342aea289cbf801997b653a906a37a7f7e948b645reed@google.com    } else {
63442aea289cbf801997b653a906a37a7f7e948b645reed@google.com        bounds.setEmpty();
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
63642aea289cbf801997b653a906a37a7f7e948b645reed@google.com    // now jam our 1st clip to be bounds, and intersect the rest with that
6371f836ee096bb988adef4b9757b2629c7afeda36dreed    rec->fRasterClip.setRect(bounds);
63842aea289cbf801997b653a906a37a7f7e948b645reed@google.com    while ((rec = (MCRec*)iter.next()) != NULL) {
6391f836ee096bb988adef4b9757b2629c7afeda36dreed        (void)rec->fRasterClip.op(bounds, SkRegion::kIntersect_Op);
64042aea289cbf801997b653a906a37a7f7e948b645reed@google.com    }
64142aea289cbf801997b653a906a37a7f7e948b645reed@google.com
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return device;
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
645a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
646a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
647a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
648a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
649a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
650a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
651a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == bitmap->pixelRef()) {
652848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
653a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
654a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
655a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
656a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
657a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
658a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBitmap bm(*bitmap);
659a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bm.lockPixels();
660a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
661a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return true;
662a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
663a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
664a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
665a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->setPixelRef(NULL);
666a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
667a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
668a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
66951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
670c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
671a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
672a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
673a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
674a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
675ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
676ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
67774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
678848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
679a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
680a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
681a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
682a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
683a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
684daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
685c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
686a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
687a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
688c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
689a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) {
690a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    switch (origInfo.colorType()) {
691a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kUnknown_SkColorType:
692a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kIndex_8_SkColorType:
693a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
694a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        default:
695a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            break;
696a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
697a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == dstP || rowBytes < origInfo.minRowBytes()) {
698a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
699a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
700a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (0 == origInfo.width() || 0 == origInfo.height()) {
70151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        return false;
70251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
703a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
704a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
705a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
706a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
707a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
708a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
709a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
710a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
711a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!srcR.intersect(0, 0, size.width(), size.height())) {
712a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
713a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
714db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
715a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // the intersect may have shrunk info's logical size
716e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(srcR.width(), srcR.height());
717db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
718a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
719a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (x > 0) {
720a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        x = 0;
721a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
722a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (y > 0) {
723a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        y = 0;
724a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
725a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // here x,y are either 0 or negative
726a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
727db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
728a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
729a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
73051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
73151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7324cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
7334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
7344cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7354cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7364cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBitmap bm(bitmap);
7374cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    bm.lockPixels();
7384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bm.getPixels()) {
7394cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
7404cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7414cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
7424cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
7434cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7444cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
7454cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
7464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
7474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
7484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
7494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
7504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
7514cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
7524cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7534cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
7544cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7554cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7564cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7574cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
7584cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
7594cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
7604cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7614cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7624cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7634cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
7644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
7654cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7674cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7684cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
769e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
7704cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7714cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
7724cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
7734cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
7744cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7754cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
7764cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
7774cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7784cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
7794cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
7804cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7814af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
7824af35f348b2e2f6c428819118eb7a2f2fff53a74reed    this->predrawNotify();
7834af35f348b2e2f6c428819118eb7a2f2fff53a74reed
7844cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
7854ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
7864cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
78751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7884370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
7894370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
7904370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7914370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
7971f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
7994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
80146799cd9f0bded51a189d77731b25af159ab4609reed@google.com            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
803045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
80546799cd9f0bded51a189d77731b25af159ab4609reed@google.com                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
814f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
815f0090cb80ab10a49e511aa5450ae38917fa058d9reed    return fMCStack.count();
816f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
817f0090cb80ab10a49e511aa5450ae38917fa058d9reed
818f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
819f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
820f0090cb80ab10a49e511aa5450ae38917fa058d9reed    return this->internalSave();
821f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
822f0090cb80ab10a49e511aa5450ae38917fa058d9reed
823f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
824f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // check for underflow
825f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (fMCStack.count() > 1) {
826f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->willRestore();
827f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->internalRestore();
828f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->didRestore();
829f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
830f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
831f0090cb80ab10a49e511aa5450ae38917fa058d9reed
832f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
833f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
834f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
835f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
836f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
837f0090cb80ab10a49e511aa5450ae38917fa058d9reed
838f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
839f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
840f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
841f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
842f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
843f0090cb80ab10a49e511aa5450ae38917fa058d9reed
8445f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malitaint SkCanvas::internalSave() {
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int saveCount = this->getSaveCount(); // record this before the actual save
8464b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
848d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
8504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8515f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    fClipStack.save();
8525c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return saveCount;
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
857b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
859b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
860b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
861b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
864a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
865c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                               SkIRect* intersection, const SkImageFilter* imageFilter) {
866bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
867c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkRegion::Op op = SkRegion::kIntersect_Op;
868bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
869a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
870f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
871c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
872c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
8731f836ee096bb988adef4b9757b2629c7afeda36dreed        imageFilter->filterBounds(clipBounds, fMCRec->fMatrix, &clipBounds);
874c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        // Filters may grow the bounds beyond the device bounds.
875c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        op = SkRegion::kReplace_Op;
876c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
877bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
87849f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
8804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->getTotalMatrix().mapRect(&r, *bounds);
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
885bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
8861f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
887bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
888a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
89489f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
89589f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        fClipStack.clipDevRect(ir, op);
89689f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        // early exit if the clip is now empty
8971f836ee096bb988adef4b9757b2629c7afeda36dreed        if (!fMCRec->fRasterClip.op(ir, op)) {
89889f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org            return false;
89989f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        }
900a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
901a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
902a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
903a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
904a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
905a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
906a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
907a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
908d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
909d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
910d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
911d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
912d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
913a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
914a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org                        SaveFlags flags) {
915e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
916e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return this->internalSaveLayer(bounds, paint, flags, false, strategy);
9178926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
9188926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
919e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgint SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
920e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                bool justForImageFilter, SaveLayerStrategy strategy) {
921b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
9222a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    flags |= kClipToLayer_SaveFlag;
923b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
924b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
925a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
926a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
9275f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    int count = this->internalSave();
928a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
929a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
930a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
931a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
932c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return count;
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
936e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
937e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
938e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
939e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org        return count;
940e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
941e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
942b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    // Kill the imagefilter if our device doesn't allow it
943b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    SkLazyPaint lazyP;
944b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    if (paint && paint->getImageFilter()) {
945b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
9468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            if (justForImageFilter) {
9478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                // early exit if the layer was just for the imageFilter
9488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                return count;
9498926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
950b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            SkPaint* p = lazyP.set(*paint);
951b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            p->setImageFilter(NULL);
952b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            paint = p;
953b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
954b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
955b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com
95615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
95715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
95815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
960b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    SkBaseDevice* device = this->getTopDevice();
961b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    if (NULL == device) {
962b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
963b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        return count;
964b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
965b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
966b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    SkBaseDevice::Usage usage = SkBaseDevice::kSaveLayer_Usage;
96776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    if (paint && paint->getImageFilter()) {
968b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        usage = SkBaseDevice::kImageFilter_Usage;
96976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    }
970b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    device = device->onCreateCompatibleDevice(SkBaseDevice::CreateInfo(info, usage,
971b2db898573e3cdcc8234eebf51961bfc4977ebbcreed                                                                       fProps.pixelGeometry()));
972e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    if (NULL == device) {
973e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        SkDebugf("Unable to create device for layer.");
974e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        return count;
975e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
976e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
9776f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
978d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM* layer = SkNEW_ARGS(DeviceCM,
979d954498c01ccf0417feacf89e45d0c62a06a813breed                                 (device, ir.fLeft, ir.fTop, paint, this, fConservativeRasterClip));
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
986b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount += 1;
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
990d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
991d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
992d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
993d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1009c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10115f6102d07982043542343ff0a6c67b1319ac9fc7Florin Malita    fClipStack.restore();
10126c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
101388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
102749f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
10296f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
10308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
10318926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                     layer->fPaint);
10328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
10347c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
1035b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            SkASSERT(fSaveLayerCount > 0);
1036b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            fSaveLayerCount -= 1;
10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(layer);
103988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10427c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.combool SkCanvas::isDrawingToLayer() const {
1043b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    return fSaveLayerCount > 0;
10447c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com}
10457c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
10464a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
10474a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (NULL == props) {
10484a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
10494a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
10504a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
105176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
105276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
10534a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
105476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
10554a8126e7f81384526629b1e21bf89b632ea13cd9reed    return dev ? dev->newSurface(info, props) : NULL;
105676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
105776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1058c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1059c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1060c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1061c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1062c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1063900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1064c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1065c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1066c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1067c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1068c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return this->onPeekPixels(info, rowBytes);
1069c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1070c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1071c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1072c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1073c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return dev ? dev->peekPixels(info, rowBytes) : NULL;
1074c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1075c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
10766b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
10776b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
10786b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    if (pixels && origin) {
10796b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
10806b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
10816b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    return pixels;
10829c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
10839c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
10849c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comvoid* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
10859c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
10869c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessPixels(info, rowBytes) : NULL;
10879c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
10889c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1089c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1090c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1091c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1092c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1093848250415eddc54075f7eb8795e8db79e749c6abreed        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1094c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1095c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1096c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1097c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1098c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1099c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1100c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1101c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1102c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1103c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1104c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1105c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1106c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
110700f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1108c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1109c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1110c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1111c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1112c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1113c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1114210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.orgvoid SkCanvas::onPushCull(const SkRect& cullRect) {
1115210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    // do nothing. Subclasses may do something
1116210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org}
1117210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org
1118210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.orgvoid SkCanvas::onPopCull() {
1119210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    // do nothing. Subclasses may do something
1120210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org}
1121210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org
11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
1123520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef SK_DEBUG
1124520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org// Ensure that cull rects are monotonically nested in device space.
1125520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::validateCull(const SkIRect& devCull) {
1126520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (fCullStack.isEmpty()
1127520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        || devCull.isEmpty()
1128520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        || fCullStack.top().contains(devCull)) {
1129520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        return;
1130520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1131520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1132520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
1133520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
1134520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              fCullStack.top().x(), fCullStack.top().y(),
1135520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              fCullStack.top().right(), fCullStack.top().bottom()));
1136520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1137520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef ASSERT_NESTED_CULLING
1138520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkDEBUGFAIL("Invalid cull.");
1139520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1140520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1141520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1142520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1143520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::pushCull(const SkRect& cullRect) {
1144520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    ++fCullCount;
1145520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->onPushCull(cullRect);
1146520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1147520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef SK_DEBUG
1148520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    // Map the cull rect into device space.
1149520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkRect mappedCull;
1150520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->getTotalMatrix().mapRect(&mappedCull, cullRect);
1151520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1152520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    // Take clipping into account.
1153520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkIRect devClip, devCull;
1154520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    mappedCull.roundOut(&devCull);
1155520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->getClipDeviceBounds(&devClip);
1156520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (!devCull.intersect(devClip)) {
1157520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        devCull.setEmpty();
1158520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1159520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1160520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->validateCull(devCull);
1161520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    fCullStack.push(devCull); // balanced in popCull
1162520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1163520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1164520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1165520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::popCull() {
1166520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkASSERT(fCullStack.count() == fCullCount);
1167520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1168520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (fCullCount > 0) {
1169520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        --fCullCount;
1170520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        this->onPopCull();
1171520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1172520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        SkDEBUGCODE(fCullStack.pop());
1173520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1174520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1175520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1176520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11789bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
118050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11842c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
11862c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11889bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
11899bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
11909bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
119178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
119278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
119378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
119478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
119578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
119678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
119778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
119878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
119978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
12009bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12019bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
12029bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
12039bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
12049bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12059bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12081f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
12098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                  const SkPaint* paint) {
12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12158926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
12171f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
121876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
121976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
122076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
12222d97bc139a7de5813468bd3dbfd0037351ae5606fmalita            SkDeviceImageFilterProxy proxy(dstDev, fProps);
122376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
12246776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1225b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1226fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1227d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
12284cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1229be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
123055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
12314cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
12325efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
12335efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
12346776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
12356776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
123676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
123776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1238b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
123976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
12458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                          const SkPaint* paint) {
12468f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawSprite()");
124750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
12498926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
125050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
1251fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12528926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
12538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
12548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
12558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1256fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1258fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12598926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
12608926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
12618926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
12628926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12638926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
12642d97bc139a7de5813468bd3dbfd0037351ae5606fmalita            SkDeviceImageFilterProxy proxy(iter.fDevice, fProps);
12658926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
12666776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1267fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1268d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1269f622a6c8fd176acf9944de8df00d7f0bb56b67d3halcanary            const SkIRect clipBounds = bitmap.bounds();
1270be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
127155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
12724cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
12735efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
12745efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
12756776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
12765efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
12778926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
12788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
12798926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
12808926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
12818926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
12828926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
12838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
12848926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
128692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1287d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1288d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1289d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
129292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1293d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1294d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1295d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
129892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1299d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1300d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1301d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
130492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1305d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1306d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1307d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
130844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
130944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
131092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1311d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1312d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1313d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1314d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1316c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13171f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
131844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
131944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
132044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
132144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1324c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13251f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
132644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
13314b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1338759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
13398f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
13408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
13418f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
13428f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
13438f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1344da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1345da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
13461f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1347da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1348da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1349da17f758442f16747af39f8fbaed9c097048519creed@google.com
13503b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1351da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1352c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1353da17f758442f16747af39f8fbaed9c097048519creed@google.com
1354da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
13551f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1356da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1357da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1358da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1359da17f758442f16747af39f8fbaed9c097048519creed@google.com
13605c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
13615c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1363c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
13658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
13668f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13681f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.rectStaysRect()) {
1369123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
137098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
137198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
137298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13751f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&r, rect);
13768f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1377d954498c01ccf0417feacf89e45d0c62a06a813breed        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1379123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
138098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
138198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
138298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
13868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
139073e714eb766617ce06757829a3c0b345c7963faareedstatic void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
139173e714eb766617ce06757829a3c0b345c7963faareed                            SkRegion::Op op, bool doAA) {
1392d64c9487135094c83f658319f53ea2005ecc08b2reed    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1393819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1394819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1395759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
13968f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
13974ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
13988f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
13998f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14008f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
14014ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
14028f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
140314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
14048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
140514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
14061f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
140714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
140814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
140914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
141014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
14118f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
14128f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
14138f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
141414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
14158f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
141614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
141714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
141814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
141914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
142073e714eb766617ce06757829a3c0b345c7963faareed        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
14218f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
142214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
142314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
142414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
142514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
142614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
14278f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
14284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
14294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1430759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
14318f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14328f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
14338f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
14348f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
14358f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14368f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
14378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14388f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14398f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
14408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1441da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1442da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
14431f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1444da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1445da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1446fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
14473b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1448da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1449c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1450fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1451da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
14521f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1453da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1454da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1455da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1456da17f758442f16747af39f8fbaed9c097048519creed@google.com
14575c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14585c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1460c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
14628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
14638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
14661f836ee096bb988adef4b9757b2629c7afeda36dreed    path.transform(fMCRec->fMatrix, &devPath);
14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1468fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1469fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1470fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1471fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1472fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1473fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1474fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1475fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1476fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1477fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
14785c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
14798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
14805c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
148145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
148245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.reset();
148345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
148445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack* clipStack = getClipStack();
148545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
148645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack::Element* element;
148745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        while ((element = iter.next())) {
148845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkClipStack::Element::Type type = element->getType();
148945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkPath operand;
14902a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org            if (type != SkClipStack::Element::kEmpty_Type) {
14912a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org                element->asPath(&operand);
14922a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org            }
149345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkRegion::Op elementOp = element->getOp();
149445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            if (elementOp == SkRegion::kReplace_Op) {
149545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                devPath = operand;
149645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            } else {
149745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                Op(devPath, operand, (SkPathOp) elementOp, &devPath);
149845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            }
149996fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
150096fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // perhaps we need an API change to avoid this sort of mixed-signals about
150196fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // clipping.
15028f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            if (element->isAA()) {
15038f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                edgeStyle = kSoft_ClipEdgeStyle;
15048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            }
150545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
150645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
150745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
150845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
150973e714eb766617ce06757829a3c0b345c7963faareed    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1512759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
15138f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
15148f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15158f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15168f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
15175c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15185c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1520c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15225c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
15235c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1524115d931d2fbd3a109a21b28c8a9c5099e6c49c54reed@google.com    fClipStack.clipDevRect(rgn.getBounds(), op);
15255c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15261f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
15278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1529819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1530819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1531819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
15321f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1533ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
15345c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1535ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1536ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1537ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1538819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1539819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1540d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1541819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
154280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
15438182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
15448182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
15458182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
15468182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
15478182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
15488182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
15498182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15508182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
15518182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
15528182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15539cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
15549cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
15559cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
155673e714eb766617ce06757829a3c0b345c7963faareed                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
15579cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
15589cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1559819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1560819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1561819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1562819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1563819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
156490c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
156580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
15668182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
15678182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
15688182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
1569c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
157090c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
157190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
157290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
15735c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
15745c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1575754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
15761f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1577754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1578754de5f65b466f721d952a379194cc94de376f42reed@google.com
15795c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
15801f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
15815c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
15825c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
15833b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
15841607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1585116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1586116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
15871f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15911f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.hasPerspective()) {
1592a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
15931f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&dst, rect);
1594b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1595a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1596c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1597d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1598a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1599c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1600c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1601a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1602a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1603c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1604a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1605a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1606a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
16078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16103b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
16113b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
16128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16143b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1615bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
16168f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
16178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
16188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1620d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1621d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
16221f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
162372dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
162472dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
162572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1626d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1627d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1628d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
162949f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1630bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
16313b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
16323b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1633fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
16348f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
16358f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
16368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
16398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1641bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
16421f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1643bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1644bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1645bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1646bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1647bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1648bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1649bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
165049f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1651bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1652bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1653bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1654bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1655bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
16568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
16571f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16605c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
16611f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
16625c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16635c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16649c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
16659c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
16669c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessRenderTarget() : NULL;
16679c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
16689c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1669644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1670644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1671644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
167249f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
1673644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
167449f085dddff10473b6ebf832a974288300224e60bsalomon        if (renderTarget) {
1675644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1676644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1677644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1678644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1679644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1680644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1681644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1682644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1683e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1684ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1685ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
16868f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawDRRect()");
1687ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1688ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1689ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1690ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1691ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1692ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1693ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1694ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1695ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1696ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1697ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1698ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1699ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1700ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1701ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1702ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1703ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1704ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
17058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
17068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
17078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
17088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17092a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) {
17108ebaa7171246eb5b3a7dd65ba42ef42a888508d7fmalita    SkDrawIter  iter(this);
1711995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org    this->predrawNotify();
17122a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    while (iter.next()) {
17132a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com        iter.fDevice->clear(color);
17142a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    }
17152a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com}
17162a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com
171728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
171849f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
171928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
172028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
172128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
172228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) {
17248f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPaint()");
1725fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1726fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1727fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1728fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
172978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
17308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
17324e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
17338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
17368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
17398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
17408f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT1("skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
17418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
174578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
174678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1747a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1748a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1749a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1750a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1751a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1752a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1753a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
175478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
175578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
1756a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
1757a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1758fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1759a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
17608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
17618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
176278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
17634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
17648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
17654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
17684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
17698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17717ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
17728f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawRect()");
177378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
177478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
17758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
177678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(r, &storage);
177778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
17808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17814b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
178278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
17838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
17854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
17868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17884e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17914ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
17928f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawOval()");
179378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
179478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
17954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
179678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
179778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17984ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
17994ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
18004ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1801306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
180278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
180346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
180446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
180546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
180646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
180746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
180846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
18094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
18104ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
18114ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
18128f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawRRect()");
181378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
181478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
18154ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
181678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
181778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
18184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
18194ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
18204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
18214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
18224ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
18234ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
18244ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1825f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
1826f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
18274ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
1828f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1829f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
18304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1831f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
183278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1833f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1834f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
1835f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1836f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
1837f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1838f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
18394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
18404ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1841ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1842ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
1843ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
1844ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    const SkRect* bounds = NULL;
1845ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
1846ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1847ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        if (this->quickReject(*bounds)) {
1848ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org            return;
1849ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        }
1850ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
185125c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1852ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
185325c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1854ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
1855ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1856ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
185725c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1858ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
1859ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
18604ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
18617ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
18628f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPath()");
18639364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
18649364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
18659364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
18669364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
186778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
186878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1869fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
187078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
187178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
187278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18760b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
18770b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
18780b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
18796803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
1880fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
1881fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
1882fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
1883fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
18848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
18868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18884e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
18898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1894b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixrvoid SkCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top,
1895b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr                       const SkPaint* paint) {
18968f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawImage()");
1897b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr    image->draw(this, left, top, paint);
1898b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
1899b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
1900b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixrvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect* src,
1901b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr                           const SkRect& dst,
1902b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr                           const SkPaint* paint) {
19038f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawImageRect()");
19045ceff913cfd458c653358db7f60e995f505bce84piotaixr    image->drawRect(this, src, dst, paint);
1905b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
1906b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
19078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
19088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint* paint) {
19098f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawBitmap()");
19108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
19118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19123d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
19139efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
19149efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
19159efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
19169efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
19179efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
19189efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
19199efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
19209efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
19213b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
19228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
19238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
19248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19254b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
19278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
19289bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
19298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19319987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
19327112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1933eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
1934eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      DrawBitmapRectFlags flags) {
193550b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
19368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
19378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
193874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
193978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
194078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
19413d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
19429efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
19439efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
19449efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
19453b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
19463d60812865bb034851da777a91413ab584929887reed@google.com            return;
19473d60812865bb034851da777a91413ab584929887reed@google.com        }
19488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19493d60812865bb034851da777a91413ab584929887reed@google.com
195033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
195133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
195233535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
19538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19547064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
195578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
19567064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
195733535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
1958eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
1959f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
19607064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
196133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
19628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19647112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1965eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    const SkRect& dst, const SkPaint* paint,
1966eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    DrawBitmapRectFlags flags) {
19678f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawBitmapRectToRect()");
19689987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
1969eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
19709987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
19719987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
19738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPaint* paint) {
19748f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawBitmapMatrix()");
19758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
19769bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
19778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19799987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
19809987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkIRect& center, const SkRect& dst,
19819987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkPaint* paint) {
198250b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
198350b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org        return;
198450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    }
19853d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
198660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        SkRect storage;
198760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        const SkRect* bounds = &dst;
198860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
198960abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
199060abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
19913b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
19923d60812865bb034851da777a91413ab584929887reed@google.com            return;
19933d60812865bb034851da777a91413ab584929887reed@google.com        }
19943d60812865bb034851da777a91413ab584929887reed@google.com    }
19953d60812865bb034851da777a91413ab584929887reed@google.com
19969987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t w = bitmap.width();
19979987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t h = bitmap.height();
19989987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19999987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkIRect c = center;
20009987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // pin center to the bounds of the bitmap
20019987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fLeft = SkMax32(0, center.fLeft);
20029987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fTop = SkMax32(0, center.fTop);
20039987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fRight = SkPin32(center.fRight, c.fLeft, w);
20049987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
20059987ec3791336bad6af5cbe513564786b2df55aareed@google.com
20067112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcX[4] = {
20077d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
20087112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
20097112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcY[4] = {
20107d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
20117112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
20129987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstX[4] = {
20139987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
20149987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
20159987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
20169987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstY[4] = {
20179987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
20189987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
20199987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
202074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
20219987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstX[1] > dstX[2]) {
20229987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
20239987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[2] = dstX[1];
20249987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
202574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
20269987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstY[1] > dstY[2]) {
20279987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
20289987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[2] = dstY[1];
20299987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
203074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
20319987ec3791336bad6af5cbe513564786b2df55aareed@google.com    for (int y = 0; y < 3; y++) {
20327112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com        SkRect s, d;
20337112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com
20349987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fTop = srcY[y];
20359987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fBottom = srcY[y+1];
20369987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fTop = dstY[y];
20379987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fBottom = dstY[y+1];
20389987ec3791336bad6af5cbe513564786b2df55aareed@google.com        for (int x = 0; x < 3; x++) {
20399987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fLeft = srcX[x];
20409987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fRight = srcX[x+1];
20419987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fLeft = dstX[x];
20429987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fRight = dstX[x+1];
2043eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org            this->internalDrawBitmapRect(bitmap, &s, d, paint,
204431acc11977815402e4ef2681350f8559285bec97robertphillips@google.com                                         kNone_DrawBitmapRectFlag);
20459987ec3791336bad6af5cbe513564786b2df55aareed@google.com        }
20469987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
20479987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
20489987ec3791336bad6af5cbe513564786b2df55aareed@google.com
20499987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
20509987ec3791336bad6af5cbe513564786b2df55aareed@google.com                              const SkRect& dst, const SkPaint* paint) {
20518f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawBitmapNine()");
20529987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
20539987ec3791336bad6af5cbe513564786b2df55aareed@google.com
20549987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // Need a device entry-point, so gpu can use a mesh
20559987ec3791336bad6af5cbe513564786b2df55aareed@google.com    this->internalDrawBitmapNine(bitmap, center, dst, paint);
20569987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
20579987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2058f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2059f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
20601f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2061112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2062112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2063a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2064112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2065f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2066f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2067f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2068f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2069f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2070f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2071f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2072f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2073f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
20742c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
20752c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2076f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2077f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
207852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
207952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
208017b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
208152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
208252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
208352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
208417b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
208552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
208652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
208752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
208852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
208952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
209052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
209152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
209252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
209352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
209452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
209552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
209652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
209752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
209852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
209952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
210052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
210152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
210252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
210352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
210452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
210552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
210652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
210752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
210852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
210952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
211052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
211152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
211252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
211352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
211452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
211552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
211652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
211752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
211852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
211952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
212052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
212152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
212252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
212352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
212452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
212552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
212652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
212752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
212852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
212952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
213052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
213152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
213252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
213352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
213452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
213552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
213652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
213752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
213852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
213952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
214052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
214152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
214252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
214352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
214452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
214552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
214652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
214752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
214852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
214952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2150e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2151e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
215278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
21538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2156f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
215752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
215852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21614e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2164e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2165e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
216605c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
216705c4a4322e7d4f3417b7df33825bab8603d52051fmalita
216878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
216987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
217205c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2173f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
21748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2175b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
21764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2179e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2180e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
218105c4a4322e7d4f3417b7df33825bab8603d52051fmalita
218205c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
218305c4a4322e7d4f3417b7df33825bab8603d52051fmalita
218478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
218587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
21868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
218805c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2189f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
21908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2191b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
21924e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2195e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2196e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
219778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
219887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
21998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
22014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
22028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2203b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2204945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
22054325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
22064325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
220700d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
220800d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
22097ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
221019653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
22117ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        SkRect storage;
22127ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
22137ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) {
22147ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita            return;
22157ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        }
22167ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
22177ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2218aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
221900d5c2c6523321d25b32905ff4822f083a4173eefmalita
2220aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2221aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2222aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint());
222300d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
222400d5c2c6523321d25b32905ff4822f083a4173eefmalita
2225aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
222600d5c2c6523321d25b32905ff4822f083a4173eefmalita}
222700d5c2c6523321d25b32905ff4822f083a4173eefmalita
2228e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2229e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2230e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
22318f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawText()");
2232e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2233e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2234e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2235e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
22368f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPosText()");
2237e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2238e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2239e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2240e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
22418f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPosTextH()");
2242e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2243e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2244e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2245e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
22468f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawTextOnPath()");
2247e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2248e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
224900d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
225000d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
22518f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawTextBlob()");
225249f085dddff10473b6ebf832a974288300224e60bsalomon    if (blob) {
225300d5c2c6523321d25b32905ff4822f083a4173eefmalita        this->onDrawTextBlob(blob, x, y, paint);
225400d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
225500d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2256e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
22578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
22588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPoint verts[], const SkPoint texs[],
22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkColor colors[], SkXfermode* xmode,
22608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const uint16_t indices[], int indexCount,
22618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
22628f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawVertices()");
226378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
22644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
22674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
22684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
22728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2274b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2275b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
22768f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPatch()");
2277b3c9d1c33caf325aada244204215eb790c228c12dandov    if (NULL == cubics) {
2278b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2279b3c9d1c33caf325aada244204215eb790c228c12dandov    }
22806cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2281ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2282ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2283ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2284b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2285ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2286ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2287ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
22886cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2289b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2290b3c9d1c33caf325aada244204215eb790c228c12dandov}
2291b3c9d1c33caf325aada244204215eb790c228c12dandov
2292b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2293b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2294b3c9d1c33caf325aada244204215eb790c228c12dandov
2295ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
22966cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2297ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2298b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2299ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
23006cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2301ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2302ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2303ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
23046a070dc06af4e9f305f9d08a69e34d18ade473cbreedvoid SkCanvas::EXPERIMENTAL_drawDrawable(SkCanvasDrawable* dr) {
23056be2aa9a251bf6022570a03140f956655b3ef1dareed    if (dr && !this->quickReject(dr->getBounds())) {
23066be2aa9a251bf6022570a03140f956655b3ef1dareed        this->onDrawDrawable(dr);
23076a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
23086a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
23096a070dc06af4e9f305f9d08a69e34d18ade473cbreed
23106a070dc06af4e9f305f9d08a69e34d18ade473cbreedvoid SkCanvas::onDrawDrawable(SkCanvasDrawable* dr) {
23116a070dc06af4e9f305f9d08a69e34d18ade473cbreed    dr->draw(this);
23126a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
23136a070dc06af4e9f305f9d08a69e34d18ade473cbreed
23148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
23158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
23168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
23178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
23188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2320845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
23218f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawARGB()");
23228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
23238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2325845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
23260baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
23278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
23298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2331845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
23328f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawColor()");
23338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
23348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2336845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
23370baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
23388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
23408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
23438f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPoint(SkPaint)");
23448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
23454b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
23478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
23488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
23518f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPoint(SkColor)");
23528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
23538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
23544b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
23568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
23578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
23588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
23618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
23628f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawLine()");
23638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
23644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
23668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
23678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
23688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
23718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
23728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
23738f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawRectCoords()");
23748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
23758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
23778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
23788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
23818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
23828f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawCircle()");
23838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
23848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
23858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
23888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
23894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
23908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
23938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
23948f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawRoundRect()");
23958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
23968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
23978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
23983b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
23998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
24008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
24018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
24024ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
24034ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
24044ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
24058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
24068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
24078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
24118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
24128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
24138f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawArc()");
24148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
24158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
24168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
24178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
24188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
24198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
24208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
24218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
24228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
24238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
24248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
24258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
24268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
24308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
24318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
24328f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawTextOnPathHV()");
24338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
24344b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
24368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
24378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2439f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
24409b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkCanvas::drawPicture(const SkPicture* picture) {
24418f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPicture()");
244249f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2443d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->onDrawPicture(picture, NULL, NULL);
24449b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    }
24459b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips}
24469b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2447d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
24488f757f540a8378c7b1354aab3d4650eaa920b17adanakj    TRACE_EVENT0("skia", "SkCanvas::drawPicture(SkMatrix, SkPaint)");
244949f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2450d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix && matrix->isIdentity()) {
2451d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            matrix = NULL;
2452d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2453d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        this->onDrawPicture(picture, matrix, paint);
2454d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2455d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
24569b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2457d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2458d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2459145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
246049f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2461145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2462145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2463d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2464145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2465145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2466145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2467145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
2468a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2469d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2470c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
24718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
24748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
24758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2477d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
24788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
24808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
24828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
24838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
24868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
24878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
24908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
24918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24931f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
24948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
24958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
24988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
24998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
25038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
25048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
25058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
25078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
25108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
25118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
251220a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
251320a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
251420a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2515c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
25163107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25173107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
25183107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25193107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
25203107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
25213107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
25223107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
25233107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
25243107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
25253107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
25263107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25273107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25283107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
25293107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
25303107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
253128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
25323107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
25333107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
25343107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
25353107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25363107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25373107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
25383107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
25393107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25403107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgSkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
25413107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
25423107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        return NULL;
25433107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25443107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25453107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkBitmap bitmap;
2546848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap.tryAllocPixels(info)) {
25473107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        return NULL;
25483107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25493107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25503107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    // should this functionality be moved into allocPixels()?
25513107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!bitmap.info().isOpaque()) {
25523107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        bitmap.eraseColor(0);
25533107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25543107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
25553107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
255642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org
255742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
255842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
255942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
256042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2561eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
256242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
256342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
256442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
256542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
256642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
256742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2568d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2569d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2570d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2571d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2572a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2573d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2574d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2575d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
257649f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2577a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2578d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2579a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2580d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2581a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
258249f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2583d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2584d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
25856cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
258649f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2587d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2588d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2589d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2590d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2591d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2592d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2593d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2594