18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h"
119c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org#include "SkDeviceImageFilterProxy.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
1574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
1645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
180017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
194ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
2352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
24a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
28644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
29644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
30644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
31da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
32da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
3315e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
57ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#ifdef SK_DEBUG
58ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#include "SkPixelRef.h"
59ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
60f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com/*
61f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  Some pixelref subclasses can support being "locked" from another thread
62f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  during the lock-scope of skia calling them. In these instances, this balance
63f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  check will fail, but may not be indicative of a problem, so we allow a build
64f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  flag to disable this check.
65f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *
66f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  Potentially another fix would be to have a (debug-only) virtual or flag on
67f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  pixelref, which could tell us at runtime if this check is valid. That would
68f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  eliminate the need for this heavy-handed build check.
69f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com */
70f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK
71f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.comclass AutoCheckLockCountBalance {
72f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.compublic:
73f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com    AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ }
74f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com};
75f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#else
76ea033606a06d05d2d42aa7118409fee798e53167reed@google.comclass AutoCheckLockCountBalance {
77ea033606a06d05d2d42aa7118409fee798e53167reed@google.compublic:
78ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) {
79ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0;
80ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
81ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    ~AutoCheckLockCountBalance() {
82ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        const int count = fPixelRef ? fPixelRef->getLockCount() : 0;
83ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        SkASSERT(count == fLockCount);
84ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
85ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
86ea033606a06d05d2d42aa7118409fee798e53167reed@google.comprivate:
87ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    const SkPixelRef* fPixelRef;
88ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    int               fLockCount;
89ea033606a06d05d2d42aa7118409fee798e53167reed@google.com};
90f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#endif
91ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
92ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#define CHECK_LOCKCOUNT_BALANCE(bitmap)  AutoCheckLockCountBalance clcb(bitmap)
93ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
94ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#else
95ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    #define CHECK_LOCKCOUNT_BALANCE(bitmap)
96ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#endif
97ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
982c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
992c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
10097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() {
10197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
102c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
10397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
10497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
10597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1081f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1171f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
118045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix*     fMatrix;
1206f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1221f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            : fNext(NULL) {
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != device) {
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
12640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1284b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
13088edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fDevice) {
13440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
13888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1394b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
140045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
1426f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
1436f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
1464b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
1554b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
159045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
1624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1683fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
1693fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
177f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
178f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1800e354aacd84d3bede3f97cbde35a54ba62a89533bsalomon@google.com    SkMatrix    fMatrixStorage;
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1926c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    int             fFlags;
1930017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkMatrix*       fMatrix;        // points to either fMatrixStorage or prev MCRec
1940017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip*   fRasterClip;    // points to either fRegionStorage or prev MCRec
1950017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkDrawFilter*   fFilter;        // the current filter (or null)
1964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*   fLayer;
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
20488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    DeviceCM*   fTopLayer;
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2066c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    MCRec(const MCRec* prev, int flags) : fFlags(flags) {
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != prev) {
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (flags & SkCanvas::kMatrix_SaveFlag) {
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrixStorage = *prev->fMatrix;
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrix = &fMatrixStorage;
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrix = prev->fMatrix;
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (flags & SkCanvas::kClip_SaveFlag) {
2160017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClipStorage = *prev->fRasterClip;
2170017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClip = &fRasterClipStorage;
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2190017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClip = prev->fRasterClip;
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter = prev->fFilter;
22382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkSafeRef(fFilter);
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTopLayer = prev->fTopLayer;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {   // no prev
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.reset();
2284b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix     = &fMatrixStorage;
2300017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            fRasterClip = &fRasterClipStorage;
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter     = NULL;
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTopLayer   = NULL;
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
24082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2444b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2460017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkMatrix        fMatrixStorage;
2470017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip    fRasterClipStorage;
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2528a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
2534370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
2548a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com        fClipStack = &canvas->fClipStack;
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
2598a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2614b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
270f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
271f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
274045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
275045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBitmap = &fDevice->accessBitmap(true);
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
279f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
283199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2884b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2891f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
2906f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
2916f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
2956f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
31078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
31178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
3124e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
3144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
3154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
3168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        fDoClearImageFilter = false;
3174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3198926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
3208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
3218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            tmp.setImageFilter(fOrigPaint.getImageFilter());
322e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
323e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                            true, SkCanvas::kFullLayer_SaveLayerStrategy);
3248926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // we'll clear the imageFilter for the actual draws in next(), so
3258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // it will only be applied during the restore().
3268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fDoClearImageFilter = true;
3278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
32979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
33079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
33179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
33279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
333129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
334129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
33579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = NULL;
336129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
337129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = !fFilter && !fDoClearImageFilter;
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
34074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
3428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (fDoClearImageFilter) {
3438926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
3448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
34774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3484e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
3494e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
3504e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
3514e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
35274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
353129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
354129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
355129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
356129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
357129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
358129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fPaint = &fOrigPaint;
359129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
360129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
361129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
362129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
363fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
36474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3662c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazyPaint;
3672c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
3682c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
3692c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
3702c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
3712c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
3728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    bool            fDoClearImageFilter;
3732c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
374129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
37579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
37679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
377129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
378129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
381129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
382632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
383129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
38479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
385632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
386129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkPaint* paint = fLazyPaint.set(fOrigPaint);
3878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
388129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fDoClearImageFilter) {
389129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
390129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
3918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
39279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
393129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
394129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
395129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
396129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
397971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
398971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
399971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
400971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
40179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (NULL == fLooperContext) {
402129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
403632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
404632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
405129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
406129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
4078926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
408129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
40979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
4104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
4114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4124e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
413632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
414632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
4154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
4164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
4174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
4194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
4204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
42697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
4278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    AutoDrawLooper  looper(this, paint, true);                      \
4288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
4298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
4308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
43178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
43297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
43378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    AutoDrawLooper  looper(this, paint, false, bounds);             \
4344e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
4364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
4374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4411f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::init(SkBaseDevice* device) {
442c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
443c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
4448f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
44545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
446447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org    fDeviceCMDirty = false;
447b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount = 0;
448210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    fCullCount = 0;
44974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    new (fMCRec) MCRec(NULL, 0);
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
458f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
459403f8d7a052269583175e945689824838e5e0ef4commit-bot@chromium.org    return this->setRootDevice(device);
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
462cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
463e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
464e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
4658d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
466ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
4678d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    this->init(NULL);
4688d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
4698d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
470e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.orgSkCanvas::SkCanvas(int width, int height)
471e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
472e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
473e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
474ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
475e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    SkBitmap bitmap;
476a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
477e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
478e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org}
479e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
4801f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkCanvas::SkCanvas(SkBaseDevice* device)
481e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
482e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->init(device);
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap)
489e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
490e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4931f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
499b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    SkASSERT(0 == fSaveLayerCount);
5007c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
504b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
51774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
51874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
51974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
52074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
52174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
52274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
52374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
52474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
52574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
528bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
5291f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
530bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
531bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
532bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
533bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
534bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
5354ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
5364ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
5374ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
5384ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
5394ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
5404ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
5414ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
5424ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
5434ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
5444ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
5454ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
5461f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
547210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
548210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
549210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
5501f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
552c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5571f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
5580b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
5590b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
5600b53d59a24f667350b4282f88470713902409030reed@google.com    }
5619266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
5629266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
5639266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
564403f8d7a052269583175e945689824838e5e0ef4commit-bot@chromium.orgSkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
5664c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    SkDeque::F2BIter iter(fMCStack);
5674c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    MCRec*           rec = (MCRec*)iter.next();
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
5691f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*    rootDevice = rec->fLayer->fDevice;
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice == device) {
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return device;
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (device) {
57640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        device->onAttachToCanvas(this);
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice) {
57940a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        rootDevice->onDetachFromCanvas();
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rootDevice = device;
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
5864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Now we update our initial region to have the bounds of the new device,
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and then intersect all of the clips in our stack with these bounds,
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to ensure that we can't draw outside of the device's bounds (and trash
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                     memory).
5914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this is only a partial-fix, since if the new device is larger than
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the previous one, we don't know how to "enlarge" the clips in our stack,
5944b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        so drawing may be artificially restricted. Without keeping a history of
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reconstruct the correct clips, so this approximation will have to do.
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The caller really needs to restore() back to the base if they want to
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        accurately take advantage of the new device bounds.
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
60142aea289cbf801997b653a906a37a7f7e948b645reed@google.com    SkIRect bounds;
60242aea289cbf801997b653a906a37a7f7e948b645reed@google.com    if (device) {
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bounds.set(0, 0, device->width(), device->height());
60442aea289cbf801997b653a906a37a7f7e948b645reed@google.com    } else {
60542aea289cbf801997b653a906a37a7f7e948b645reed@google.com        bounds.setEmpty();
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
60742aea289cbf801997b653a906a37a7f7e948b645reed@google.com    // now jam our 1st clip to be bounds, and intersect the rest with that
60842aea289cbf801997b653a906a37a7f7e948b645reed@google.com    rec->fRasterClip->setRect(bounds);
60942aea289cbf801997b653a906a37a7f7e948b645reed@google.com    while ((rec = (MCRec*)iter.next()) != NULL) {
61042aea289cbf801997b653a906a37a7f7e948b645reed@google.com        (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op);
61142aea289cbf801997b653a906a37a7f7e948b645reed@google.com    }
61242aea289cbf801997b653a906a37a7f7e948b645reed@google.com
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return device;
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
616a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
617a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
618a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
619a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
620a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
621a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
622a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == bitmap->pixelRef()) {
623a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        if (!bitmap->allocPixels()) {
624a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
625a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
626a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
627a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
628a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
629a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBitmap bm(*bitmap);
630a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bm.lockPixels();
631a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
632a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return true;
633a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
634a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
635a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
636a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->setPixelRef(NULL);
637a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
638a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
639a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
64051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
641c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
642a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
643a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
644a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
645a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
646ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
647ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
64874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
649a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!bitmap->allocN32Pixels(r.width(), r.height())) {
650a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
651a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
652a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
653a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
654a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
655daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
656c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
657a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
658a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
659c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
660a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) {
661a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    switch (origInfo.colorType()) {
662a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kUnknown_SkColorType:
663a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        case kIndex_8_SkColorType:
664a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
665a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        default:
666a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            break;
667a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
668a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == dstP || rowBytes < origInfo.minRowBytes()) {
669a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
670a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
671a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (0 == origInfo.width() || 0 == origInfo.height()) {
67251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        return false;
67351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
674a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
675a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
676a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
677a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
678a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
679a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
680a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
681a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
682a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!srcR.intersect(0, 0, size.width(), size.height())) {
683a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
684a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
685db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
686a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkImageInfo info = origInfo;
687a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // the intersect may have shrunk info's logical size
688a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    info.fWidth = srcR.width();
689a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    info.fHeight = srcR.height();
690db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
691a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
692a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (x > 0) {
693a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        x = 0;
694a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
695a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (y > 0) {
696a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        y = 0;
697a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
698a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // here x,y are either 0 or negative
699a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
700db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
701a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
702a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
70351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
70451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7054cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
7064cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
7074cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7084cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7094cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBitmap bm(bitmap);
7104cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    bm.lockPixels();
7114cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bm.getPixels()) {
7124cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
7134cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7144cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
7154cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
7164cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7174cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
7184cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
7194cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
7204cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
7214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
7224cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
7234cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
7244cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
7254cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7264cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
7274cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7284cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7294cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7304cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
7314cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
7324cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
7334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7344cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7354cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7364cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
7374cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
7384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7394cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7404cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7414cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkImageInfo info = origInfo;
7424cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
7434cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    info.fWidth = target.width();
7444cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    info.fHeight = target.height();
7454cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
7474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
7484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
7494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
7514cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
7524cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7534cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
7544cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
7554cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7564cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
7574ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
7584cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
75951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7604370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
7614370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
7624370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7634370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        const SkRasterClip& totalClip = *fMCRec->fRasterClip;
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
7714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
77346799cd9f0bded51a189d77731b25af159ab4609reed@google.com            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
77746799cd9f0bded51a189d77731b25af159ab4609reed@google.com                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) {
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int saveCount = this->getSaveCount(); // record this before the actual save
7884b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
7914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
7934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7946c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    if (SkCanvas::kClip_SaveFlag & flags) {
7956c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org        fClipStack.save();
7966c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    }
7975c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return saveCount;
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
801d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::save() {
802d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    this->willSave(kMatrixClip_SaveFlag);
803d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->internalSave(kMatrixClip_SaveFlag);
804d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
805d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) {
807e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    this->willSave(flags);
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // call shared impl
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->internalSave(flags);
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
813b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
815b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
816b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
817b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
820a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
821c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                               SkIRect* intersection, const SkImageFilter* imageFilter) {
822bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
823c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkRegion::Op op = SkRegion::kIntersect_Op;
824bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
825a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
826f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
827c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
828c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
829c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        imageFilter->filterBounds(clipBounds, *fMCRec->fMatrix, &clipBounds);
830c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        // Filters may grow the bounds beyond the device bounds.
831c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        op = SkRegion::kReplace_Op;
832c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
833bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != bounds) {
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
8364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->getTotalMatrix().mapRect(&r, *bounds);
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
841bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
8420017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fMCRec->fRasterClip->setEmpty();
843bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
844a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
85089f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
85189f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        fClipStack.clipDevRect(ir, op);
85289f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        // early exit if the clip is now empty
85389f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        if (!fMCRec->fRasterClip->op(ir, op)) {
85489f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org            return false;
85589f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org        }
856a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
857a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
858a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
859a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
860a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
861a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
862a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
863a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
864d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
865d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
866d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
867d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
868d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
869a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
870a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org                        SaveFlags flags) {
871e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
872e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    return this->internalSaveLayer(bounds, paint, flags, false, strategy);
8738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
8748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
8752b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.orgstatic SkBaseDevice* create_compatible_device(SkCanvas* canvas,
8762b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.org                                              const SkImageInfo& info) {
87776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* device = canvas->getDevice();
87815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    return device ? device->createCompatibleDevice(info) : NULL;
87976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
88076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
881e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.orgint SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
882e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org                                bool justForImageFilter, SaveLayerStrategy strategy) {
883b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
8842a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    flags |= kClipToLayer_SaveFlag;
885b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
886b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
887a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
888a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
889a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    int count = this->internalSave(flags);
890a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
891a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
892a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
893a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
894c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return count;
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
898e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
899e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
900e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
901e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org        return count;
902e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
903e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
904b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    // Kill the imagefilter if our device doesn't allow it
905b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    SkLazyPaint lazyP;
906b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    if (paint && paint->getImageFilter()) {
907b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
9088926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            if (justForImageFilter) {
9098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                // early exit if the layer was just for the imageFilter
9108926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                return count;
9118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
912b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            SkPaint* p = lazyP.set(*paint);
913b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            p->setImageFilter(NULL);
914b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            paint = p;
915b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
916b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
917b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com
91815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
91915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
92015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9221f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device;
92376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    if (paint && paint->getImageFilter()) {
9242b290cec9825da11d8e09074727cfaac5eca6453commit-bot@chromium.org        device = create_compatible_device(this, info);
92576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    } else {
92615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        device = this->createLayerDevice(info);
92776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    }
928e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    if (NULL == device) {
929e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        SkDebugf("Unable to create device for layer.");
930e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        return count;
931e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
932e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
9336f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
93440a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
941b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount += 1;
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
945d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
946d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
947d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
948d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() {
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // check for underflow
9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCStack.count() > 1) {
963e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org        this->willRestore();
9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->internalRestore();
9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
972c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9746c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    if (SkCanvas::kClip_SaveFlag & fMCRec->fFlags) {
9756c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org        fClipStack.restore();
9766c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    }
9776c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
97888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != layer) {
9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
9946f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
9958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
9968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                     layer->fPaint);
9978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
9997c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
1000b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            SkASSERT(fSaveLayerCount > 0);
1001b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            fSaveLayerCount -= 1;
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(layer);
100488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const {
10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCStack.count();
10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) {
10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // sanity check
10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count < 1) {
10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count = 1;
10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
101674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
1017b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com    int n = this->getSaveCount() - count;
1018b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com    for (int i = 0; i < n; ++i) {
10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->restore();
10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10237c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.combool SkCanvas::isDrawingToLayer() const {
1024b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    return fSaveLayerCount > 0;
10257c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com}
10267c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
102776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
102876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    return this->onNewSurface(info);
102976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
103076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
103176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
103276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
103376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    return dev ? dev->newSurface(info) : NULL;
103476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
103576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1036c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1037c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1038c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1039c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1040c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1041900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1042c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1043c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1044c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1045c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1046c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return this->onPeekPixels(info, rowBytes);
1047c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1048c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1049c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1050c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1051c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return dev ? dev->peekPixels(info, rowBytes) : NULL;
1052c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1053c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
10546b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
10556b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
10566b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    if (pixels && origin) {
10576b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
10586b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
10596b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    return pixels;
10609c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
10619c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
10629c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comvoid* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
10639c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
10649c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessPixels(info, rowBytes) : NULL;
10659c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
10669c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1067c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1068c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1069c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1070c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1071a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.allocPixels(fInfo)) {
1072c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1073c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1074c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1075c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1076c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1077c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1078c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1079c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1080c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1081c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1082c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1083c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1084c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
108500f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1086c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1087c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1088c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1089c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1090c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1091c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1092210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.orgvoid SkCanvas::onPushCull(const SkRect& cullRect) {
1093210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    // do nothing. Subclasses may do something
1094210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org}
1095210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org
1096210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.orgvoid SkCanvas::onPopCull() {
1097210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org    // do nothing. Subclasses may do something
1098210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org}
1099210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
1101520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef SK_DEBUG
1102520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org// Ensure that cull rects are monotonically nested in device space.
1103520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::validateCull(const SkIRect& devCull) {
1104520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (fCullStack.isEmpty()
1105520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        || devCull.isEmpty()
1106520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        || fCullStack.top().contains(devCull)) {
1107520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        return;
1108520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1109520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1110520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
1111520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
1112520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              fCullStack.top().x(), fCullStack.top().y(),
1113520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org              fCullStack.top().right(), fCullStack.top().bottom()));
1114520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1115520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef ASSERT_NESTED_CULLING
1116520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkDEBUGFAIL("Invalid cull.");
1117520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1118520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1119520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1120520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1121520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::pushCull(const SkRect& cullRect) {
1122520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    ++fCullCount;
1123520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->onPushCull(cullRect);
1124520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1125520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#ifdef SK_DEBUG
1126520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    // Map the cull rect into device space.
1127520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkRect mappedCull;
1128520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->getTotalMatrix().mapRect(&mappedCull, cullRect);
1129520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1130520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    // Take clipping into account.
1131520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkIRect devClip, devCull;
1132520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    mappedCull.roundOut(&devCull);
1133520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->getClipDeviceBounds(&devClip);
1134520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (!devCull.intersect(devClip)) {
1135520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        devCull.setEmpty();
1136520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1137520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1138520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    this->validateCull(devCull);
1139520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    fCullStack.push(devCull); // balanced in popCull
1140520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org#endif
1141520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1142520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1143520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.orgvoid SkCanvas::popCull() {
1144520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    SkASSERT(fCullStack.count() == fCullCount);
1145520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1146520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    if (fCullCount > 0) {
1147520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        --fCullCount;
1148520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        this->onPopCull();
1149520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1150520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org        SkDEBUGCODE(fCullStack.pop());
1151520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org    }
1152520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org}
1153520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org
1154520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11569bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
115850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11622c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
11642c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11669bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
11679bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
11689bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    CHECK_LOCKCOUNT_BALANCE(bitmap);
11699bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
117078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
117178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
117278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
117378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
117478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
117578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
117678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
117778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
117878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
11799bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
11809bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
11819bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
11829bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
11839bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
11849bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11871f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
11888926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                  const SkPaint* paint) {
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp.setDither(true);
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11944b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
11958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
11971f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
119876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
119976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
120076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
12029c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org            SkDeviceImageFilterProxy proxy(dstDev);
120376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
12046776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1205b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1206fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1207d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
12084cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
12091a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
12101a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            SkAutoUnref aur(NULL);
12111a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            if (!cache) {
12121a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org                cache = SkImageFilter::Cache::Create();
12131a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org                aur.reset(cache);
12141a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            }
1215f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            SkImageFilter::Context ctx(matrix, clipBounds, cache);
12164cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
12175efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
12185efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
12196776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
12206776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
122176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
122276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1223b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
122476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12264e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
12308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                          const SkPaint* paint) {
123150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
12338926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
123450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
123550b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    CHECK_LOCKCOUNT_BALANCE(bitmap);
1236fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12378926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
12388926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
12398926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
12408926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1241fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1243fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
12458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
12468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
12478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
12499c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org            SkDeviceImageFilterProxy proxy(iter.fDevice);
12508926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
12516776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1252fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1253d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
12544cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
12551a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
12561a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            SkAutoUnref aur(NULL);
12571a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            if (!cache) {
12581a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org                cache = SkImageFilter::Cache::Create();
12591a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org                aur.reset(cache);
12601a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org            }
1261f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            SkImageFilter::Context ctx(matrix, clipBounds, cache);
12624cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
12635efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
12645efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
12656776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
12665efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
12678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
12688926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
12698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
12708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
12718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
12728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
12738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
12748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
127692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1277d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1278d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1279d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
128292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1283d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1284d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1285d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
128892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1289d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1290d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1291d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
129492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1295d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1296d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1297d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
129844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
129944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
130092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1301d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1302d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1303d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1304d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1306c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
130792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org    fMCRec->fMatrix->preConcat(matrix);
130844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
130944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
131044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
131144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1314c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *fMCRec->fMatrix = matrix;
131644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
13214b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1328759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
13298f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
13308f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
13318f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
13328f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
13338f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1334da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1335da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
1336da17f758442f16747af39f8fbaed9c097048519creed@google.com        if (fMCRec->fRasterClip->isEmpty()) {
1337da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1338da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1339da17f758442f16747af39f8fbaed9c097048519creed@google.com
13403b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1341da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1342c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1343da17f758442f16747af39f8fbaed9c097048519creed@google.com
1344da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
1345da17f758442f16747af39f8fbaed9c097048519creed@google.com            return fMCRec->fRasterClip->setEmpty();
1346da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1347da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1348da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1349da17f758442f16747af39f8fbaed9c097048519creed@google.com
13505c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
13515c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1353c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13548f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
13558f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
13568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCRec->fMatrix->rectStaysRect()) {
1359123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
136098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
136198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
136298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMCRec->fMatrix->mapRect(&r, rect);
13668f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
13678f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1369123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
137098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
137198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
137298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
13768f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13808f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comstatic void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
13818f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                             const SkPath& devPath, SkRegion::Op op, bool doAA) {
1382759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    // base is used to limit the size (and therefore memory allocation) of the
1383759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    // region that results from scan converting devPath.
1384759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    SkRegion base;
1385759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com
1386819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    if (SkRegion::kIntersect_Op == op) {
1387759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // since we are intersect, we can do better (tighter) with currRgn's
1388759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // bounds, than just using the device. However, if currRgn is complex,
1389759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // our region blitter may hork, so we do that case in two steps.
13900017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        if (currClip->isRect()) {
1391b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // FIXME: we should also be able to do this when currClip->isBW(),
1392b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // but relaxing the test above triggers GM asserts in
1393b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // SkRgnBuilder::blitH(). We need to investigate what's going on.
13948f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->setPath(devPath, currClip->bwRgn(), doAA);
1395759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        } else {
13960017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            base.setRect(currClip->getBounds());
13970017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            SkRasterClip clip;
13980017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            clip.setPath(devPath, base, doAA);
13998f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->op(clip, op);
1400759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        }
1401819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    } else {
14021f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        const SkBaseDevice* device = canvas->getDevice();
1403ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        if (!device) {
14048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->setEmpty();
14058f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            return;
1406ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        }
1407ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1408a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        base.setRect(0, 0, device->width(), device->height());
1409819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1410819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        if (SkRegion::kReplace_Op == op) {
14118f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->setPath(devPath, base, doAA);
1412819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        } else {
14130017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            SkRasterClip clip;
14140017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            clip.setPath(devPath, base, doAA);
14158f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            currClip->op(clip, op);
1416819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1417819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1418819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1419819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1420759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
14218f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14224ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
14238f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
14248f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14258f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
14264ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
14278f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
142814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
14298f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
143014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
143114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) {
143214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
143314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
143414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
143514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
14368f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
14378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
14388f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
143914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
14408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
144114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
144214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
144314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
144414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
14458f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
14468f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
144714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
144814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
144914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
145014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
145114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
14528f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
14534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
14544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1455759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
14568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14578f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
14588f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
14598f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
14608f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
14628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
14658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1466da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1467da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1468da17f758442f16747af39f8fbaed9c097048519creed@google.com        if (fMCRec->fRasterClip->isEmpty()) {
1469da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1470da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1471fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
14723b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1473da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1474c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1475fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1476da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
1477da17f758442f16747af39f8fbaed9c097048519creed@google.com            return fMCRec->fRasterClip->setEmpty();
1478da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1479da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1480da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1481da17f758442f16747af39f8fbaed9c097048519creed@google.com
14825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14835c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1485c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
14878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
14888f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path.transform(*fMCRec->fMatrix, &devPath);
14928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1493fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1494fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1495fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1496fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1497fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1498fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1499fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1500fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1501fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1502fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
15035c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
15048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
15055c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
150645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
150745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.reset();
150845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
150945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack* clipStack = getClipStack();
151045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
151145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack::Element* element;
151245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        while ((element = iter.next())) {
151345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkClipStack::Element::Type type = element->getType();
151445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkPath operand;
15152a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org            if (type != SkClipStack::Element::kEmpty_Type) {
15162a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org                element->asPath(&operand);
15172a67e123a3e559774a16a58cbe5106bc0fb86740commit-bot@chromium.org            }
151845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkRegion::Op elementOp = element->getOp();
151945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            if (elementOp == SkRegion::kReplace_Op) {
152045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                devPath = operand;
152145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            } else {
152245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                Op(devPath, operand, (SkPathOp) elementOp, &devPath);
152345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            }
152496fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
152596fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // perhaps we need an API change to avoid this sort of mixed-signals about
152696fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // clipping.
15278f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            if (element->isAA()) {
15288f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                edgeStyle = kSoft_ClipEdgeStyle;
15298f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            }
153045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
153145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
153245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
153345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
15348f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle);
15358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1537759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
1538ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                                                   bool inverseFilled) {
1539ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // This is for updating the clip conservatively using only bounds
1540ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // information.
1541ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // Contract:
1542ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    The current clip must contain the true clip. The true
1543ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    clip is the clip that would have normally been computed
1544ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    by calls to clipPath and clipRRect
1545ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // Objective:
1546ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    Keep the current clip as small as possible without
1547ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    breaking the contract, using only clip bounding rectangles
1548ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    (for performance).
1549ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org
1550ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // N.B.: This *never* calls back through a virtual on canvas, so subclasses
1551ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // don't have to worry about getting caught in a loop. Thus anywhere
1552ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // we call a virtual method, we explicitly prefix it with
1553ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // SkCanvas:: to be sure to call the base-class.
1554a5d3e77420621c912383c3b22e542d9413d68278skia.committer@gmail.com
1555ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    if (inverseFilled) {
1556ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        switch (op) {
1557ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kIntersect_Op:
1558ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kDifference_Op:
1559ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // These ops can only shrink the current clip. So leaving
15608f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                // the clip unchanged conservatively respects the contract.
15618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1562ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kUnion_Op:
1563ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReplace_Op:
1564ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReverseDifference_Op:
15658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            case SkRegion::kXOR_Op: {
1566ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // These ops can grow the current clip up to the extents of
1567ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // the input clip, which is inverse filled, so we just set
1568ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // the current clip to the device bounds.
1569ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    SkRect deviceBounds;
1570ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    SkIRect deviceIBounds;
1571ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    this->getDevice()->getGlobalBounds(&deviceIBounds);
15724469938e92d779dff05e745559e67907bbf21e78reed@google.com                    deviceBounds = SkRect::Make(deviceIBounds);
1573091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org
1574ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // set the clip in device space
1575091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org                    SkMatrix savedMatrix = this->getTotalMatrix();
1576ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    this->SkCanvas::setMatrix(SkMatrix::I());
1577370a89980b2d38a6d01903b484bf404d6c48b496skia.committer@gmail.com                    this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op,
15788f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                                               kHard_ClipEdgeStyle);
1579091a594dbc4116ec2e54724432472bf37dae794acommit-bot@chromium.org                    this->setMatrix(savedMatrix);
15808f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                    break;
15818f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            }
1582ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            default:
1583ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                SkASSERT(0); // unhandled op?
1584ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        }
1585ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    } else {
1586ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        // Not inverse filled
1587ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        switch (op) {
1588ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kIntersect_Op:
1589ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kUnion_Op:
1590ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReplace_Op:
15918f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
15928f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1593ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kDifference_Op:
1594ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Difference can only shrink the current clip.
1595ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Leaving clip unchanged conservatively fullfills the contract.
15968f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1597ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReverseDifference_Op:
1598ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // To reverse, we swap in the bounds with a replace op.
1599ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // As with difference, leave it unchanged.
16008f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
16018f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1602ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kXOR_Op:
1603ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Be conservative, based on (A XOR B) always included in (A union B),
1604ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // which is always included in (bounds(A) union bounds(B))
16058f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle);
16068f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                break;
1607ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            default:
1608ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                SkASSERT(0); // unhandled op?
1609ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        }
1610ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    }
1611ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org}
1612ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org
1613759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
16148f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
16158f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16168f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
16178f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
16185c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16195c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1621c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
16228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16235c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
16245c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1625115d931d2fbd3a109a21b28c8a9c5099e6c49c54reed@google.com    fClipStack.clipDevRect(rgn.getBounds(), op);
16265c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16278f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    fMCRec->fRasterClip->op(rgn, op);
16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1630819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1631819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1632819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
16331f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1634ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
16355c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1636ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1637ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1638ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1639819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1640819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
16410017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip tmpClip(ir);
1642819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
164380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
16448182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
16458182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
16468182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
16478182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
16488182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
16498182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
16508182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
16518182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
16528182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
16538182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
16549cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
16559cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
16569cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
16578f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com                clip_path_helper(this, &tmpClip, path, element->getOp(), element->isAA());
16589cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
16599cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1660819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1661819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1662819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1663819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1664819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
166590c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
166680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
16678182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
16688182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
16698182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
1670c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
167190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
167290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
167390c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
16745c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
16755c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1676754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
1677754de5f65b466f721d952a379194cc94de376f42reed@google.com    return fMCRec->fRasterClip->isEmpty();
1678754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1679754de5f65b466f721d952a379194cc94de376f42reed@google.com
16805c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
16815c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    return fMCRec->fRasterClip->isRect();
16825c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16835c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16843b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
1685116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
16861607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1687116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1688116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
16890017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    if (fMCRec->fRasterClip->isEmpty()) {
16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16938d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com    if (fMCRec->fMatrix->hasPerspective()) {
1694a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
1695a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        fMCRec->fMatrix->mapRect(&dst, rect);
1696a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkIRect idst;
1697a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        dst.roundOut(&idst);
16980017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1699a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1700c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1701d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1702a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1703c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1704c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1705a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1706a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1707c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1708a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1709a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1710a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
17118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17143b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
17153b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
17168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17183b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1719bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
17208f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
17218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
17228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1724d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1725d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
1726d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    if (!fMCRec->fMatrix->invert(&inverse)) {
172772dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
172872dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
172972dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1730d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1731d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1732d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
17338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != bounds) {
1734bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
17353b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
17363b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1737fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
17388f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
17398f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
17408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
17418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1745bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
17460017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    const SkRasterClip& clip = *fMCRec->fRasterClip;
1747bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1748bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1749bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1750bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1751bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1752bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1753bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
1754bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (NULL != bounds) {
1755bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1756bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1757bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1758bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1759bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
17608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
17618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *fMCRec->fMatrix;
17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17645c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
1765bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.comSkCanvas::ClipType SkCanvas::getClipType() const {
17668f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (fMCRec->fRasterClip->isEmpty()) {
17678f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return kEmpty_ClipType;
17688f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
17698f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (fMCRec->fRasterClip->isRect()) {
17708f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return kRect_ClipType;
17718f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
1772bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return kComplex_ClipType;
1773bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
17745c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org#endif
1775bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
17765c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org#ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP
17778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const {
17780017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    return fMCRec->fRasterClip->forceGetBW();
17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17805c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org#endif
17815c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17825c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
17835c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    return fMCRec->fRasterClip->forceGetBW();
17845c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17855c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17865c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgvoid SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const {
17875c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    path->reset();
17885c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17895c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    const SkRegion& rgn = fMCRec->fRasterClip->forceGetBW();
17905c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    if (rgn.isEmpty()) {
17915c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        return;
17925c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    }
17935c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org    (void)rgn.getBoundaryPath(path);
17945c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17969c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
17979c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
17989c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessRenderTarget() : NULL;
17999c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
18009c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
180115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgSkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
18021f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getTopDevice();
180315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1806644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1807644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1808644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
1809644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    if (NULL != device) {
1810644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
1811644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        if (NULL != renderTarget) {
1812644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1813644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1814644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1815644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1816644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1817644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1818644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1819644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1820e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1821ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1822ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
1823ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1824ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1825ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1826ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1827ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1828ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1829ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1830ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1831ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1832ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1833ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1834ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1835ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1836ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1837ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1838ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1839ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1840ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
18428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
18438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18452a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) {
18462a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    SkDrawIter  iter(this);
1847995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org    this->predrawNotify();
18482a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    while (iter.next()) {
18492a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com        iter.fDevice->clear(color);
18502a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    }
18512a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com}
18522a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com
185328361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
185428361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    if (NULL != fSurfaceBase) {
185528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
185628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
185728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
185828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
18598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) {
1860fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1861fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1862fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1863fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
186478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
18658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
18688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
18768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
18778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
187978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
188078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1881a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1882a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1883a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1884a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1885a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1886a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1887a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
188878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
188978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
1890a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
1891a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1892fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1893a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
18948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
18958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
189678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
18974b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
18988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
19008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19014b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19057ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
190678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
190778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
19088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
190978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(r, &storage);
191078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
19128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
19138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
191578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
19168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
19184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
19198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19244ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
192578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
192678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
19274ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
192878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
192978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
19314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
19324ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1933306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
193478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
193546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
193646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
193746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
193846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
193946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
194046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
19414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
19424ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
19434ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
194478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
194578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
19464ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
194778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
194878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
19504ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
19514ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
19524ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
19534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
19544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
19554ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1956f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
1957f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
19584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
1959f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1960f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
19614ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1962f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
196378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1964f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1965f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
1966f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1967f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
1968f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1969f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
19704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
19714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1972ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1973ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
1974ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
1975ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    const SkRect* bounds = NULL;
1976ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
1977ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1978ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        if (this->quickReject(*bounds)) {
1979ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org            return;
1980ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        }
1981ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
198225c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1983ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
198425c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1985ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
1986ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1987ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
198825c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1989ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
1990ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
19914ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
19927ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
19939364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
19949364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
19959364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
19969364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
199778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
199878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1999fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
200078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
200178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
200278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20060b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
20070b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
20080b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
20096803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2010fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
2011fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2012fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
2013fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
20148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
201578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
20168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
20198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
20258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint* paint) {
20268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
20278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20283d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
20299efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
20309efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
20319efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
20329efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
20339efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
20349efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
20359efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
20369efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
20373b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
20388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
20398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
20408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20414b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
20438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
20449bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
20458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20479987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
20487112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2049eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2050eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      DrawBitmapRectFlags flags) {
205150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
20528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
20538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
205474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
2055ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_LOCKCOUNT_BALANCE(bitmap);
2056ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
205778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
205878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
20593d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
20609efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
20619efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
20629efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
20633b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
20643d60812865bb034851da777a91413ab584929887reed@google.com            return;
20653d60812865bb034851da777a91413ab584929887reed@google.com        }
20668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20673d60812865bb034851da777a91413ab584929887reed@google.com
206833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
206933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
207033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
20718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20727064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
207378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
20747064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
207533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2076eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
2077f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
20787064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
207933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
20808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20827112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
2083eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    const SkRect& dst, const SkPaint* paint,
2084eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    DrawBitmapRectFlags flags) {
20859987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2086eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
20879987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
20889987ec3791336bad6af5cbe513564786b2df55aareed@google.com
20898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
20908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPaint* paint) {
20918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
20929bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
20938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20959987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
20969987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkIRect& center, const SkRect& dst,
20979987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkPaint* paint) {
209850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
209950b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org        return;
210050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    }
21013d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
210260abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        SkRect storage;
210360abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        const SkRect* bounds = &dst;
210460abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
210560abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
210660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
21073b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
21083d60812865bb034851da777a91413ab584929887reed@google.com            return;
21093d60812865bb034851da777a91413ab584929887reed@google.com        }
21103d60812865bb034851da777a91413ab584929887reed@google.com    }
21113d60812865bb034851da777a91413ab584929887reed@google.com
21129987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t w = bitmap.width();
21139987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t h = bitmap.height();
21149987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21159987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkIRect c = center;
21169987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // pin center to the bounds of the bitmap
21179987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fLeft = SkMax32(0, center.fLeft);
21189987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fTop = SkMax32(0, center.fTop);
21199987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fRight = SkPin32(center.fRight, c.fLeft, w);
21209987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
21219987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21227112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcX[4] = {
21237d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
21247112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
21257112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcY[4] = {
21267d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
21277112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
21289987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstX[4] = {
21299987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
21309987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
21319987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
21329987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstY[4] = {
21339987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
21349987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
21359987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
213674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21379987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstX[1] > dstX[2]) {
21389987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
21399987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[2] = dstX[1];
21409987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
214174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21429987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstY[1] > dstY[2]) {
21439987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
21449987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[2] = dstY[1];
21459987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
214674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21479987ec3791336bad6af5cbe513564786b2df55aareed@google.com    for (int y = 0; y < 3; y++) {
21487112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com        SkRect s, d;
21497112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com
21509987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fTop = srcY[y];
21519987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fBottom = srcY[y+1];
21529987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fTop = dstY[y];
21539987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fBottom = dstY[y+1];
21549987ec3791336bad6af5cbe513564786b2df55aareed@google.com        for (int x = 0; x < 3; x++) {
21559987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fLeft = srcX[x];
21569987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fRight = srcX[x+1];
21579987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fLeft = dstX[x];
21589987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fRight = dstX[x+1];
2159eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org            this->internalDrawBitmapRect(bitmap, &s, d, paint,
216031acc11977815402e4ef2681350f8559285bec97robertphillips@google.com                                         kNone_DrawBitmapRectFlag);
21619987ec3791336bad6af5cbe513564786b2df55aareed@google.com        }
21629987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
21639987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21649987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21659987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
21669987ec3791336bad6af5cbe513564786b2df55aareed@google.com                              const SkRect& dst, const SkPaint* paint) {
21679987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
21689987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21699987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // Need a device entry-point, so gpu can use a mesh
21709987ec3791336bad6af5cbe513564786b2df55aareed@google.com    this->internalDrawBitmapNine(bitmap, center, dst, paint);
21719987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21729987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2173f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2174f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
21751f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
21761f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice::TextFlags flags;
2177f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        if (device->filterTextFlags(paint, &flags)) {
2178a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2179f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            newPaint->setFlags(flags.fFlags);
2180f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            newPaint->setHinting(flags.fHinting);
2181f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2182f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2183f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2184f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2185f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2186f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2187f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2188f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2189f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
21902c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
21912c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2192f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2193f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
219452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
219552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
219617b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
219752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
219852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
219952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
220017b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
220152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
220252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
220352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
220452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
220552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
220652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
220752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
220852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
220952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
221052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
221152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
221252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
221352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
221452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
221552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
221652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
221752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
221852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
221952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
222052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
222152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
222252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
222352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
222452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
222552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
222652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
222752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
222852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
222952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
223052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
223152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
223252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
223352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
223452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
223552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
223652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
223752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
223852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
223952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
224152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
224252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
224352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
224452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
224552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
224752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
224852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
225052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
225152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
225252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
225352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
225452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
225552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
225652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
225752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
225852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
225952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
226052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
226152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
226252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
226352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
226452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
226552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2266e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2267e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
226878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2272f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
227352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
227452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
22788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2280e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2281e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
228278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
228387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
22848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
22868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
2287f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
22888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2289b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
22904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
22918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2293e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2294e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
229578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
229687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
22978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
22998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
2300f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
23018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2302b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
23034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2306e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2307e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
230878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
230987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
23124e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
23138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2314b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2315945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
23164325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
23174325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
2318e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2319e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2320e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
2321e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2322e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2323e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2324e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
2325e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2326e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2327e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2328e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
2329e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2330e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2331e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2332e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
2333e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2334e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2335e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
23368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
23378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPoint verts[], const SkPoint texs[],
23388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkColor colors[], SkXfermode* xmode,
23398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const uint16_t indices[], int indexCount,
23408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
234178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
23424b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
23454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
23464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
23478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23484b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23494e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
23538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
23548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
23558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
23568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2358845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
23598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
23608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2362845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
23630baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
23648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
23668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2368845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
23698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
23708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2372845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
23730baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
23748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
23768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
23798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
23804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
23828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
23838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
23868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
23878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
23884b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
23908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
23918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
23928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
23958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
23968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
23974b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
23988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
23998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
24008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
24018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
24048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
24058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
24068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
24078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
24098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
24108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
24138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
24148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
24158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
24168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
24198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
24204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
24218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
24248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
24258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
24268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
24278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
24283b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
24298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
24308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
24318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
24324ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
24334ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
24344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
24358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
24368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
24378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
24418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
24428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
24438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
24448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
24458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
24468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
24478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
24488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
24498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
24508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
24518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
24528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
24538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
24548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
24558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
24598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
24608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
24618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
24624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
24648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
24658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2467f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
24689b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkCanvas::EXPERIMENTAL_optimize(const SkPicture* picture) {
2469145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
2470145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    if (NULL != device) {
2471145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        device->EXPERIMENTAL_optimize(picture);
2472145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2473145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org}
2474f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com
24759b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkCanvas::EXPERIMENTAL_purge(const SkPicture* picture) {
2476c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
2477c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org    if (NULL != device) {
2478c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org        device->EXPERIMENTAL_purge(picture);
2479c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org    }
2480c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org}
2481c873329ae9ff00b0c45f7294172ad2e9b1ec44c8commit-bot@chromium.org
24829b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkCanvas::drawPicture(const SkPicture* picture) {
24839b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    if (NULL != picture) {
24849b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips        this->onDrawPicture(picture);
24859b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    }
24869b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips}
24879b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
24889b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillipsvoid SkCanvas::onDrawPicture(const SkPicture* picture) {
24899b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    SkASSERT(NULL != picture);
24909b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2491145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
2492145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    if (NULL != device) {
2493145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2494145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
24959b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips        if (device->EXPERIMENTAL_drawPicture(this, picture)) {
2496145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2497145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2498145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2499145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
25009b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    picture->draw(this);
25018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
25048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
25058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2507d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
25088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
25108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
25128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
25138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
25168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
25178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
25208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
25218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25231f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
25248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
25258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
25288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
25298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
25328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
25338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
25348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
25358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
25378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
25408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
25418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
254220a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
254320a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
254420a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2545c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
25463107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25473107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
25483107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25493107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
25503107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
25513107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
25523107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
25533107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
25543107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
25553107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
25563107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25573107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25583107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
25593107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
25603107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
256128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
25623107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
25633107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
25643107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
25653107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25663107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25673107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
25683107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
25693107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25703107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgSkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
25713107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
25723107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        return NULL;
25733107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25743107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25753107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkBitmap bitmap;
25763107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!bitmap.allocPixels(info)) {
25773107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        return NULL;
25783107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25793107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
25803107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    // should this functionality be moved into allocPixels()?
25813107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    if (!bitmap.info().isOpaque()) {
25823107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        bitmap.eraseColor(0);
25833107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
25843107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
25853107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
258642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org
258742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
258842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
258942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
259042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2591eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
259242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
259342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
259442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
259542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
259642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
259742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2598