SkCanvas.cpp revision 6b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBounder.h"
139c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org#include "SkDeviceImageFilterProxy.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
1774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
1845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
200017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
2552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
26a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
30644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
31644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
32644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
33da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
34da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
3515e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
59ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#ifdef SK_DEBUG
60ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#include "SkPixelRef.h"
61ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
62f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com/*
63f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  Some pixelref subclasses can support being "locked" from another thread
64f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  during the lock-scope of skia calling them. In these instances, this balance
65f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  check will fail, but may not be indicative of a problem, so we allow a build
66f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  flag to disable this check.
67f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *
68f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  Potentially another fix would be to have a (debug-only) virtual or flag on
69f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  pixelref, which could tell us at runtime if this check is valid. That would
70f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  eliminate the need for this heavy-handed build check.
71f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com */
72f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK
73f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.comclass AutoCheckLockCountBalance {
74f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.compublic:
75f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com    AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ }
76f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com};
77f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#else
78ea033606a06d05d2d42aa7118409fee798e53167reed@google.comclass AutoCheckLockCountBalance {
79ea033606a06d05d2d42aa7118409fee798e53167reed@google.compublic:
80ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) {
81ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0;
82ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
83ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    ~AutoCheckLockCountBalance() {
84ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        const int count = fPixelRef ? fPixelRef->getLockCount() : 0;
85ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        SkASSERT(count == fLockCount);
86ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
87ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
88ea033606a06d05d2d42aa7118409fee798e53167reed@google.comprivate:
89ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    const SkPixelRef* fPixelRef;
90ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    int               fLockCount;
91ea033606a06d05d2d42aa7118409fee798e53167reed@google.com};
92f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#endif
93ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
9453783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.orgclass AutoCheckNoSetContext {
9553783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.orgpublic:
9653783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) {
9753783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org        this->assertNoSetContext(fPaint);
9853783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    }
9953783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    ~AutoCheckNoSetContext() {
10053783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org        this->assertNoSetContext(fPaint);
10153783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    }
10253783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
10353783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.orgprivate:
10453783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    const SkPaint& fPaint;
10553783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
10653783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    void assertNoSetContext(const SkPaint& paint) {
10753783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org        SkShader* s = paint.getShader();
10853783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org        if (s) {
10953783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org            SkASSERT(!s->setContextHasBeenCalled());
11053783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org        }
11153783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    }
11253783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org};
11353783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
114ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#define CHECK_LOCKCOUNT_BALANCE(bitmap)  AutoCheckLockCountBalance clcb(bitmap)
11553783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org#define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext     cshsc(paint)
116ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
117ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#else
118ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    #define CHECK_LOCKCOUNT_BALANCE(bitmap)
11953783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    #define CHECK_SHADER_NOSETCONTEXT(paint)
120ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#endif
121ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
1222c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
1232c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
12497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() {
12597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
126c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
12797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
12897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
12997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1321f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1411f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix*     fMatrix;
1446f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1461f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            : fNext(NULL) {
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != device) {
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
15040a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1524b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
15488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fDevice) {
15840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
16188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
16288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
165045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
1666f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
1676f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
1704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
1794b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
1864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1923fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
1933fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
201f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
202f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2040e354aacd84d3bede3f97cbde35a54ba62a89533bsalomon@google.com    SkMatrix    fMatrixStorage;
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2166c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    int             fFlags;
2170017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkMatrix*       fMatrix;        // points to either fMatrixStorage or prev MCRec
2180017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip*   fRasterClip;    // points to either fRegionStorage or prev MCRec
2190017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkDrawFilter*   fFilter;        // the current filter (or null)
2204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*   fLayer;
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
22888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    DeviceCM*   fTopLayer;
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2306c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    MCRec(const MCRec* prev, int flags) : fFlags(flags) {
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != prev) {
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (flags & SkCanvas::kMatrix_SaveFlag) {
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrixStorage = *prev->fMatrix;
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrix = &fMatrixStorage;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrix = prev->fMatrix;
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2384b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (flags & SkCanvas::kClip_SaveFlag) {
2400017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClipStorage = *prev->fRasterClip;
2410017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClip = &fRasterClipStorage;
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2430017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClip = prev->fRasterClip;
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter = prev->fFilter;
24782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkSafeRef(fFilter);
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTopLayer = prev->fTopLayer;
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {   // no prev
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.reset();
2524b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix     = &fMatrixStorage;
2540017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            fRasterClip = &fRasterClipStorage;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter     = NULL;
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTopLayer   = NULL;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
26482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2700017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkMatrix        fMatrixStorage;
2710017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip    fRasterClipStorage;
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2768a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
2774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
2788a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com        fClipStack = &canvas->fClipStack;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBounder = canvas->getBounder();
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
2848a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
295f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
296f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
299045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
300045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBitmap = &fDevice->accessBitmap(true);
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
304f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fBounder) {
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fBounder->setClip(fClip);
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
311199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3171f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
3186f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3196f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3236f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3378926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
33878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
33978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
3404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
3424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
3434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
3448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        fDoClearImageFilter = false;
3454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
3488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
3498926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            tmp.setImageFilter(fOrigPaint.getImageFilter());
350e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
351e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                            true, SkCanvas::kFullLayer_SaveLayerStrategy);
3528926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // we'll clear the imageFilter for the actual draws in next(), so
3538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // it will only be applied during the restore().
3548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fDoClearImageFilter = true;
3558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3568926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
35779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
35879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
35979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
36079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
361129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
362129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
36379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = NULL;
364129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
365129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = !fFilter && !fDoClearImageFilter;
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
36874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3694e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
3708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (fDoClearImageFilter) {
3718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
3728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
37574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
3774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
3784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
3794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
38074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
381129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
382129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
383129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
384129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
385129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
386129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fPaint = &fOrigPaint;
387129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
388129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
389129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
390129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
391fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
39274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3942c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazyPaint;
3952c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
3962c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
3972c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
3982c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
3992c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
4008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    bool            fDoClearImageFilter;
4012c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
402129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
40379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
40479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
405129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
406129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
409129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
410632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
411129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
41279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
413632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
414129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkPaint* paint = fLazyPaint.set(fOrigPaint);
4158926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
416129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fDoClearImageFilter) {
417129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
418129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
4198926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
42079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
421129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
422129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
423129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
424129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
425971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
426971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
427971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
428971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
42979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (NULL == fLooperContext) {
430129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
431632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
432632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
433129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
434129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
4358926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
436129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
43779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
4384e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
4394e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
441632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
442632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
4434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
4444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
4454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
4474e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
4484e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Stack helper for managing a SkBounder. In the destructor, if we were
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    given a bounder, we call its commit() method, signifying that we are
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    done accumulating bounds for that draw.
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit {
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkAutoBounderCommit() {
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fBounder) {
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBounder->commit();
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBounder*  fBounder;
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
464e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoBounderCommit(...) SK_REQUIRE_LOCAL_VAR(SkAutoBounderCommit)
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
47197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
4728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    AutoDrawLooper  looper(this, paint, true);                      \
4738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
4748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkAutoBounderCommit ac(fBounder);                           \
4758926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
4768926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
47778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
47897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
47978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    AutoDrawLooper  looper(this, paint, false, bounds);             \
4804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoBounderCommit ac(fBounder);                           \
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
4834b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
4844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4881f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::init(SkBaseDevice* device) {
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBounder = NULL;
490c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
491c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
4928f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
49345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
494447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org    fDeviceCMDirty = false;
495b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount = 0;
496210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    fCullCount = 0;
49774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    new (fMCRec) MCRec(NULL, 0);
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50240a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
506f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
507403f8d7a052269583175e945689824838e5e0ef4commit-bot@chromium.org    return this->setRootDevice(device);
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
510cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
511e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
512e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
5138d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
514ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
5158d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    this->init(NULL);
5168d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
5178d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
518e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.orgSkCanvas::SkCanvas(int width, int height)
519e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
520e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
521e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
522ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
523e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    SkBitmap bitmap;
524900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    bitmap.setConfig(SkImageInfo::MakeUnknown(width, height));
525e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
526e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org}
527e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
5281f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkCanvas::SkCanvas(SkBaseDevice* device)
529e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
530e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->init(device);
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap)
537e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
538e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5411f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
547b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    SkASSERT(0 == fSaveLayerCount);
5487c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5518d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    SkSafeUnref(fBounder);
55274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
553b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) {
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fBounder, bounder);
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return bounder;
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
57174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
57274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
57374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
57474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
57574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
57674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
57774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
57874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
57974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
582bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
5831f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
584bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
585bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
586bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
587bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
588bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
5894ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
5904ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
5914ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
5924ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
5934ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
5944ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
5954ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
5964ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
5974ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
5984ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
5994ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
6001f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
601210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
602210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
603210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
6041f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
606c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
6120b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
6130b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
6140b53d59a24f667350b4282f88470713902409030reed@google.com    }
6159266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
6169266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
6179266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
618403f8d7a052269583175e945689824838e5e0ef4commit-bot@chromium.orgSkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
6204c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    SkDeque::F2BIter iter(fMCStack);
6214c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    MCRec*           rec = (MCRec*)iter.next();
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
6231f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*    rootDevice = rec->fLayer->fDevice;
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice == device) {
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return device;
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6284b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (device) {
63040a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        device->onAttachToCanvas(this);
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice) {
63340a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        rootDevice->onDetachFromCanvas();
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rootDevice = device;
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
6404b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Now we update our initial region to have the bounds of the new device,
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and then intersect all of the clips in our stack with these bounds,
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to ensure that we can't draw outside of the device's bounds (and trash
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                     memory).
6454b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this is only a partial-fix, since if the new device is larger than
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the previous one, we don't know how to "enlarge" the clips in our stack,
6484b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        so drawing may be artificially restricted. Without keeping a history of
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reconstruct the correct clips, so this approximation will have to do.
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The caller really needs to restore() back to the base if they want to
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        accurately take advantage of the new device bounds.
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65542aea289cbf801997b653a906a37a7f7e948b645reed@google.com    SkIRect bounds;
65642aea289cbf801997b653a906a37a7f7e948b645reed@google.com    if (device) {
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bounds.set(0, 0, device->width(), device->height());
65842aea289cbf801997b653a906a37a7f7e948b645reed@google.com    } else {
65942aea289cbf801997b653a906a37a7f7e948b645reed@google.com        bounds.setEmpty();
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
66142aea289cbf801997b653a906a37a7f7e948b645reed@google.com    // now jam our 1st clip to be bounds, and intersect the rest with that
66242aea289cbf801997b653a906a37a7f7e948b645reed@google.com    rec->fRasterClip->setRect(bounds);
66342aea289cbf801997b653a906a37a7f7e948b645reed@google.com    while ((rec = (MCRec*)iter.next()) != NULL) {
66442aea289cbf801997b653a906a37a7f7e948b645reed@google.com        (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op);
66542aea289cbf801997b653a906a37a7f7e948b645reed@google.com    }
66642aea289cbf801997b653a906a37a7f7e948b645reed@google.com
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return device;
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
670a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
671a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
672a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
673a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
674a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
675a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
676a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == bitmap->pixelRef()) {
677a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        if (!bitmap->allocPixels()) {
678a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
679a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
680a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
681a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
682a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
683a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBitmap bm(*bitmap);
684a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bm.lockPixels();
685a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
686a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return true;
687a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
688a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
689a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
690a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->setPixelRef(NULL);
691a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
692a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
693a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
69451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
695c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
696a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
697a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
698a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
699a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
700ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
701ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
70274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
703a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!bitmap->allocN32Pixels(r.width(), r.height())) {
704a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
705a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
706a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
707a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
708a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
709daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
710c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
711a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
712a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
713c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
714a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) {
715a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    switch (origInfo.colorType()) {
716a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kUnknown_SkColorType:
717a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kIndex_8_SkColorType:
718a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
719a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        default:
720a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            break;
721a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
722a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == dstP || rowBytes < origInfo.minRowBytes()) {
723a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
724a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
725a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (0 == origInfo.width() || 0 == origInfo.height()) {
72651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        return false;
72751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
728a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
729a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
730a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
731a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
732a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
733a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
734a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
735a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
736a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!srcR.intersect(0, 0, size.width(), size.height())) {
737a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
738a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
739db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
740a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkImageInfo info = origInfo;
741a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // the intersect may have shrunk info's logical size
742a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    info.fWidth = srcR.width();
743a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    info.fHeight = srcR.height();
744db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
745a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
746a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (x > 0) {
747a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        x = 0;
748a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
749a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (y > 0) {
750a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        y = 0;
751a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
752a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // here x,y are either 0 or negative
753a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
754db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
755a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
756a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
75751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
75851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7594cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
7604cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
7614cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7624cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7634cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBitmap bm(bitmap);
7644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    bm.lockPixels();
7654cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bm.getPixels()) {
7664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
7674cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7684cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
7694cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
7704cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7714cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
7724cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
7734cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
7744cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
7754cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
7764cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
7774cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
7784cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
7794cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7804cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
7814cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7824cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7834cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7844cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
7854cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
7864cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
7874cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7884cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7894cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7904cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
7914cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
7924cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7934cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7944cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7954cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkImageInfo info = origInfo;
7964cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
7974cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    info.fWidth = target.width();
7984cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    info.fHeight = target.height();
7994cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8004cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
8014cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
8024cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
8034cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8044cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
8054cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
8064cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8074cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
8084cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
8094cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8104cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
8114ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
8124cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
81351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8144370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
8154370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
8164370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8174370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
823045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        const SkRasterClip& totalClip = *fMCRec->fRasterClip;
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
8254b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
82746799cd9f0bded51a189d77731b25af159ab4609reed@google.com            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
829045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
83146799cd9f0bded51a189d77731b25af159ab4609reed@google.com                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) {
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int saveCount = this->getSaveCount(); // record this before the actual save
8424b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
8454b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
8474b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8486c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    if (SkCanvas::kClip_SaveFlag & flags) {
8496c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org        fClipStack.save();
8506c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    }
8515c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return saveCount;
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
855e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgvoid SkCanvas::willSave(SaveFlags) {
856e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // Do nothing. Subclasses may do something.
857e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org}
858e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) {
860e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    this->willSave(flags);
8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // call shared impl
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->internalSave(flags);
8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
866b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
868b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
869b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
870b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
873a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
874c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                               SkIRect* intersection, const SkImageFilter* imageFilter) {
875bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
876c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkRegion::Op op = SkRegion::kIntersect_Op;
877bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
878a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
879f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
880c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
881c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
882c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        imageFilter->filterBounds(clipBounds, *fMCRec->fMatrix, &clipBounds);
883c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        // Filters may grow the bounds beyond the device bounds.
884c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        op = SkRegion::kReplace_Op;
885c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
886bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != bounds) {
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
8894b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->getTotalMatrix().mapRect(&r, *bounds);
8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
894bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
8950017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fMCRec->fRasterClip->setEmpty();
896bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
897a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
90389f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
90489f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        fClipStack.clipDevRect(ir, op);
90589f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        // early exit if the clip is now empty
90689f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        if (!fMCRec->fRasterClip->op(ir, op)) {
90789f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org            return false;
90889f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        }
909a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
910a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
911a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
912a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
913a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
914a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
915a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
916a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
917e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgSkCanvas::SaveLayerStrategy SkCanvas::willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) {
918e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
919e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // Do nothing. Subclasses may do something.
920e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return kFullLayer_SaveLayerStrategy;
921e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org}
922e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
923a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
924a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org                        SaveFlags flags) {
925e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // Overriding classes may return false to signal that we don't need to create a layer.
926e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
927e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return this->internalSaveLayer(bounds, paint, flags, false, strategy);
9288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
9298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
9302b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.orgstatic SkBaseDevice* create_compatible_device(SkCanvas* canvas,
9312b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.org                                              const SkImageInfo& info) {
93276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* device = canvas->getDevice();
93315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    return device ? device->createCompatibleDevice(info) : NULL;
93476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
93576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
936e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgint SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
937e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                bool justForImageFilter, SaveLayerStrategy strategy) {
938b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
939b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    flags = (SaveFlags)(flags | kClipToLayer_SaveFlag);
940b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
941b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
942a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
943a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
944a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    int count = this->internalSave(flags);
945a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
946a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
947a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
948a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
949c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return count;
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
953e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
954e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
955e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
956e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org        return count;
957e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
958e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
959b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    // Kill the imagefilter if our device doesn't allow it
960b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    SkLazyPaint lazyP;
961b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    if (paint && paint->getImageFilter()) {
962b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
9638926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            if (justForImageFilter) {
9648926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                // early exit if the layer was just for the imageFilter
9658926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                return count;
9668926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
967b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            SkPaint* p = lazyP.set(*paint);
968b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            p->setImageFilter(NULL);
969b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            paint = p;
970b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
971b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
972b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com
97315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
97415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
97515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9771f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device;
97876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    if (paint && paint->getImageFilter()) {
9792b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.org        device = create_compatible_device(this, info);
98076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    } else {
98115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        device = this->createLayerDevice(info);
98276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    }
983e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    if (NULL == device) {
984e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        SkDebugf("Unable to create device for layer.");
985e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        return count;
986e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
987e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
9886f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
98940a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
996b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount += 1;
9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1011e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgvoid SkCanvas::willRestore() {
1012e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // Do nothing. Subclasses may do something.
1013e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org}
1014e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() {
10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // check for underflow
10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCStack.count() > 1) {
1018e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org        this->willRestore();
10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->internalRestore();
10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1027c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10296c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    if (SkCanvas::kClip_SaveFlag & fMCRec->fFlags) {
10306c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org        fClipStack.restore();
10316c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    }
10326c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
103388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != layer) {
10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
10496f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
10508926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
10518926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                     layer->fPaint);
10528926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
10547c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
1055b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            SkASSERT(fSaveLayerCount > 0);
1056b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            fSaveLayerCount -= 1;
10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(layer);
105988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const {
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCStack.count();
10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) {
10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // sanity check
10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count < 1) {
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count = 1;
10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
107174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
1072b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com    int n = this->getSaveCount() - count;
1073b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com    for (int i = 0; i < n; ++i) {
10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->restore();
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10787c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.combool SkCanvas::isDrawingToLayer() const {
1079b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    return fSaveLayerCount > 0;
10807c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com}
10817c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
108276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
108376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    return this->onNewSurface(info);
108476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
108576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
108676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
108776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
108876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    return dev ? dev->newSurface(info) : NULL;
108976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
109076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1091c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1092c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1093c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1094c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1095c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1096900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1097c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1098c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1099c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1100c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1101c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return this->onPeekPixels(info, rowBytes);
1102c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1103c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1104c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1105c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1106c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return dev ? dev->peekPixels(info, rowBytes) : NULL;
1107c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1108c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
11096b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
11106b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
11116b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    if (pixels && origin) {
11126b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
11136b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
11146b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    return pixels;
11159c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
11169c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
11179c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comvoid* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
11189c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
11199c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessPixels(info, rowBytes) : NULL;
11209c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
11219c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1122c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1123c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1124c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1125c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1126a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.allocPixels(fInfo)) {
1127c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1128c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1129c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1130c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1131c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1132c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1133c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1134c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1135c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1136c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1137c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1138c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1139c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
1140c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes,
1141c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org                                     NULL, NULL);
1142c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1143c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1144c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1145c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1146c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1147c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1148210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.orgvoid SkCanvas::onPushCull(const SkRect& cullRect) {
1149210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    // do nothing. Subclasses may do something
1150210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org}
1151210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org
1152210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.orgvoid SkCanvas::onPopCull() {
1153210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    // do nothing. Subclasses may do something
1154210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org}
1155210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
1157520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef SK_DEBUG
1158520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org// Ensure that cull rects are monotonically nested in device space.
1159520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::validateCull(const SkIRect& devCull) {
1160520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (fCullStack.isEmpty()
1161520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        || devCull.isEmpty()
1162520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        || fCullStack.top().contains(devCull)) {
1163520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        return;
1164520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1165520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1166520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
1167520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
1168520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              fCullStack.top().x(), fCullStack.top().y(),
1169520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              fCullStack.top().right(), fCullStack.top().bottom()));
1170520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1171520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef ASSERT_NESTED_CULLING
1172520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkDEBUGFAIL("Invalid cull.");
1173520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1174520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1175520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1176520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1177520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::pushCull(const SkRect& cullRect) {
1178520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    ++fCullCount;
1179520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->onPushCull(cullRect);
1180520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1181520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef SK_DEBUG
1182520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    // Map the cull rect into device space.
1183520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkRect mappedCull;
1184520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->getTotalMatrix().mapRect(&mappedCull, cullRect);
1185520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1186520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    // Take clipping into account.
1187520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkIRect devClip, devCull;
1188520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    mappedCull.roundOut(&devCull);
1189520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->getClipDeviceBounds(&devClip);
1190520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (!devCull.intersect(devClip)) {
1191520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        devCull.setEmpty();
1192520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1193520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1194520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->validateCull(devCull);
1195520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    fCullStack.push(devCull); // balanced in popCull
1196520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1197520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1198520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1199520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::popCull() {
1200520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkASSERT(fCullStack.count() == fCullCount);
1201520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1202520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (fCullCount > 0) {
1203520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        --fCullCount;
1204520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        this->onPopCull();
1205520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1206520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        SkDEBUGCODE(fCullStack.pop());
1207520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1208520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1209520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1210520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12129bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
121450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12182c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12202c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12229bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12239bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
12249bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    CHECK_LOCKCOUNT_BALANCE(bitmap);
12259bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
122678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
122778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
122878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
122978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
123078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
123178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
123278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
123378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
123478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
12359bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12369bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
12379bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
12389bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
12399bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12409bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12431f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
12448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                  const SkPaint* paint) {
12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp.setDither(true);
12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12518926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
12531f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
125476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
125576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
125676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
12589c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org            SkDeviceImageFilterProxy proxy(dstDev);
125976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
12606776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1261b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1262fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1263d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
12644cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
12651a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
12661a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            SkAutoUnref aur(NULL);
12671a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            if (!cache) {
12681a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org                cache = SkImageFilter::Cache::Create();
12691a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org                aur.reset(cache);
12701a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            }
1271f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            SkImageFilter::Context ctx(matrix, clipBounds, cache);
12724cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
12735efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
12745efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
12756776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
12766776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
127776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
127876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1279b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
128076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
12868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                          const SkPaint* paint) {
128750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12888926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
12898926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
129050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
129150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    CHECK_LOCKCOUNT_BALANCE(bitmap);
1292fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12938926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
12948926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
12958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
12968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1297fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1299fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
13018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
13028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
13038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
13048926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
13059c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org            SkDeviceImageFilterProxy proxy(iter.fDevice);
13068926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
13076776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1308fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1309d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
13104cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
13111a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
13121a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            SkAutoUnref aur(NULL);
13131a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            if (!cache) {
13141a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org                cache = SkImageFilter::Cache::Create();
13151a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org                aur.reset(cache);
13161a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            }
1317f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            SkImageFilter::Context ctx(matrix, clipBounds, cache);
13184cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
13195efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
13205efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
13216776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
13225efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
13238926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
13248926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
13258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
13268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
13278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
13288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
13298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
13308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
133292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1333d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1334d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1335d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
133892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1339d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1340d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1341d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
134492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1345d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1346d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1347d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
135092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1351d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1352d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1353d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
135444c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
135544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
135644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkCanvas::didConcat(const SkMatrix&) {
135744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    // Do nothing. Subclasses may do something.
13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
136092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1361d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1362d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1363d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1364d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1366c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
136792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org    fMCRec->fMatrix->preConcat(matrix);
136844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
136944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
137044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
137144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
137244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.orgvoid SkCanvas::didSetMatrix(const SkMatrix&) {
137344c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    // Do nothing. Subclasses may do something.
13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1378c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *fMCRec->fMatrix = matrix;
138044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
13854b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1392759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
13938f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
13948f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
13958f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
13968f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
13978f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1398da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1399da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
1400da17f758442f16747af39f8fbaed9c097048519creed@google.com        if (fMCRec->fRasterClip->isEmpty()) {
1401da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1402da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1403da17f758442f16747af39f8fbaed9c097048519creed@google.com
14043b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1405da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1406c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1407da17f758442f16747af39f8fbaed9c097048519creed@google.com
1408da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
1409da17f758442f16747af39f8fbaed9c097048519creed@google.com            return fMCRec->fRasterClip->setEmpty();
1410da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1411da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1412da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1413da17f758442f16747af39f8fbaed9c097048519creed@google.com
14145c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14155c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1417c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14188f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
14198f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
14208f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCRec->fMatrix->rectStaysRect()) {
1423123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
142498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
142598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
142698de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMCRec->fMatrix->mapRect(&r, rect);
14308f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
14318f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1433123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
143498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
143598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
143698de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
14408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14448f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comstatic void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
14458f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                             const SkPath& devPath, SkRegion::Op op, bool doAA) {
1446759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    // base is used to limit the size (and therefore memory allocation) of the
1447759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    // region that results from scan converting devPath.
1448759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    SkRegion base;
1449759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com
1450819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    if (SkRegion::kIntersect_Op == op) {
1451759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // since we are intersect, we can do better (tighter) with currRgn's
1452759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // bounds, than just using the device. However, if currRgn is complex,
1453759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // our region blitter may hork, so we do that case in two steps.
14540017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        if (currClip->isRect()) {
1455b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // FIXME: we should also be able to do this when currClip->isBW(),
1456b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // but relaxing the test above triggers GM asserts in
1457b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // SkRgnBuilder::blitH(). We need to investigate what's going on.
14588f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->setPath(devPath, currClip->bwRgn(), doAA);
1459759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        } else {
14600017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            base.setRect(currClip->getBounds());
14610017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            SkRasterClip clip;
14620017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            clip.setPath(devPath, base, doAA);
14638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->op(clip, op);
1464759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        }
1465819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    } else {
14661f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        const SkBaseDevice* device = canvas->getDevice();
1467ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        if (!device) {
14688f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->setEmpty();
14698f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            return;
1470ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        }
1471ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1472a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        base.setRect(0, 0, device->width(), device->height());
1473819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1474819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        if (SkRegion::kReplace_Op == op) {
14758f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->setPath(devPath, base, doAA);
1476819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        } else {
14770017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            SkRasterClip clip;
14780017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            clip.setPath(devPath, base, doAA);
14798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->op(clip, op);
1480819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1481819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1482819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1483819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1484759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
14858f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14864ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
14878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
14888f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14898f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
14904ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
14918f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
149214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
14938f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
149414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
149514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) {
149614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
149714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
149814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
149914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
15008f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
15018f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
15028f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
150314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
15048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
150514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
150614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
150714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
150814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
15098f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
15108f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
151114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
151214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
151314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
151414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
151514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
15168f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
15174ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
15184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1519759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
15208f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15218f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
15228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
15238f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
15248f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
15258f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
15268f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15278f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15288f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15298f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1530da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1531da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1532da17f758442f16747af39f8fbaed9c097048519creed@google.com        if (fMCRec->fRasterClip->isEmpty()) {
1533da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1534da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1535fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
15363b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1537da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1538c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1539fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1540da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
1541da17f758442f16747af39f8fbaed9c097048519creed@google.com            return fMCRec->fRasterClip->setEmpty();
1542da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1543da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1544da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1545da17f758442f16747af39f8fbaed9c097048519creed@google.com
15465c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15475c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1549c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
15518f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
15528f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
15558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path.transform(*fMCRec->fMatrix, &devPath);
15568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1557fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1558fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1559fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1560fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1561fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1562fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1563fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1564fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1565fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1566fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
15675c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
15688f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
15695c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
157045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
157145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.reset();
157245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
157345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack* clipStack = getClipStack();
157445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
157545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack::Element* element;
157645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        while ((element = iter.next())) {
157745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkClipStack::Element::Type type = element->getType();
157845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            if (type == SkClipStack::Element::kEmpty_Type) {
157945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                continue;
158045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            }
158145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkPath operand;
1582e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            element->asPath(&operand);
158345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkRegion::Op elementOp = element->getOp();
158445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            if (elementOp == SkRegion::kReplace_Op) {
158545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                devPath = operand;
158645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            } else {
158745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                Op(devPath, operand, (SkPathOp) elementOp, &devPath);
158845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            }
158996fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
159096fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // perhaps we need an API change to avoid this sort of mixed-signals about
159196fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // clipping.
15928f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            if (element->isAA()) {
15938f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                edgeStyle = kSoft_ClipEdgeStyle;
15948f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            }
159545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
159645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
159745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
159845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
15998f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle);
16008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1602759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
1603ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                                                   bool inverseFilled) {
1604ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // This is for updating the clip conservatively using only bounds
1605ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // information.
1606ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // Contract:
1607ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    The current clip must contain the true clip. The true
1608ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    clip is the clip that would have normally been computed
1609ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    by calls to clipPath and clipRRect
1610ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // Objective:
1611ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    Keep the current clip as small as possible without
1612ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    breaking the contract, using only clip bounding rectangles
1613ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    (for performance).
1614ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org
1615ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // N.B.: This *never* calls back through a virtual on canvas, so subclasses
1616ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // don't have to worry about getting caught in a loop. Thus anywhere
1617ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // we call a virtual method, we explicitly prefix it with
1618ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // SkCanvas:: to be sure to call the base-class.
1619a5d3e77420621c912383c3b22e542d9413d68278skia.committer@gmail.com
1620ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    if (inverseFilled) {
1621ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        switch (op) {
1622ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kIntersect_Op:
1623ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kDifference_Op:
1624ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // These ops can only shrink the current clip. So leaving
16258f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                // the clip unchanged conservatively respects the contract.
16268f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1627ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kUnion_Op:
1628ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReplace_Op:
1629ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReverseDifference_Op:
16308f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            case SkRegion::kXOR_Op: {
1631ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // These ops can grow the current clip up to the extents of
1632ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // the input clip, which is inverse filled, so we just set
1633ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // the current clip to the device bounds.
1634ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    SkRect deviceBounds;
1635ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    SkIRect deviceIBounds;
1636ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    this->getDevice()->getGlobalBounds(&deviceIBounds);
16374469938e92d779dff05e745559e67907bbf21e78reed@google.com                    deviceBounds = SkRect::Make(deviceIBounds);
1638091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org
1639ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // set the clip in device space
1640091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org                    SkMatrix savedMatrix = this->getTotalMatrix();
1641ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    this->SkCanvas::setMatrix(SkMatrix::I());
1642370a89980b2d38a6d01903b484bf404d6c48b496skia.committer@gmail.com                    this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op,
16438f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                                               kHard_ClipEdgeStyle);
1644091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org                    this->setMatrix(savedMatrix);
16458f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                    break;
16468f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            }
1647ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            default:
1648ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                SkASSERT(0); // unhandled op?
1649ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        }
1650ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    } else {
1651ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        // Not inverse filled
1652ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        switch (op) {
1653ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kIntersect_Op:
1654ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kUnion_Op:
1655ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReplace_Op:
16568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
16578f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1658ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kDifference_Op:
1659ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Difference can only shrink the current clip.
1660ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Leaving clip unchanged conservatively fullfills the contract.
16618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1662ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReverseDifference_Op:
1663ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // To reverse, we swap in the bounds with a replace op.
1664ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // As with difference, leave it unchanged.
16658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
16668f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1667ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kXOR_Op:
1668ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Be conservative, based on (A XOR B) always included in (A union B),
1669ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // which is always included in (bounds(A) union bounds(B))
16708f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle);
16718f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1672ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            default:
1673ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                SkASSERT(0); // unhandled op?
1674ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        }
1675ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    }
1676ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org}
1677ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org
1678759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
16798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
16808f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16818f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
16828f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
16835c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16845c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1686c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16885c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
16895c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1690115d931d2fbd3a109a21b28c8a9c5099e6c49c54reed@google.com    fClipStack.clipDevRect(rgn.getBounds(), op);
16915c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16928f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    fMCRec->fRasterClip->op(rgn, op);
16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1695819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1696819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1697819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
16981f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1699ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
17005c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1701ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1702ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1703ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1704819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1705819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
17060017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip tmpClip(ir);
1707819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
170880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
17098182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
17108182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
17118182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
17128182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
17138182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
17148182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
17158182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
17168182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
17178182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
17188182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
17199cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
17209cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
17219cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
17228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                clip_path_helper(this, &tmpClip, path, element->getOp(), element->isAA());
17239cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
17249cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1725819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1726819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1727819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1728819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1729819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
173090c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
173180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
17328182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
17338182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
17348182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    static const SkRect kEmpty = { 0, 0, 0, 0 };
17358182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
17368182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
17378182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kPath_Type:
17388182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                visitor->clipPath(element->getPath(), element->getOp(), element->isAA());
17398182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
1740e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            case SkClipStack::Element::kRRect_Type:
1741e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                visitor->clipRRect(element->getRRect(), element->getOp(), element->isAA());
1742e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                break;
17438182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
17448182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                visitor->clipRect(element->getRect(), element->getOp(), element->isAA());
17458182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
17468182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
17478182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false);
17488182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
174990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com        }
175090c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
175190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
175290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
17535c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
17545c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1755754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
1756754de5f65b466f721d952a379194cc94de376f42reed@google.com    return fMCRec->fRasterClip->isEmpty();
1757754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1758754de5f65b466f721d952a379194cc94de376f42reed@google.com
17595c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
17605c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    return fMCRec->fRasterClip->isRect();
17615c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17625c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17633b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
1764116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
17651607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1766116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1767116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
17680017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    if (fMCRec->fRasterClip->isEmpty()) {
17698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17728d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com    if (fMCRec->fMatrix->hasPerspective()) {
1773a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
1774a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        fMCRec->fMatrix->mapRect(&dst, rect);
1775a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkIRect idst;
1776a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        dst.roundOut(&idst);
17770017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1778a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1779c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1780d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1781a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1782c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1783c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1784a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1785a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1786c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1787a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1788a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1789a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17933b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
17943b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17973b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1798bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
17998f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1803d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1804d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
1805d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    if (!fMCRec->fMatrix->invert(&inverse)) {
180672dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
180772dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
180872dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1809d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1810d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1811d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
18128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != bounds) {
1813bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
18143b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
18153b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1816fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
18178f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
18188f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1824bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
18250017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    const SkRasterClip& clip = *fMCRec->fRasterClip;
1826bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1827bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1828bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1829bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1830bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1831bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1832bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
1833bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (NULL != bounds) {
1834bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1835bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1836bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1837bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1838bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
18398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *fMCRec->fMatrix;
18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18435c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
1844bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.comSkCanvas::ClipType SkCanvas::getClipType() const {
18458f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (fMCRec->fRasterClip->isEmpty()) {
18468f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return kEmpty_ClipType;
18478f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
18488f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (fMCRec->fRasterClip->isRect()) {
18498f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return kRect_ClipType;
18508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
1851bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return kComplex_ClipType;
1852bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
18535c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org#endif
1854bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
18555c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org#ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP
18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const {
18570017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    return fMCRec->fRasterClip->forceGetBW();
18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18595c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org#endif
18605c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
18615c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
18625c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    return fMCRec->fRasterClip->forceGetBW();
18635c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
18645c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
18655c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgvoid SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const {
18665c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    path->reset();
18675c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
18685c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    const SkRegion& rgn = fMCRec->fRasterClip->forceGetBW();
18695c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    if (rgn.isEmpty()) {
18705c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        return;
18715c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    }
18725c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    (void)rgn.getBoundaryPath(path);
18735c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18759c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
18769c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
18779c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessRenderTarget() : NULL;
18789c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
18799c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
188015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgSkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
18811f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getTopDevice();
188215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
18838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1885644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1886644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1887644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
1888644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    if (NULL != device) {
1889644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
1890644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        if (NULL != renderTarget) {
1891644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1892644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1893644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1894644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1895644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1896644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1897644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1898644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1899e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1900ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1901ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
1902ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1903ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1904ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1905ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1906ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1907ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1908ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1909ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1910ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1911ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1912ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1913ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1914ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1915ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1916ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1917ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1918ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1919ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
19208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
19228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19242a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) {
19252a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    SkDrawIter  iter(this);
1926995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org    this->predrawNotify();
19272a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    while (iter.next()) {
19282a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com        iter.fDevice->clear(color);
19292a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    }
19302a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com}
19312a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com
193228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
193328361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    if (NULL != fSurfaceBase) {
193428361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
193528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
193628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
193728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
19388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) {
1939fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1940fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1941fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1942fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
194353783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
194453783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
194578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
19484e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
19498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19514e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
19558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
19568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
19588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
196053783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
196153783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
196278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
196378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1964a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1965a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1966a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1967a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1968a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1969a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1970a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
197178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
197278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
1973a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
1974a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1975fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1976a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
19778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
19788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
197978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
19804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
19824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19887ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
198953783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
199053783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
199178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
199278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
19938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
199478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(r, &storage);
199578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
19978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
200078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
201053783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
201153783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
201278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
201378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
20144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
201578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
201678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20174ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
20184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
20194ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2020306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
202178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
202246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
202346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
202446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
202546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
202646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
202746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
20284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
20304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
203153783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
203253783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
203378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
203478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
20354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
203678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
203778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
20394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
20404ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
20414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
20424ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
20434ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
20444ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2045f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2046f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
20474ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2048f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2049f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
20504ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2051f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
205278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2053f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2054f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2055f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2056f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2057f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2058f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
20594ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20604ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2061ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2062ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
206353783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
206453783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
2065ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
2066ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    const SkRect* bounds = NULL;
2067ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
2068ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
2069ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        if (this->quickReject(*bounds)) {
2070ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org            return;
2071ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        }
2072ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
207325c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2074ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
207525c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2076ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2077ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2078ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
207925c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2080ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2081ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
20824ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
20837ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
208453783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
208553783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
20869364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
20879364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
20889364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
20899364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
209078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
209178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
2092fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
209378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
209478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
209578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
20978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
20988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20990b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
21000b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
21010b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
2102fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        if (path.isInverseFillType()) {
2103fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
2104fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2105fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
2106fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
210878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
21128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint* paint) {
21198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
21208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21213d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
21229efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
21239efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
21249efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
21259efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
21269efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
21279efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
21289efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
21299efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
21303b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
21328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
21338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21344b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
21368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
21379bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
21388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21409987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
21417112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2142eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2143eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      DrawBitmapRectFlags flags) {
214450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
21458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
21468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
214774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
2148ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_LOCKCOUNT_BALANCE(bitmap);
2149ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
215078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
215178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
21523d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
21539efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
21549efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
21559efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
21563b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
21573d60812865bb034851da777a91413ab584929887reed@google.com            return;
21583d60812865bb034851da777a91413ab584929887reed@google.com        }
21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21603d60812865bb034851da777a91413ab584929887reed@google.com
216133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
216233535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
216333535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21657064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
216678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
21677064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
216833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2169eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
2170f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
21717064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
217233535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21757112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
2176eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    const SkRect& dst, const SkPaint* paint,
2177eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    DrawBitmapRectFlags flags) {
21789987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2179eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
21809987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21819987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
21838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPaint* paint) {
21848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
21859bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
21868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21889987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
21899987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkIRect& center, const SkRect& dst,
21909987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkPaint* paint) {
219150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
219250b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org        return;
219350b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    }
21943d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
219560abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        SkRect storage;
219660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        const SkRect* bounds = &dst;
219760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
219860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
219960abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
22003b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
22013d60812865bb034851da777a91413ab584929887reed@google.com            return;
22023d60812865bb034851da777a91413ab584929887reed@google.com        }
22033d60812865bb034851da777a91413ab584929887reed@google.com    }
22043d60812865bb034851da777a91413ab584929887reed@google.com
22059987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t w = bitmap.width();
22069987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t h = bitmap.height();
22079987ec3791336bad6af5cbe513564786b2df55aareed@google.com
22089987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkIRect c = center;
22099987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // pin center to the bounds of the bitmap
22109987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fLeft = SkMax32(0, center.fLeft);
22119987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fTop = SkMax32(0, center.fTop);
22129987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fRight = SkPin32(center.fRight, c.fLeft, w);
22139987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
22149987ec3791336bad6af5cbe513564786b2df55aareed@google.com
22157112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcX[4] = {
22167d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
22177112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
22187112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcY[4] = {
22197d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
22207112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
22219987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstX[4] = {
22229987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
22239987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
22249987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
22259987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstY[4] = {
22269987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
22279987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
22289987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
222974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
22309987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstX[1] > dstX[2]) {
22319987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
22329987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[2] = dstX[1];
22339987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
223474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
22359987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstY[1] > dstY[2]) {
22369987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
22379987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[2] = dstY[1];
22389987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
223974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
22409987ec3791336bad6af5cbe513564786b2df55aareed@google.com    for (int y = 0; y < 3; y++) {
22417112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com        SkRect s, d;
22427112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com
22439987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fTop = srcY[y];
22449987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fBottom = srcY[y+1];
22459987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fTop = dstY[y];
22469987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fBottom = dstY[y+1];
22479987ec3791336bad6af5cbe513564786b2df55aareed@google.com        for (int x = 0; x < 3; x++) {
22489987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fLeft = srcX[x];
22499987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fRight = srcX[x+1];
22509987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fLeft = dstX[x];
22519987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fRight = dstX[x+1];
2252eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org            this->internalDrawBitmapRect(bitmap, &s, d, paint,
225331acc11977815402e4ef2681350f8559285bec97robertphillips@google.com                                         kNone_DrawBitmapRectFlag);
22549987ec3791336bad6af5cbe513564786b2df55aareed@google.com        }
22559987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
22569987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
22579987ec3791336bad6af5cbe513564786b2df55aareed@google.com
22589987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
22599987ec3791336bad6af5cbe513564786b2df55aareed@google.com                              const SkRect& dst, const SkPaint* paint) {
22609987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
22619987ec3791336bad6af5cbe513564786b2df55aareed@google.com
22629987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // Need a device entry-point, so gpu can use a mesh
22639987ec3791336bad6af5cbe513564786b2df55aareed@google.com    this->internalDrawBitmapNine(bitmap, center, dst, paint);
22649987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
22659987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2266f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2267f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
22681f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
22691f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice::TextFlags flags;
2270f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        if (device->filterTextFlags(paint, &flags)) {
2271a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2272f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            newPaint->setFlags(flags.fFlags);
2273f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            newPaint->setHinting(flags.fHinting);
2274f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2275f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2276f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2277f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2278f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2279f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2280f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2281f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2282f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
22832c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
22842c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2285f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2286f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
228752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
228852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
228917b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
229052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
229152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
229252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
229317b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
229452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
229552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
229652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
229752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
229852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
229952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
230052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
230152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
230252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
230352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
230452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
230552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
230652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
230752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
230852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
230952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
231052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
231152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
231252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
231352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
231452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
231552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
231652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
231752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
231852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
231952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
232052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
232152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
232252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
232352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
232452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
232552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
232652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
232752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
232852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
232952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
233052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
233152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
233252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
233352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
233452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
233552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
233652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
233752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
233852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
233952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
234052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
234152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
234252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
234352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
234452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
234552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
234652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
234752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
234852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
234952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
235052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
235152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
235252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
235352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
235452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
235552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
235652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
235752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
235852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
23598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength,
23608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        SkScalar x, SkScalar y, const SkPaint& paint) {
236153783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
236253783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
236378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
23648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23664e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2367f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
236852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
236952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
23708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength,
23768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           const SkPoint pos[], const SkPaint& paint) {
237753783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
237853783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
237978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
23804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
23838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
2384f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
23858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength,
23918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkScalar xpos[], SkScalar constY,
23928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
239353783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
239453783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
239578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
23964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
23998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
2400f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24024b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
24078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPath& path, const SkMatrix* matrix,
24088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
240953783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
241053783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
241178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
24128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
24154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
24168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
24228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPoint verts[], const SkPoint texs[],
24238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkColor colors[], SkXfermode* xmode,
24248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const uint16_t indices[], int indexCount,
24258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
242653783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org    CHECK_SHADER_NOSETCONTEXT(paint);
242753783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org
242878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
24294b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
24324e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
24334e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
24348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
24408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
24418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
24428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
24438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2445845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
24468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
24478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2449845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
24500baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
24518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
24538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2455845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
24568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
24578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2459845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
24600baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
24618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
24638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
24668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
24674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
24698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
24708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
24738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
24748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
24754b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
24778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
24788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
24798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
24828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
24838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
24844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
24868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
24878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
24888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
24918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
24928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
24938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
24948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
24968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
24978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
25008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
25018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
25038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
25068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
25074ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
25088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
25118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
25128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
25138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
25148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
25153b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
25168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
25178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
25188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25194ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
25204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
25214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
25228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
25238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
25248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
25288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
25298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
25308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
25318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
25328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
25338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
25348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
25358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
25368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
25388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
25398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
25408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
25428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
25468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
25478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
25488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
25494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
25518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
25528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2554f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
2555145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.orgvoid SkCanvas::EXPERIMENTAL_optimize(SkPicture* picture) {
2556145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
2557145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    if (NULL != device) {
2558145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        device->EXPERIMENTAL_optimize(picture);
2559145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2560145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org}
2561f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com
2562c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.orgvoid SkCanvas::EXPERIMENTAL_purge(SkPicture* picture) {
2563c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
2564c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org    if (NULL != device) {
2565c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org        device->EXPERIMENTAL_purge(picture);
2566c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org    }
2567c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org}
2568c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org
25698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) {
2570145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
2571145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    if (NULL != device) {
2572145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2573145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2574c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org        if (device->EXPERIMENTAL_drawPicture(this, &picture)) {
2575145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2576145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2577145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2578145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
25798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    picture.draw(this);
25808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
25838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
25848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2586d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
25878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
25898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
25918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
25928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
25958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
25968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
25998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
26008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26021f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
26038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
26048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
26078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
26088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
26118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
26128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
26138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
26148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
26168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
26198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
26208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
262120a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
262220a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
262320a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
262420a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.comSkCanvas::ClipVisitor::~ClipVisitor() { }
26253107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26263107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
26273107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26283107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
26293107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
26303107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
26313107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
26323107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
26333107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
26343107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
26353107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
26363107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26373107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
26383107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
26393107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
264028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
26413107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
26423107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
26433107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
26443107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
26453107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26463107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
26473107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
26483107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26493107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgSkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
26503107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
26513107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        return NULL;
26523107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
26533107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26543107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkBitmap bitmap;
26553107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!bitmap.allocPixels(info)) {
26563107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        return NULL;
26573107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
26583107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26593107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    // should this functionality be moved into allocPixels()?
26603107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!bitmap.info().isOpaque()) {
26613107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        bitmap.eraseColor(0);
26623107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
26633107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
26643107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
266542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org
266642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
266742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
266842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
266942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2670eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
267142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
267242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
267342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
267442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2675eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
267642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    // should this functionality be moved into allocPixels()?
267742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.info().isOpaque()) {
267842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        bitmap.eraseColor(0);
267942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
268042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
268142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2682