SkCanvas.cpp revision c3bd8af6d5722e854feca70c40d92f4954c5b67b
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBounder.h"
139c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org#include "SkDeviceImageFilterProxy.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
1774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
1845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
200017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
2452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
25a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
29644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
30644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
31644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
32da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
33da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
3415e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#ifdef SK_DEBUG
59ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#include "SkPixelRef.h"
60ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
61f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com/*
62f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  Some pixelref subclasses can support being "locked" from another thread
63f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  during the lock-scope of skia calling them. In these instances, this balance
64f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  check will fail, but may not be indicative of a problem, so we allow a build
65f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  flag to disable this check.
66f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *
67f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  Potentially another fix would be to have a (debug-only) virtual or flag on
68f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  pixelref, which could tell us at runtime if this check is valid. That would
69f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com *  eliminate the need for this heavy-handed build check.
70f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com */
71f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK
72f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.comclass AutoCheckLockCountBalance {
73f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.compublic:
74f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com    AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ }
75f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com};
76f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#else
77ea033606a06d05d2d42aa7118409fee798e53167reed@google.comclass AutoCheckLockCountBalance {
78ea033606a06d05d2d42aa7118409fee798e53167reed@google.compublic:
79ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) {
80ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0;
81ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
82ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    ~AutoCheckLockCountBalance() {
83ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        const int count = fPixelRef ? fPixelRef->getLockCount() : 0;
84ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        SkASSERT(count == fLockCount);
85ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
86ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
87ea033606a06d05d2d42aa7118409fee798e53167reed@google.comprivate:
88ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    const SkPixelRef* fPixelRef;
89ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    int               fLockCount;
90ea033606a06d05d2d42aa7118409fee798e53167reed@google.com};
91f53d0a998b59f922c7e04c94310a83df76bbc400reed@google.com#endif
92ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
93ea033606a06d05d2d42aa7118409fee798e53167reed@google.comclass AutoCheckNoSetContext {
94ea033606a06d05d2d42aa7118409fee798e53167reed@google.compublic:
95ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) {
96ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        this->assertNoSetContext(fPaint);
97ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
98ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    ~AutoCheckNoSetContext() {
99ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        this->assertNoSetContext(fPaint);
100ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
101ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
102ea033606a06d05d2d42aa7118409fee798e53167reed@google.comprivate:
103ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    const SkPaint& fPaint;
104ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
105ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    void assertNoSetContext(const SkPaint& paint) {
106ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        SkShader* s = paint.getShader();
107ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        if (s) {
108ea033606a06d05d2d42aa7118409fee798e53167reed@google.com            SkASSERT(!s->setContextHasBeenCalled());
109ea033606a06d05d2d42aa7118409fee798e53167reed@google.com        }
110ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    }
111ea033606a06d05d2d42aa7118409fee798e53167reed@google.com};
112ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
113ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#define CHECK_LOCKCOUNT_BALANCE(bitmap)  AutoCheckLockCountBalance clcb(bitmap)
114ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext     cshsc(paint)
115ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
116ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#else
117ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    #define CHECK_LOCKCOUNT_BALANCE(bitmap)
118ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    #define CHECK_SHADER_NOSETCONTEXT(paint)
119ea033606a06d05d2d42aa7118409fee798e53167reed@google.com#endif
120ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
1212c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
1222c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
12397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() {
12497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
125c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
12697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
12797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
12897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1311f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1401f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix*     fMatrix;
1436f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1451f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            : fNext(NULL) {
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != device) {
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
14940a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1514b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
15388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15588edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fDevice) {
15740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
16088edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
16188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
163045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
1656f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
1666f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
1694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
1784b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
1854b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1904b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1913fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
1923fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
200f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
201f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2030e354aacd84d3bede3f97cbde35a54ba62a89533bsalomon@google.com    SkMatrix    fMatrixStorage;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec*          fNext;
2166c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    int             fFlags;
2170017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkMatrix*       fMatrix;        // points to either fMatrixStorage or prev MCRec
2180017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip*   fRasterClip;    // points to either fRegionStorage or prev MCRec
2190017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkDrawFilter*   fFilter;        // the current filter (or null)
2204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*   fLayer;
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
22888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    DeviceCM*   fTopLayer;
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2306c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    MCRec(const MCRec* prev, int flags) : fFlags(flags) {
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != prev) {
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (flags & SkCanvas::kMatrix_SaveFlag) {
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrixStorage = *prev->fMatrix;
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrix = &fMatrixStorage;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fMatrix = prev->fMatrix;
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2384b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (flags & SkCanvas::kClip_SaveFlag) {
2400017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClipStorage = *prev->fRasterClip;
2410017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClip = &fRasterClipStorage;
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2430017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fRasterClip = prev->fRasterClip;
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter = prev->fFilter;
24782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkSafeRef(fFilter);
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTopLayer = prev->fTopLayer;
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {   // no prev
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.reset();
2524b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix     = &fMatrixStorage;
2540017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            fRasterClip = &fRasterClipStorage;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fFilter     = NULL;
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTopLayer   = NULL;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
26482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2700017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkMatrix        fMatrixStorage;
2710017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip    fRasterClipStorage;
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2768a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
2774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
2788a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com        fClipStack = &canvas->fClipStack;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBounder = canvas->getBounder();
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
2848a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
295f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
296f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
299045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
300045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBitmap = &fDevice->accessBitmap(true);
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
304f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fBounder) {
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fBounder->setClip(fClip);
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
311199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3171f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
3186f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3196f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3236f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3378926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
33878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
33978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
3404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
3414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fLooper = paint.getLooper();
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
3434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
3444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
3458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        fDoClearImageFilter = false;
3464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
3498926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
3508926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            tmp.setImageFilter(fOrigPaint.getImageFilter());
35178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp,
3528926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                    SkCanvas::kARGB_ClipLayer_SaveFlag, true);
3538926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // we'll clear the imageFilter for the actual draws in next(), so
3548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // it will only be applied during the restore().
3558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fDoClearImageFilter = true;
3568926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
3584e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        if (fLooper) {
3594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com            fLooper->init(canvas);
360129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
361129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
362129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
363129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = !fFilter && !fDoClearImageFilter;
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
36674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
3688926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (fDoClearImageFilter) {
3698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
3708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
37374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
3754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
3764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
3774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
37874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
379129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
380129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
381129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
382129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
383129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
384129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fPaint = &fOrigPaint;
385129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
386129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
387129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
388129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
389fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
39074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3922c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazyPaint;
3932c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
3942c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
3952c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawLooper*   fLooper;
3962c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
3972c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
3982c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
3998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    bool            fDoClearImageFilter;
4002c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
401129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
402129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
403129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
406129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
407632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
408129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
409129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(fLooper || fFilter || fDoClearImageFilter);
410632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
411129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkPaint* paint = fLazyPaint.set(fOrigPaint);
4128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
413129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fDoClearImageFilter) {
414129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
415129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
4168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
417129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fLooper && !fLooper->next(fCanvas, paint)) {
418129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
419129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
420129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
421129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
422971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
423971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
424971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
425971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
426129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (NULL == fLooper) {
427129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
428632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
429632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
430129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
431129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
4328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
433129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
434129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (!fLooper && !fFilter) {
4354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
4364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
438632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
439632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
4404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
4414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
4424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
4444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
4454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Stack helper for managing a SkBounder. In the destructor, if we were
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    given a bounder, we call its commit() method, signifying that we are
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    done accumulating bounds for that draw.
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBounderCommit {
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkAutoBounderCommit() {
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL != fBounder) {
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBounder->commit();
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBounder*  fBounder;
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
461e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoBounderCommit(...) SK_REQUIRE_LOCAL_VAR(SkAutoBounderCommit)
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
46897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
4698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    AutoDrawLooper  looper(this, paint, true);                      \
4708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
4718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkAutoBounderCommit ac(fBounder);                           \
4728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
4738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
47478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
47597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
47678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    AutoDrawLooper  looper(this, paint, false, bounds);             \
4774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoBounderCommit ac(fBounder);                           \
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
4804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
4814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4851f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::init(SkBaseDevice* device) {
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBounder = NULL;
487c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
488c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
4898f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
49045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
491447bcfa8898ce10e7b6493ba9e3e23e08bd13f01agl@chromium.org    fDeviceCMDirty = false;
492b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount = 0;
49374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    new (fMCRec) MCRec(NULL, 0);
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
49840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fNext = NULL;
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
503f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->setDevice(device);
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
507cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
508e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
509e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
5108d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
511ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
5128d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    this->init(NULL);
5138d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
5148d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
515e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.orgSkCanvas::SkCanvas(int width, int height)
516e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
517e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
518e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
519ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
520e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    SkBitmap bitmap;
521e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    bitmap.setConfig(SkBitmap::kNo_Config, width, height);
522e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
523e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org}
524e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
5251f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkCanvas::SkCanvas(SkBaseDevice* device)
526e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
527e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->init(device);
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::SkCanvas(const SkBitmap& bitmap)
534e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
535e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inc_canvas();
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5381f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
544b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    SkASSERT(0 == fSaveLayerCount);
5457c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5488d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    SkSafeUnref(fBounder);
54974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
550b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBounder* SkCanvas::setBounder(SkBounder* bounder) {
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fBounder, bounder);
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return bounder;
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
56974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
57074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
57174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
57274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
57374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
57474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
57574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
57674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
579bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
5801f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
581bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
582bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
583bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
584bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
585bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
586210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.comSkISize SkCanvas::getDeviceSize() const {
5871f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
588210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
589210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
590210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
5911f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
593c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5981f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
5990b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
6000b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
6010b53d59a24f667350b4282f88470713902409030reed@google.com    }
6029266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
6039266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
6049266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
6051f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::setDevice(SkBaseDevice* device) {
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
6074c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    SkDeque::F2BIter iter(fMCStack);
6084c09d5cd4b9e6f0be1352f62288efdedc1bc3de3reed@google.com    MCRec*           rec = (MCRec*)iter.next();
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
6101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*    rootDevice = rec->fLayer->fDevice;
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice == device) {
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return device;
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6154b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (device) {
61740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        device->onAttachToCanvas(this);
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rootDevice) {
62040a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com        rootDevice->onDetachFromCanvas();
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rootDevice = device;
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
6274b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Now we update our initial region to have the bounds of the new device,
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        and then intersect all of the clips in our stack with these bounds,
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        to ensure that we can't draw outside of the device's bounds (and trash
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                                     memory).
6324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this is only a partial-fix, since if the new device is larger than
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the previous one, we don't know how to "enlarge" the clips in our stack,
6354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        so drawing may be artificially restricted. Without keeping a history of
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reconstruct the correct clips, so this approximation will have to do.
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        The caller really needs to restore() back to the base if they want to
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        accurately take advantage of the new device bounds.
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
64242aea289cbf801997b653a906a37a7f7e948b645reed@google.com    SkIRect bounds;
64342aea289cbf801997b653a906a37a7f7e948b645reed@google.com    if (device) {
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bounds.set(0, 0, device->width(), device->height());
64542aea289cbf801997b653a906a37a7f7e948b645reed@google.com    } else {
64642aea289cbf801997b653a906a37a7f7e948b645reed@google.com        bounds.setEmpty();
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
64842aea289cbf801997b653a906a37a7f7e948b645reed@google.com    // now jam our 1st clip to be bounds, and intersect the rest with that
64942aea289cbf801997b653a906a37a7f7e948b645reed@google.com    rec->fRasterClip->setRect(bounds);
65042aea289cbf801997b653a906a37a7f7e948b645reed@google.com    while ((rec = (MCRec*)iter.next()) != NULL) {
65142aea289cbf801997b653a906a37a7f7e948b645reed@google.com        (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op);
65242aea289cbf801997b653a906a37a7f7e948b645reed@google.com    }
65342aea289cbf801997b653a906a37a7f7e948b645reed@google.com
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return device;
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6576850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.combool SkCanvas::readPixels(SkBitmap* bitmap,
6586850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                          int x, int y,
6596850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com                          Config8888 config8888) {
6601f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
66151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    if (!device) {
66251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        return false;
66351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
6646850eab42ba4c2a7033a99824b02a2846ce0ef2absalomon@google.com    return device->readPixels(bitmap, x, y, config8888);
66551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
66651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
667c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
6681f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
669ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
670ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
671ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
67274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
673daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com    SkIRect bounds;
674c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    bounds.set(0, 0, device->width(), device->height());
675daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com    if (!bounds.intersect(srcRect)) {
676daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
677c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
678c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
679c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    SkBitmap tmp;
680c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(),
681c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com                                               bounds.height());
682c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) {
683c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        bitmap->swap(tmp);
684c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com        return true;
685c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    } else {
68651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com        return false;
68751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
68851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
68951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
690d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.comvoid SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y,
691d58a1cd00b969a7755c375f55cf80f4d49d3047bbsalomon@google.com                           Config8888 config8888) {
6921f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
69351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    if (device) {
694405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com        if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()),
695405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com                                SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) {
696405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com            device->accessBitmap(true);
697405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com            device->writePixels(bitmap, x, y, config8888);
698405d0f43d8fa03874aee23669e5fdb38f21cc3e7bsalomon@google.com        }
69951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com    }
70051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
70151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7024370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
7034370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
7044370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
7054370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
711045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        const SkRasterClip& totalClip = *fMCRec->fRasterClip;
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
7134b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
71546799cd9f0bded51a189d77731b25af159ab4609reed@google.com            layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
717045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
71946799cd9f0bded51a189d77731b25af159ab4609reed@google.com                layer->updateMC(totalMatrix, clip, fClipStack, &clip);
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::internalSave(SaveFlags flags) {
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int saveCount = this->getSaveCount(); // record this before the actual save
7304b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    new (newTop) MCRec(fMCRec, flags);    // balanced in restore()
7334b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    newTop->fNext = fMCRec;
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
7364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
7376c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    if (SkCanvas::kClip_SaveFlag & flags) {
7386c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org        fClipStack.save();
7396c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    }
7405c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return saveCount;
7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::save(SaveFlags flags) {
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // call shared impl
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->internalSave(flags);
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C32MASK (1 << SkBitmap::kARGB_8888_Config)
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C16MASK (1 << SkBitmap::kRGB_565_Config)
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define C8MASK  (1 << SkBitmap::kA8_Config)
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkBitmap::Config resolve_config(SkCanvas* canvas,
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const SkIRect& bounds,
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       SkCanvas::SaveFlags flags,
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       bool* isOpaque) {
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // loop through and union all the configs we may draw into
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t configMask = 0;
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
7641f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* device = canvas->getLayerDevice(i);
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (device->intersects(bounds))
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            configMask |= 1 << device->config();
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if the caller wants alpha or fullcolor, we can't return 565
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkCanvas::kHasAlphaLayer_SaveFlag))
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        configMask &= ~C16MASK;
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (configMask) {
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case C8MASK:    // if we only have A8, return that
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkBitmap::kA8_Config;
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case C16MASK:   // if we only have 565, return that
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkBitmap::kRGB_565_Config;
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    default:
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkBitmap::kARGB_8888_Config; // default answer
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkBitmap::kARGB_8888_Config; // default answer
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
793a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
794c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                               SkIRect* intersection, const SkImageFilter* imageFilter) {
795bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
796c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkRegion::Op op = SkRegion::kIntersect_Op;
797bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
798a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
799f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
800c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
801c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
802c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        imageFilter->filterBounds(clipBounds, *fMCRec->fMatrix, &clipBounds);
803c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        // Filters may grow the bounds beyond the device bounds.
804c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        op = SkRegion::kReplace_Op;
805c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
806bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != bounds) {
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
8094b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->getTotalMatrix().mapRect(&r, *bounds);
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
814bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
8150017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com                fMCRec->fRasterClip->setEmpty();
816bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
817a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
823c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    fClipStack.clipDevRect(ir, op);
824a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // early exit if the clip is now empty
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (bounds_affects_clip(flags) &&
827c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        !fMCRec->fRasterClip->op(ir, op)) {
828a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
829a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
830a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
831a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
832a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
833a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
834a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
835a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
836a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
837a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
838a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org                        SaveFlags flags) {
8398926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    return this->internalSaveLayer(bounds, paint, flags, false);
8408926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
8418926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
84276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comstatic SkBaseDevice* createCompatibleDevice(SkCanvas* canvas,
84376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com                                            SkBitmap::Config config,
84476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com                                            int width, int height,
84576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com                                            bool isOpaque) {
84676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* device = canvas->getDevice();
84776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    if (device) {
84876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com        return device->createCompatibleDevice(config, width, height, isOpaque);
84976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    } else {
85076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com        return NULL;
85176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    }
85276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
85376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
8548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comint SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
8558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                SaveFlags flags, bool justForImageFilter) {
856a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
857a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
858a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    int count = this->internalSave(flags);
859a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
860a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
861a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
862a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
863c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return count;
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
867b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    // Kill the imagefilter if our device doesn't allow it
868b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    SkLazyPaint lazyP;
869b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    if (paint && paint->getImageFilter()) {
870b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
8718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            if (justForImageFilter) {
8728926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                // early exit if the layer was just for the imageFilter
8738926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                return count;
8748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
875b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            SkPaint* p = lazyP.set(*paint);
876b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            p->setImageFilter(NULL);
877b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            paint = p;
878b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
879b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
880b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool isOpaque;
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8841f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device;
88576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    if (paint && paint->getImageFilter()) {
88676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com        device = createCompatibleDevice(this, config, ir.width(), ir.height(),
88776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com                                        isOpaque);
88876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    } else {
88976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        device = this->createLayerDevice(config, ir.width(), ir.height(),
89076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com                                         isOpaque);
89176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    }
892e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    if (NULL == device) {
893e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        SkDebugf("Unable to create device for layer.");
894e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com        return count;
895e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
896e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
8976f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
89840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
905b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    fSaveLayerCount += 1;
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restore() {
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // check for underflow
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCStack.count() > 1) {
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->internalRestore();
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
931c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9336c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    if (SkCanvas::kClip_SaveFlag & fMCRec->fFlags) {
9346c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org        fClipStack.restore();
9356c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org    }
9366c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
93788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != layer) {
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
9536f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
9548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
9558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                     layer->fPaint);
9568926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
9587c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
959b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            SkASSERT(fSaveLayerCount > 0);
960b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org            fSaveLayerCount -= 1;
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(layer);
96388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::getSaveCount() const {
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCStack.count();
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::restoreToCount(int count) {
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // sanity check
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count < 1) {
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count = 1;
9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
97574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
976b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com    int n = this->getSaveCount() - count;
977b9d1c6a3c43a2cbcbd612f4ec4aaf604a1fa6444reed@google.com    for (int i = 0; i < n; ++i) {
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->restore();
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9827c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.combool SkCanvas::isDrawingToLayer() const {
983b0a7ace7cb2a7559bbc254a7c93698bc71bbd245junov@chromium.org    return fSaveLayerCount > 0;
9847c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com}
9857c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
98676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
98776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    return this->onNewSurface(info);
98876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
98976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
99076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.comSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
99176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
99276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    return dev ? dev->newSurface(info) : NULL;
99376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
99476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
995c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
996c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
997c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
998c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
999c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1000c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        // TODO: need a real unknown for alphatype it seems.
1001c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        SkAlphaType unknownAlphaType = kIgnore_SkAlphaType;
1002c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return SkImageInfo::Make(0, 0, kUnknown_SkColorType, unknownAlphaType);
1003c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1004c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1005c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1006c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1007c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return this->onPeekPixels(info, rowBytes);
1008c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1009c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1010c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
1011c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1012c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    return dev ? dev->peekPixels(info, rowBytes) : NULL;
1013c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1014c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1015c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1016c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1017c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1018c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1019c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (kUnknown_SkColorType == fInfo.colorType() ||
1020c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            !fBitmap.allocPixels(fInfo))
1021c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        {
1022c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1023c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1024c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fBitmap.lockPixels();
1025c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1026c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1027c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1028c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1029c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1030c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1031c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1032c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1033c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1034c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1035c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
1036c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes,
1037c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org                                     NULL, NULL);
1038c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1039c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1040c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1041c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1042c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1043c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10469bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
104850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10522c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
10542c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10569bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
10579bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
10589bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    CHECK_LOCKCOUNT_BALANCE(bitmap);
10599bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
106078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
106178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
106278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
106378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
106478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
106578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
106678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
106778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
106878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
10699bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
10709bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
10719bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
10729bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
10739bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
10749bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10771f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
10788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                                  const SkPaint* paint) {
10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmp.setDither(true);
10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
10858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
10871f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
108876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
108976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
109076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
10918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
10929c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org            SkDeviceImageFilterProxy proxy(dstDev);
109376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
10946776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1095b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1096fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1097fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
10986776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            if (filter->filterImage(&proxy, src, matrix, &dst, &offset)) {
10995efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
11005efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
11016776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
11026776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
110376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
110476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1105b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
110676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.comvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
11128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com                          const SkPaint* paint) {
111350b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
11148926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
11158926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
111650b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
111750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    CHECK_LOCKCOUNT_BALANCE(bitmap);
1118fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11198926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
11208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
11218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
11228926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11248926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1125fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
11278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
11288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
11298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
11308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
11319c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org            SkDeviceImageFilterProxy proxy(iter.fDevice);
11328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
11336776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1134fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1135fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
11366776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, matrix, &dst, &offset)) {
11375efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
11385efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
11396776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
11405efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
11418926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
11428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
11438926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
11448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
11458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
11468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
11478926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
11488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::translate(SkScalar dx, SkScalar dy) {
11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1153c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preTranslate(dx, dy);
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::scale(SkScalar sx, SkScalar sy) {
11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1159c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preScale(sx, sy);
11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::rotate(SkScalar degrees) {
11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1165c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preRotate(degrees);
11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::skew(SkScalar sx, SkScalar sy) {
11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1171c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preSkew(sx, sy);
11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::concat(const SkMatrix& matrix) {
11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1177c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fMatrix->preConcat(matrix);
11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1183c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *fMCRec->fMatrix = matrix;
11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is not virtual, so it must call a virtual method so that subclasses
11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// will see its action
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
11914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1198c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1199da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1200da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
1201da17f758442f16747af39f8fbaed9c097048519creed@google.com        if (fMCRec->fRasterClip->isEmpty()) {
1202da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1203da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1204da17f758442f16747af39f8fbaed9c097048519creed@google.com
12053b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1206da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1207c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1208da17f758442f16747af39f8fbaed9c097048519creed@google.com
1209da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
1210da17f758442f16747af39f8fbaed9c097048519creed@google.com            return fMCRec->fRasterClip->setEmpty();
1211da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1212da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1213da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1214da17f758442f16747af39f8fbaed9c097048519creed@google.com
12155c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
12165c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1218c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
12198f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    doAA &= fAllowSoftClip;
12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fMCRec->fMatrix->rectStaysRect()) {
1222123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
122398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
122498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
122598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMCRec->fMatrix->mapRect(&r, rect);
12290017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        fClipStack.clipDevRect(r, op, doAA);
12300017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        return fMCRec->fRasterClip->op(r, op, doAA);
12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1232123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
123398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
123498de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
123598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
1239c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com        return this->SkCanvas::clipPath(path, op, doAA);
12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12430017708a5bcb6d0fbff0fac565085bef65de7433reed@google.comstatic bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
1244c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.com                           const SkPath& devPath, SkRegion::Op op, bool doAA) {
1245759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    // base is used to limit the size (and therefore memory allocation) of the
1246759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    // region that results from scan converting devPath.
1247759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com    SkRegion base;
1248759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com
1249819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    if (SkRegion::kIntersect_Op == op) {
1250759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // since we are intersect, we can do better (tighter) with currRgn's
1251759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // bounds, than just using the device. However, if currRgn is complex,
1252759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        // our region blitter may hork, so we do that case in two steps.
12530017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        if (currClip->isRect()) {
1254b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // FIXME: we should also be able to do this when currClip->isBW(),
1255b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // but relaxing the test above triggers GM asserts in
1256b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            // SkRgnBuilder::blitH(). We need to investigate what's going on.
1257b446fc7f05d2e3f22d574187b433e02b0c781e1fcommit-bot@chromium.org            return currClip->setPath(devPath, currClip->bwRgn(), doAA);
1258759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        } else {
12590017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            base.setRect(currClip->getBounds());
12600017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            SkRasterClip clip;
12610017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            clip.setPath(devPath, base, doAA);
12620017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            return currClip->op(clip, op);
1263759876a9223ef64f9d0db235d7a46750f8193cbcreed@google.com        }
1264819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    } else {
12651f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        const SkBaseDevice* device = canvas->getDevice();
1266ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        if (!device) {
1267ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com            return currClip->setEmpty();
1268ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        }
1269ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1270a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        base.setRect(0, 0, device->width(), device->height());
1271819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1272819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        if (SkRegion::kReplace_Op == op) {
12730017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            return currClip->setPath(devPath, base, doAA);
1274819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        } else {
12750017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            SkRasterClip clip;
12760017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            clip.setPath(devPath, base, doAA);
12770017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            return currClip->op(clip, op);
1278819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1279819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1280819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1281819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
12824ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.combool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
12834ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
12844ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
12854ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA);
12864ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    } else {
12874ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkPath path;
12884ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        path.addRRect(rrect);
12894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
12904ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        return this->SkCanvas::clipPath(path, op, doAA);
12914ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
12924ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
12934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1294c42d35daa77febcd6791b5dcb0d5f7ec0f5aa84creed@google.combool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1295da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1296da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1297da17f758442f16747af39f8fbaed9c097048519creed@google.com        if (fMCRec->fRasterClip->isEmpty()) {
1298da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1299da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1300fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13013b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1302da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1303c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1304fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1305da17f758442f16747af39f8fbaed9c097048519creed@google.com            fClipStack.clipEmpty();
1306da17f758442f16747af39f8fbaed9c097048519creed@google.com            return fMCRec->fRasterClip->setEmpty();
1307da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1308da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1309da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1310da17f758442f16747af39f8fbaed9c097048519creed@google.com
13115c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
13125c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1314c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13158f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    doAA &= fAllowSoftClip;
13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path.transform(*fMCRec->fMatrix, &devPath);
13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1320fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1321fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1322fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1323fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1324fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1325fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1326fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1327fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1328fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1329fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
13305c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
13310017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    fClipStack.clipDevPath(devPath, op, doAA);
13325c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
133345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
133445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.reset();
133545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
133645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack* clipStack = getClipStack();
133745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
133845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        const SkClipStack::Element* element;
133945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        while ((element = iter.next())) {
134045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkClipStack::Element::Type type = element->getType();
134145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            if (type == SkClipStack::Element::kEmpty_Type) {
134245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                continue;
134345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            }
134445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkPath operand;
134545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            if (type == SkClipStack::Element::kRect_Type) {
134645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                operand.addRect(element->getRect());
134745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            } else if (type == SkClipStack::Element::kPath_Type) {
134845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                operand = element->getPath();
134945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            } else {
135045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                SkDEBUGFAIL("Unexpected type.");
135145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            }
135245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            SkRegion::Op elementOp = element->getOp();
135345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            if (elementOp == SkRegion::kReplace_Op) {
135445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                devPath = operand;
135545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            } else {
135645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com                Op(devPath, operand, (SkPathOp) elementOp, &devPath);
135745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com            }
135896fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
135996fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // perhaps we need an API change to avoid this sort of mixed-signals about
136096fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            // clipping.
136196fd3440fa489f74f903f30487282af99deb2a4dcaryclark@google.com            doAA |= element->isAA();
136245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
136345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
136445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
136545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
13660017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1369ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.orgbool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
1370ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                                                   bool inverseFilled) {
1371ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // This is for updating the clip conservatively using only bounds
1372ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // information.
1373ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // Contract:
1374ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    The current clip must contain the true clip. The true
1375ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    clip is the clip that would have normally been computed
1376ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    by calls to clipPath and clipRRect
1377ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // Objective:
1378ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    Keep the current clip as small as possible without
1379ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    breaking the contract, using only clip bounding rectangles
1380ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    //    (for performance).
1381ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org
1382ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // N.B.: This *never* calls back through a virtual on canvas, so subclasses
1383ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // don't have to worry about getting caught in a loop. Thus anywhere
1384ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // we call a virtual method, we explicitly prefix it with
1385ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    // SkCanvas:: to be sure to call the base-class.
1386a5d3e77420621c912383c3b22e542d9413d68278skia.committer@gmail.com
1387ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    if (inverseFilled) {
1388ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        switch (op) {
1389ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kIntersect_Op:
1390ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kDifference_Op:
1391ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // These ops can only shrink the current clip. So leaving
1392ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // the clip unchanges conservatively respects the contract.
1393ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                return this->getClipDeviceBounds(NULL);
1394ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kUnion_Op:
1395ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReplace_Op:
1396ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReverseDifference_Op:
1397ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kXOR_Op:
1398ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                {
1399ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // These ops can grow the current clip up to the extents of
1400ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // the input clip, which is inverse filled, so we just set
1401ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // the current clip to the device bounds.
1402ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    SkRect deviceBounds;
1403ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    SkIRect deviceIBounds;
1404ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    this->getDevice()->getGlobalBounds(&deviceIBounds);
14054469938e92d779dff05e745559e67907bbf21e78reed@google.com                    deviceBounds = SkRect::Make(deviceIBounds);
1406ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag);
1407ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    // set the clip in device space
1408ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    this->SkCanvas::setMatrix(SkMatrix::I());
1409ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    bool result = this->SkCanvas::clipRect(deviceBounds,
1410ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                        SkRegion::kReplace_Op, false);
1411ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    this->SkCanvas::restore(); //pop the matrix, but keep the clip
1412ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                    return result;
1413ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                }
1414ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            default:
1415ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                SkASSERT(0); // unhandled op?
1416ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        }
1417ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    } else {
1418ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        // Not inverse filled
1419ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        switch (op) {
1420ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kIntersect_Op:
1421ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kUnion_Op:
1422ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReplace_Op:
1423ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                return this->SkCanvas::clipRect(bounds, op, false);
1424ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kDifference_Op:
1425ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Difference can only shrink the current clip.
1426ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Leaving clip unchanged conservatively fullfills the contract.
1427ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                return this->getClipDeviceBounds(NULL);
1428ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kReverseDifference_Op:
1429ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // To reverse, we swap in the bounds with a replace op.
1430ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // As with difference, leave it unchanged.
1431ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                return this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, false);
1432ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            case SkRegion::kXOR_Op:
1433ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // Be conservative, based on (A XOR B) always included in (A union B),
1434ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                // which is always included in (bounds(A) union bounds(B))
1435ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                return this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, false);
1436ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org            default:
1437ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org                SkASSERT(0); // unhandled op?
1438ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org        }
1439ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    }
1440ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org    return true;
1441ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org}
1442ed8d6bb2be0ed6a20841573682afaa46dea15175junov@chromium.org
14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
14445c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14455c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1447c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14495c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
14505c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1451115d931d2fbd3a109a21b28c8a9c5099e6c49c54reed@google.com    fClipStack.clipDevRect(rgn.getBounds(), op);
14525c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14530017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    return fMCRec->fRasterClip->op(rgn, op);
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1456819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1457819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1458819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
14591f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1460ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
1461ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        SkASSERT(this->getTotalClip().isEmpty());
1462ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1463ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1464ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1465819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1466819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
14670017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkRasterClip tmpClip(ir);
1468819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
146980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
14708182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
14718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
14728182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
14738182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kPath_Type:
14748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                clipPathHelper(this,
14758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                               &tmpClip,
14768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                               element->getPath(),
14778182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                               element->getOp(),
14788182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                               element->isAA());
14798182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
14808182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
14818182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
14828182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
14838182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
14848182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
14858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
14868182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
1487819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1488819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1489819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
14906f8f292aa768869a9e85c314b124875f57504f2creed@google.com#if 0   // enable this locally for testing
1491819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // now compare against the current rgn
1492819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    const SkRegion& rgn = this->getTotalClip();
14930017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    SkASSERT(rgn == tmpClip);
149402878b844c5cd3f17d48842da3ccf44a66621501reed@google.com#endif
1495819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1496819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1497819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
149890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
149980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter                iter(fClipStack);
15008182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
15018182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
15028182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    static const SkRect kEmpty = { 0, 0, 0, 0 };
15038182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
15048182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
15058182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kPath_Type:
15068182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                visitor->clipPath(element->getPath(), element->getOp(), element->isAA());
15078182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15088182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
15098182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                visitor->clipRect(element->getRect(), element->getOp(), element->isAA());
15108182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15118182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
15128182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false);
15138182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
151490c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com        }
151590c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
151690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
151790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
15185c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
15195c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15203b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
1521116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
15221607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1523116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1524116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
15250017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    if (fMCRec->fRasterClip->isEmpty()) {
15268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
15278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15298d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com    if (fMCRec->fMatrix->hasPerspective()) {
1530a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
1531a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        fMCRec->fMatrix->mapRect(&dst, rect);
1532a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkIRect idst;
1533a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        dst.roundOut(&idst);
15340017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1535a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1536c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1537d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1538a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1539c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1540c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1541a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1542a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1543c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1544a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1545a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1546a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
15478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15503b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
15513b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15543b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1555bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
1556bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!getClipDeviceBounds(&ibounds)) {
15578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
15588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1560d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1561d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
1562d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    if (!fMCRec->fMatrix->invert(&inverse)) {
156372dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
156472dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
156572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1566d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1567d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1568d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != bounds) {
1570bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
15713b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
15723b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1573fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
15748f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
15758f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
15778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
15798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1581bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
15820017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    const SkRasterClip& clip = *fMCRec->fRasterClip;
1583bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1584bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1585bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1586bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1587bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1588bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1589bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
1590bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (NULL != bounds) {
1591bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1592bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1593bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1594bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1595bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *fMCRec->fMatrix;
15988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1600bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.comSkCanvas::ClipType SkCanvas::getClipType() const {
16010017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType;
16020017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    if (fMCRec->fRasterClip->isRect()) return kRect_ClipType;
1603bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return kComplex_ClipType;
1604bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1605bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::getTotalClip() const {
16070017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    return fMCRec->fRasterClip->forceGetBW();
16088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
161150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org                                          int width, int height,
161250b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org                                          bool isOpaque) {
16131f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getTopDevice();
1614cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com    if (device) {
1615cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com        return device->createCompatibleDeviceForSaveLayer(config, width, height,
1616cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com                                                          isOpaque);
1617e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com    } else {
1618cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.com        return NULL;
1619e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com    }
16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1622644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1623644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1624644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
1625644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    if (NULL != device) {
1626644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
1627644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        if (NULL != renderTarget) {
1628644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1629644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1630644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1631644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1632644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1633644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1634644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1635644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1636e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
16388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
16398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16412a98181f048c11f21f52fbd99f803f5fd6118261reed@google.comvoid SkCanvas::clear(SkColor color) {
16422a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    SkDrawIter  iter(this);
1643995beb6b00afc0e28f5effc8a22a7a3dcb2544e8junov@chromium.org    this->predrawNotify();
16442a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    while (iter.next()) {
16452a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com        iter.fDevice->clear(color);
16462a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com    }
16472a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com}
16482a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com
16498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPaint(const SkPaint& paint) {
1650fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1651fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1652fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1653fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
1654ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
1655ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
165678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
16594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16624e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
16668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
16678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
16688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
16698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1671ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
1672ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
167378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
167478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1675a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1676a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1677a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1678a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1679a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1680a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1681a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
168278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
168378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
1684a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
1685a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1686fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1687a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
16888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
169078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
16914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
16934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16954b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
16964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
16978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16997ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1700ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
1701ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
170278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
170378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
17048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
170578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(r, &storage);
170678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
17088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
17098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17104b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
171178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
17128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
17144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1721ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
1722ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
172378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
172478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
17254ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
172678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
172778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
17294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
17304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1731306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
173278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
173346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
173446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
173546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
173646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
173746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
173846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
17394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
17404ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
17414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.comvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1742ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
1743ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
174478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
174578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
17464ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
174778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
174878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
17504ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
17514ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
17524ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
17534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
17544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
17554ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1756f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
1757f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
17584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
1759f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1760f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
17614ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1762f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
176378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1764f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1765f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
1766f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1767f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
1768f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1769f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
17704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
17714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
17724ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
17737ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1774ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
1775ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
17769364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
17779364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
17789364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
17799364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
178078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
178178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1782fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
178378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
178478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
178578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
17868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
17878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
17888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1789fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
1790fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        if (path.isInverseFillType()) {
1791fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
1792fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
1793fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
1794fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
179678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
17994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
18068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint* paint) {
18078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
18088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18093d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
18109efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
18119efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
18129efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
18139efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
18149efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
18159efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
18169efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
18179efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
18183b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18224b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
18248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
18259bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18289987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
18297112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1830eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
1831eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      DrawBitmapRectFlags flags) {
183250b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
183574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
1836ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_LOCKCOUNT_BALANCE(bitmap);
1837ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
183878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
183978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
18403d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
18419efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
18429efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
18439efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
18443b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
18453d60812865bb034851da777a91413ab584929887reed@google.com            return;
18463d60812865bb034851da777a91413ab584929887reed@google.com        }
18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18483d60812865bb034851da777a91413ab584929887reed@google.com
184933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
185033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
185133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18537064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
185478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
18557064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
185633535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
1857eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
1858f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
18597064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
186033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18637112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1864eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    const SkRect& dst, const SkPaint* paint,
1865eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                    DrawBitmapRectFlags flags) {
18669987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
1867eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
18689987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
18699987ec3791336bad6af5cbe513564786b2df55aareed@google.com
18708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPaint* paint) {
18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
18739bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18769987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
18779987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkIRect& center, const SkRect& dst,
18789987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkPaint* paint) {
187950b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
188050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org        return;
188150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    }
18823d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
188360abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        SkRect storage;
188460abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        const SkRect* bounds = &dst;
188560abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
188660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
188760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
18883b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
18893d60812865bb034851da777a91413ab584929887reed@google.com            return;
18903d60812865bb034851da777a91413ab584929887reed@google.com        }
18913d60812865bb034851da777a91413ab584929887reed@google.com    }
18923d60812865bb034851da777a91413ab584929887reed@google.com
18939987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t w = bitmap.width();
18949987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t h = bitmap.height();
18959987ec3791336bad6af5cbe513564786b2df55aareed@google.com
18969987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkIRect c = center;
18979987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // pin center to the bounds of the bitmap
18989987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fLeft = SkMax32(0, center.fLeft);
18999987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fTop = SkMax32(0, center.fTop);
19009987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fRight = SkPin32(center.fRight, c.fLeft, w);
19019987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
19029987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19037112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcX[4] = {
19047d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
19057112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
19067112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcY[4] = {
19077d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
19087112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
19099987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstX[4] = {
19109987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
19119987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
19129987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
19139987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstY[4] = {
19149987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
19159987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
19169987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
191774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
19189987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstX[1] > dstX[2]) {
19199987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
19209987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[2] = dstX[1];
19219987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
192274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
19239987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstY[1] > dstY[2]) {
19249987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
19259987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[2] = dstY[1];
19269987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
192774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
19289987ec3791336bad6af5cbe513564786b2df55aareed@google.com    for (int y = 0; y < 3; y++) {
19297112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com        SkRect s, d;
19307112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com
19319987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fTop = srcY[y];
19329987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fBottom = srcY[y+1];
19339987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fTop = dstY[y];
19349987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fBottom = dstY[y+1];
19359987ec3791336bad6af5cbe513564786b2df55aareed@google.com        for (int x = 0; x < 3; x++) {
19369987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fLeft = srcX[x];
19379987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fRight = srcX[x+1];
19389987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fLeft = dstX[x];
19399987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fRight = dstX[x+1];
1940eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org            this->internalDrawBitmapRect(bitmap, &s, d, paint,
194131acc11977815402e4ef2681350f8559285bec97robertphillips@google.com                                         kNone_DrawBitmapRectFlag);
19429987ec3791336bad6af5cbe513564786b2df55aareed@google.com        }
19439987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
19449987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
19459987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19469987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
19479987ec3791336bad6af5cbe513564786b2df55aareed@google.com                              const SkRect& dst, const SkPaint* paint) {
19489987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
19499987ec3791336bad6af5cbe513564786b2df55aareed@google.com
19509987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // Need a device entry-point, so gpu can use a mesh
19519987ec3791336bad6af5cbe513564786b2df55aareed@google.com    this->internalDrawBitmapNine(bitmap, center, dst, paint);
19529987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
19539987ec3791336bad6af5cbe513564786b2df55aareed@google.com
1954f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
1955f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
19561f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
19571f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice::TextFlags flags;
1958f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        if (device->filterTextFlags(paint, &flags)) {
1959a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
1960f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            newPaint->setFlags(flags.fFlags);
1961f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            newPaint->setHinting(flags.fHinting);
1962f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
1963f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
1964f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
1965f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
1966f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
1967f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
1968f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
1969f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
1970f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
19712c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
19722c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
1973f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
1974f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
197552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
197652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
197717b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
197852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
197952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
198052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
198117b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
198252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
198352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
198452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
198552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
198652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
198752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
198852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
198952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
199052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
199152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
199252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
199352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
199452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
199552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
199652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
199752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
199852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
199952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
200052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
200152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
200252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
200352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
200452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
200552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
200652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
200752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
200852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
200952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
201052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
201152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
201252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
201352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
201452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
201552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
201652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
201752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
201852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
201952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
202052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
202152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
202252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
202352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
202452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
202552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
202652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
202752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
202852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
202952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
203052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
203152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
203252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
203352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
203452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
203552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
203652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
203752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
203852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
203952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
204052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
204152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
204252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
204352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
204452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
204552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
204652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
20478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawText(const void* text, size_t byteLength,
20488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        SkScalar x, SkScalar y, const SkPaint& paint) {
2049ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
2050ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
205178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
20528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2055f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
205652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
205752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
20588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength,
20648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           const SkPoint pos[], const SkPaint& paint) {
2065ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
2066ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
206778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
20684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
20718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
2072f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
20738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength,
20798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkScalar xpos[], SkScalar constY,
20808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
2081ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
2082ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
208378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
20844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
20878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
2088f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
20898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20904b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
20958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPath& path, const SkMatrix* matrix,
20968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
2097ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
2098ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
209978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
21008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
21034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPoint verts[], const SkPoint texs[],
21118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkColor colors[], SkXfermode* xmode,
21128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const uint16_t indices[], int indexCount,
21138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPaint& paint) {
2114ea033606a06d05d2d42aa7118409fee798e53167reed@google.com    CHECK_SHADER_NOSETCONTEXT(paint);
2115ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
211678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
21174b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
21204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
21214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
21228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21244e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
21288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
21298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
21308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2133845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
21348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
21358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2137845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
21380baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
21418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2143845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
21448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
21458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2147845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
21480baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
21518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
21548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
21554b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
21578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
21588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
21628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
21634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
21658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
21668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
21718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
21724b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
21748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
21758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
21768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
21798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
21808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
21818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
21828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
21848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
21858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
21888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
21898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
21908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
21918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
21948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
21954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
21968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
21998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
22008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
22018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
22028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
22033b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
22058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
22068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
22074ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
22084ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
22094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
22118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
22128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
22178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
22188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
22198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
22208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
22218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
22228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
22238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
22248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
22258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
22268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
22278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
22288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
22298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
22308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
22348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
22358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
22368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
22374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2242f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
2243f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com
22448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPicture(SkPicture& picture) {
22458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    picture.draw(this);
22468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
22498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
22508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2252d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
22558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
22578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
22588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
22618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
22628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
22658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
22668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22681f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
22708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
22738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
22748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
22778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
22788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
22808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
22828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
22858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
22868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
228720a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
228820a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
228920a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
229020a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.comSkCanvas::ClipVisitor::~ClipVisitor() { }
2291