SkCanvas.cpp revision 71c3c760a83123ee0b3127b8c65c6394ce541c50
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
9d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h"
11dbc3cefb0b624808ddb86d444e6103f216e12fa5reed#include "SkColorFilter.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
133cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
165f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt#include "SkErrorInternals.h"
17b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
1874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
1945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h"
20b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
220017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
2396472deea70169396b8e1f576e470138f55fdb1freed#include "SkReadPixelsRec.h"
244ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
287ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
2952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
30a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
318f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
35644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
36644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
37644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
38d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
39d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
40d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
41d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
42d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
43d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
44d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
45d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
460acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
470acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
480acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
490acf1b4b3645772d220c720313821bac389751b5reed}
500acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
510acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
520acf1b4b3645772d220c720313821bac389751b5reed}
530acf1b4b3645772d220c720313821bac389751b5reed
54da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
55da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
5615e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
802c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
812c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
8297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() {
8397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
84c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
8597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
8697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
8797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
904a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
914a8126e7f81384526629b1e21bf89b632ea13cd9reed    const uint32_t propFlags = props.flags();
924a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
934a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kDither_Flag;
944a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
954a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
964a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kAntiAlias_Flag;
974a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
984a8126e7f81384526629b1e21bf89b632ea13cd9reed    return flags;
994a8126e7f81384526629b1e21bf89b632ea13cd9reed}
1004a8126e7f81384526629b1e21bf89b632ea13cd9reed
1014a8126e7f81384526629b1e21bf89b632ea13cd9reed///////////////////////////////////////////////////////////////////////////////
1024a8126e7f81384526629b1e21bf89b632ea13cd9reed
1031f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1121f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1146f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
11561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const SkMatrix*     fMatrix;
11661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    SkMatrix            fMatrixStorage;
11761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const bool          fDeviceIsBitmapDevice;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11996e657d0e103b8358a77ecd913f6086929f792b8reed    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
12086a17e7716c8db858e219a46b9db3817bb770beereed             bool conservativeRasterClip, bool deviceIsBitmapDevice)
121d954498c01ccf0417feacf89e45d0c62a06a813breed        : fNext(NULL)
122d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
12361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
124d954498c01ccf0417feacf89e45d0c62a06a813breed    {
125d954498c01ccf0417feacf89e45d0c62a06a813breed        if (NULL != device) {
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
12740a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1294b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
13188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13388edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
13449f085dddff10473b6ebf832a974288300224e60bsalomon        if (fDevice) {
13540a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
13988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1404b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
141feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
142feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
143feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
144feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
145feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
146feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
147feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
148045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
1506f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
1516f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
1544b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
1634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
167045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
1704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
172045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1754b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1763fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
1773fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
185f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1971f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
198d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    DeviceCM*       fTopLayer;
2062ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRasterClip    fRasterClip;
2072ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkMatrix        fMatrix;
2082ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int             fDeferredSaveCount;
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
210d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
211d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter     = NULL;
212d954498c01ccf0417feacf89e45d0c62a06a813breed        fLayer      = NULL;
213d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer   = NULL;
2142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
2152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
216b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
217d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
218d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
219d954498c01ccf0417feacf89e45d0c62a06a813breed    }
2202ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
221d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
223d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
2242ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
225b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
23082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
234feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
235feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
236feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
237feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
238feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
239feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
240feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
241feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
242feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2478a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
2484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
2498a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
252687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack = canvas->fClipStack;
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
2548a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2564b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
265f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
266f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
269045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
270045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
27241e010cb901c0da9066c4df562030808c9ccd7f8reed            if (!fDevice->accessPixels(&fDst)) {
27341e010cb901c0da9066c4df562030808c9ccd7f8reed                fDst.reset(fDevice->imageInfo(), NULL, 0);
27441e010cb901c0da9066c4df562030808c9ccd7f8reed            }
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
276f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
280199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2854b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2861f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
2876f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
2886f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
2926f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
304dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
305dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
306dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
307dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
308dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
309dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
310dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  colorfilter, else return NULL.
311dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
312dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkColorFilter* image_to_color_filter(const SkPaint& paint) {
313dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
314dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
315dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return NULL;
316dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
317dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
318dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* imgCF;
319dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf->asAColorFilter(&imgCF)) {
320dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return NULL;
321dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
322dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
323dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
324dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (NULL == paintCF) {
325dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
326dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
327dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
328dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
329dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
330dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
331dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
332dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
333dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
334dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3374a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
33878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
33978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
3404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
3424a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
3434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
3445c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
3454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
347dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
348dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
349dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
350dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setColorFilter(simplifiedCF)->unref();
351dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setImageFilter(NULL);
352dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
353dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
354dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
355dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
3565c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
3575c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
3585c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
3595c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
3605c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
3615c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
3625c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
3635c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
3645c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
3655c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
3665c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
3675c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
3685c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
3695c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
3705c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
3718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
372dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setImageFilter(fPaint->getImageFilter());
373dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setXfermode(fPaint->getXfermode());
374e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
37576033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
3765c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
3775c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
3788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3798926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
38079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
38179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
38279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
38379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
384129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
385129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
38679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = NULL;
387129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
3885c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
390b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
3914a8126e7f81384526629b1e21bf89b632ea13cd9reed        uint32_t oldFlags = paint.getFlags();
3924a8126e7f81384526629b1e21bf89b632ea13cd9reed        fNewPaintFlags = filter_paint_flags(props, oldFlags);
3934a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (fIsSimple && (fNewPaintFlags != oldFlags)) {
394dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
3954a8126e7f81384526629b1e21bf89b632ea13cd9reed            paint->setFlags(fNewPaintFlags);
3964a8126e7f81384526629b1e21bf89b632ea13cd9reed            fPaint = paint;
3974a8126e7f81384526629b1e21bf89b632ea13cd9reed            // if we're not simple, doNext() will take care of calling setFlags()
3984a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
40074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
4025c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
4038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
4048926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
40774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
4094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
4104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
4114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
41274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
413129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
414129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
415129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
416129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
417129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
418129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
419129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
420129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
421129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
422fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
42374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
425dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintInit; // base paint storage in case we need to modify it
426dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
4272c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
4282c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
4292c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
4302c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
4312c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
4324a8126e7f81384526629b1e21bf89b632ea13cd9reed    uint32_t        fNewPaintFlags;
4335c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
4342c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
435129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
43679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
43779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
438129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
439129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
442129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
443632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
444129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
4455c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
446632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
447dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
448dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
4494a8126e7f81384526629b1e21bf89b632ea13cd9reed    paint->setFlags(fNewPaintFlags);
4508926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
4515c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
452129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
4535c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        paint->setXfermode(NULL);
454129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
4558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
45679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
457129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
458129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
459129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
460129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
461971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
462971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
463971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
464971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
46579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (NULL == fLooperContext) {
466129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
467632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
468632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
469129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
470129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
4718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
472129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
47379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
4744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
4754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
477632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
478632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
4794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
4804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
4814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
4834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
4844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
48897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
4894a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, true);              \
4908926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
4918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
4928926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
49378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
49497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
4954a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
4964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
4984b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
4994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
503feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
504feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
505feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBounds.setEmpty();
506feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBoundsDirty = true;
507feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fClipStack->reset();
508feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
509feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
510feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
511feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
512feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
513feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
514feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
515d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
516d954498c01ccf0417feacf89e45d0c62a06a813breed    fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
517c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
518c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
5198f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
52045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
521f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
5222ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
52374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
525687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack.reset(SkNEW(SkClipStack));
526687fa1c745febb57f42b0d5f03d7c1f4be2530careed
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
528d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
530a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
531a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
53286a17e7716c8db858e219a46b9db3817bb770beereed    new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, false);
533b679ca8926a832274b14fdb512f88f64b61d32eareed
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
537f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
538f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
539efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
540efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
5414a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (device->forceConservativeRasterClip()) {
5424a8126e7f81384526629b1e21bf89b632ea13cd9reed            fConservativeRasterClip = true;
5434a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
544f92c86642a1875da54d54b447f006cb9dfbbb35creed        device->onAttachToCanvas(this);
545f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
54678e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
547f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
548f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
551cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
552e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
5534a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
554e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
5558d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
556ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
557d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(NULL, kDefault_InitFlags);
5588d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
5598d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
560d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
561d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
562d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
563d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
564d954498c01ccf0417feacf89e45d0c62a06a813breed}
565d954498c01ccf0417feacf89e45d0c62a06a813breed
566d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
567d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
568fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps)
569fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips        : INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps)
57078e276889795454891cbba48ab11927968114953reed    {
57178e276889795454891cbba48ab11927968114953reed        this->setOrigin(bounds.x(), bounds.y());
57278e276889795454891cbba48ab11927968114953reed    }
573d954498c01ccf0417feacf89e45d0c62a06a813breed
574d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
575b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
576d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
577d954498c01ccf0417feacf89e45d0c62a06a813breed};
578d954498c01ccf0417feacf89e45d0c62a06a813breed
57996a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
580e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
58196a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
582e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
583e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
584b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
58578e276889795454891cbba48ab11927968114953reed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice,
586fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips                          (SkIRect::MakeWH(width, height), fProps)), kDefault_InitFlags)->unref();
587d954498c01ccf0417feacf89e45d0c62a06a813breed}
588e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
58978e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
590d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
5914a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
592d954498c01ccf0417feacf89e45d0c62a06a813breed{
593d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
594b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
595fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (bounds, fProps)), flags)->unref();
59627a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
599d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6007b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
601d954498c01ccf0417feacf89e45d0c62a06a813breed{
602d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
603b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
604d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
607fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
608fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6097b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
610fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
611fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
612fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
613fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
614fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
615fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
6164a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
6173716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6184a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
6193716fd067a5621bb94a6cb08d72afec8bf3acedareed{
6203716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
621b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
622fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap, fProps)));
6234a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
6244a8126e7f81384526629b1e21bf89b632ea13cd9reed}
62529c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
6264a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap)
6274a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6284a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
6294a8126e7f81384526629b1e21bf89b632ea13cd9reed{
6304a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
631b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
632fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap, fProps)));
6334a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
6397c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
64274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
643b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
65251985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
65874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
65974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
66074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
66174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
66274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
66374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
66474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
66574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
6691f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
670bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
671bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
672bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
673bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
674bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
6754ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
6764ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
6774ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
6784ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
6794ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
6804ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
6814ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
6824ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
6834ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
6844ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
6854ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
6861f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
687210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
688210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
689210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
6901f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
692c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6971f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
6980b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
6990b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
7000b53d59a24f667350b4282f88470713902409030reed@google.com    }
7019266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
7029266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
7039266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
704a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
705a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
706a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
707a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
708a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
709a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
710a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == bitmap->pixelRef()) {
711848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
712a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
713a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
714a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
715a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
716a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
717cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
718cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap->requestLock(&unlocker)) {
719cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
720cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
721cf01e31df6bbda270dca2ee3b4967caf51e465dcreed            return true;
722cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        }
723a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
724a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
725a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
726a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->setPixelRef(NULL);
727a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
728a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
729a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
73051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
731c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
732a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
733a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
734a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
735a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
736ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
737ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
73874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
739848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
740a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
741a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
742a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
743a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
744a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
745daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
746c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
747a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
748a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
749c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
75096472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
751a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
752a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
753a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
754a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
755a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
756f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
75796472deea70169396b8e1f576e470138f55fdb1freed    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
75896472deea70169396b8e1f576e470138f55fdb1freed    if (!rec.trim(size.width(), size.height())) {
759a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
760a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
761db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
762a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
76396472deea70169396b8e1f576e470138f55fdb1freed    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
76451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
76551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
7674cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
7684cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7694cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
770cf01e31df6bbda270dca2ee3b4967caf51e465dcreed
771cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
772cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap.requestLock(&unlocker)) {
773cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
774cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
7754cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7764cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
7774cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
7784cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7794cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
7804cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
7814cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
7824cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
7834cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
7844cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
7854cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
7864cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
7874cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7884cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
7894cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7904cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7914cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7924cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
7934cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
7944cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
7954cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7964cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7974cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7984cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
7994cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
8004cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8014cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8024cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8034cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
804e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
8054cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8064cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
8074cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
8084cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
8094cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8104cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
8114cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
8124cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8134cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
8144cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
8154cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8164af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
8174af35f348b2e2f6c428819118eb7a2f2fff53a74reed    this->predrawNotify();
8184af35f348b2e2f6c428819118eb7a2f2fff53a74reed
8194cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
8204ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
8214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
82251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8234370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
8244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
8254370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8264370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
8321f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
8344b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
836687fa1c745febb57f42b0d5f03d7c1f4be2530careed            layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL);
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
838045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
840687fa1c745febb57f42b0d5f03d7c1f4be2530careed                layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8492ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
8502ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
8512ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
8522ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8532ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
8542ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
855f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
8562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
8572ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
8582ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
8592ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
8602ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
8612ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
8622ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
8632ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
8642ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
8652ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8662ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
8672ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
8682ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
869f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
870f0090cb80ab10a49e511aa5450ae38917fa058d9reed
871f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
8722ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
8732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
8742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
8752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
8762ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
8772ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
878f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
879a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
880a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
881a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
8822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
883f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
884f0090cb80ab10a49e511aa5450ae38917fa058d9reed
885f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
8862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
8872ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
8882ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
8892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
8902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
8912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
8922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
8932ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
8942ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
895a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
8962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
8972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
8982ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
899f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
900f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
901f0090cb80ab10a49e511aa5450ae38917fa058d9reed
902f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
903f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
904f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
905f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
906f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
907f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
908f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
909f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
910f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
911f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
912f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
913f0090cb80ab10a49e511aa5450ae38917fa058d9reed
9142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
916d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
9184b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
919687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->save();
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
923b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
925b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
926b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
927b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
930a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
9319b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
932bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
933bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
934a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
935f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
936c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
93796e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
93896e657d0e103b8358a77ecd913f6086929f792b8reed
939c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
94096e657d0e103b8358a77ecd913f6086929f792b8reed        imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
941c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
942bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
94349f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
9454b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
94696e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
950bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
9519b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                fCachedLocalClipBoundsDirty = true;
9521f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
953bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
954a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
959180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
96189f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
962180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
9639b3aa54bc9605257c701cf465813f5fb1d7ba39ereed        fCachedLocalClipBoundsDirty = true;
964687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
965180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
966a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
967a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
968a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
969a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
970a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
971a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
972a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
973a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
974d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
975d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
976d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed        bounds = NULL;
977d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
978d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
979a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
98076033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy);
9812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
982d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
983d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
9842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
985d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
986d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed        bounds = NULL;
987d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
988e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
989a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
99076033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, flags, strategy);
9912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
9928926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
9938926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
9942ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
99576033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                 SaveLayerStrategy strategy) {
996b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
9972a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    flags |= kClipToLayer_SaveFlag;
998b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
999b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
1000a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1001a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
10022ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1003a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1004a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
1005a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1006a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
1007daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
10082ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1011e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1012e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1013e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
10142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1015e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1016e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
101776033be81b82c44fd5d4fdf2672eb22e505da1f0reed    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
10188dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
10198dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
102076033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1021daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
102276033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
10238dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1024b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1025b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
102615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
102715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1029b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    SkBaseDevice* device = this->getTopDevice();
1030b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    if (NULL == device) {
1031b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
10322ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1033b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1034b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
103561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    bool forceSpriteOnRestore = false;
103661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
1037daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
103861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo);
103961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
104061f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        if (NULL == newDev) {
104161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
10429a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry);
10439a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            newDev = SkBitmapDevice::Create(createInfo.fInfo, surfaceProps);
104461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            if (NULL == newDev) {
104561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                SkErrorInternals::SetError(kInternalError_SkError,
104661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                           "Unable to create device for layer.");
104761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                return;
104861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            }
104961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            forceSpriteOnRestore = true;
105061f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
105161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        device = newDev;
1052e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
1053e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
10546f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
105561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip,
105686a17e7716c8db858e219a46b9db3817bb770beereed                                            forceSpriteOnRestore));
10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1064d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1065d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
1066d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1067d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1083c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1085687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->restore();
10866c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
108788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
110149f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
11036f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
11048926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
110561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                     layer->fPaint, layer->fDeviceIsBitmapDevice);
11068926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
1108b679ca8926a832274b14fdb512f88f64b61d32eareed            SkDELETE(layer);
1109b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1110b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1111a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1112b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
111488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11174a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
11184a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (NULL == props) {
11194a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
11204a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
11214a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
112276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
112376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
11244a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
112576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
11264a8126e7f81384526629b1e21bf89b632ea13cd9reed    return dev ? dev->newSurface(info, props) : NULL;
112776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
112876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1129c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1130c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1131c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1132c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1133c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1134900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1135c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1136c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1137c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1138c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1139884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1140884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onPeekPixels(&pmap)) {
1141884e97cb04db7ed053a866567ee9c6e4c01f993areed        return NULL;
1142884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1143884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1144884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1145884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1146884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1147884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1148884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1149884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.addr();
1150c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1151c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1152884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1153c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1154884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1155c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1156c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
11576b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1158884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1159884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
1160884e97cb04db7ed053a866567ee9c6e4c01f993areed        return NULL;
1161884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1162884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1163884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1164884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1165884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1166884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1167884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1168884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
11696b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
11706b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1171884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
11729c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
11739c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1174884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
11759c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1176884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
11779c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
11789c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1179c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1180c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1181c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1182c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1183848250415eddc54075f7eb8795e8db79e749c6abreed        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1184c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1185c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1186c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1187c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1188c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1189c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1190c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1191c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1192c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1193c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1194c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1195c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1196c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
119700f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1198c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1199c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1200c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1201c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1202c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1203c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1204520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
12059bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
120750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12112c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12132c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12159bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12169bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
12179bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
121878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
121978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
122078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
122178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
122278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
122378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
122478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
122578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
122678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
12279bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12289bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
12299bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
12309bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
12319bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12329bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12351f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
123661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                  const SkPaint* paint, bool deviceIsBitmapDevice) {
12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12414b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
12441f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
124576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
124676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
124776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
1249efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips            SkImageFilter::Proxy proxy(dstDev);
125076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
12516776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1252b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1253fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1254d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
12554cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1256be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
125755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
12584cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
12595efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
12605efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
12616776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
12626776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
126376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
126461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        } else if (deviceIsBitmapDevice) {
12659572a10c9a6a868bbb8f71d7806d0a45f183333freed            const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap;
126661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
126776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1268b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
126976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
127441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) {
12750acf1b4b3645772d220c720313821bac389751b5reed    if (gTreatSpriteAsBitmap) {
12760acf1b4b3645772d220c720313821bac389751b5reed        this->save();
12770acf1b4b3645772d220c720313821bac389751b5reed        this->resetMatrix();
12780acf1b4b3645772d220c720313821bac389751b5reed        this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint);
12790acf1b4b3645772d220c720313821bac389751b5reed        this->restore();
12800acf1b4b3645772d220c720313821bac389751b5reed        return;
12810acf1b4b3645772d220c720313821bac389751b5reed    }
12820acf1b4b3645772d220c720313821bac389751b5reed
12839881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()");
128450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
12868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
128750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
1288fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12898926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
12908926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
12918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
12928926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1293fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12948926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1295fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
12978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
12988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
12998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
13008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1301efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips            SkImageFilter::Proxy proxy(iter.fDevice);
13028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
13036776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1304fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1305d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1306f622a6c8fd176acf9944de8df00d7f0bb56b67d3halcanary            const SkIRect clipBounds = bitmap.bounds();
1307be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
130855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
13094cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
13105efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
13115efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
13126776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
13135efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
13148926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
13158926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
13168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
13178926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
13188926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
13198926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
13208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
13218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
132392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1324d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1325d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1326d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
132992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1330d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1331d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1332d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
133592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1336d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1337d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1338d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
134192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1342d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1343d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1344d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
134544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
134644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
134792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1348d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1349d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1350d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1351d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
13522ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1354c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13551f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
135644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
135744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
135844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
135944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
136086a17e7716c8db858e219a46b9db3817bb770beereedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
136186a17e7716c8db858e219a46b9db3817bb770beereed    this->checkForDeferredSave();
13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1363c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13641f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
136544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
13704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1377759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
13782ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
13798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
13808f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
13818f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
13828f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
13838f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1384da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1385da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
13861f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1387da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1388da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1389da17f758442f16747af39f8fbaed9c097048519creed@google.com
13903b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1391da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1392c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1393da17f758442f16747af39f8fbaed9c097048519creed@google.com
1394687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
13951f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1396da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1397da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1398da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1399da17f758442f16747af39f8fbaed9c097048519creed@google.com
14005c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14015c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1403c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
14058f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
14068f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14081f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.rectStaysRect()) {
1409123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
141098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
141198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
141298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14151f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&r, rect);
1416687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1417d954498c01ccf0417feacf89e45d0c62a06a813breed        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1419123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
142098de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
142198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
142298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
14268f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
143073e714eb766617ce06757829a3c0b345c7963faareedstatic void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
143173e714eb766617ce06757829a3c0b345c7963faareed                            SkRegion::Op op, bool doAA) {
1432d64c9487135094c83f658319f53ea2005ecc08b2reed    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1433819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1434819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1435759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
14362ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
14398f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
14408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14418f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
14424ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
14438f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
144414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
14458f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
144614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
14471f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
144814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
144914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
145014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
145114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
14528f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
14538f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
14548f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
145514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1456687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
145714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
145814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
145914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
146014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
146173e714eb766617ce06757829a3c0b345c7963faareed        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
14628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
146314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
146414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
146514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
146614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
146714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
14688f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
14694ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
14704ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1471759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
14722ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14738f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14748f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
14758f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
14768f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
14778f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14788f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
14798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14808f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14818f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
14828f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1483da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1484da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
14851f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1486da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1487da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1488fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
14893b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1490da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1491c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1492fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1493687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
14941f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1495da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1496da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1497da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1498da17f758442f16747af39f8fbaed9c097048519creed@google.com
14995c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15005c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1502c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15038f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
15048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
15058f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
15081f836ee096bb988adef4b9757b2629c7afeda36dreed    path.transform(fMCRec->fMatrix, &devPath);
15098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1510fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1511fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1512fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1513fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1514fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1515fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1516fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1517fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1518fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1519fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
15205c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
1521687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
15225c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
152345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
15241a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        bool clipIsAA = getClipStack()->asPath(&devPath);
15251a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        if (clipIsAA) {
15261a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita            edgeStyle = kSoft_ClipEdgeStyle;
152745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
15281a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita
152945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
153045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
153145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
153273e714eb766617ce06757829a3c0b345c7963faareed    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
15338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1535759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
15362ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
15388f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15398f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
15415c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15425c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1544c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15465c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
15475c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1548687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevRect(rgn.getBounds(), op);
15495c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15501f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
15518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1553819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1554819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1555819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
15561f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1557ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
15585c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1559ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1560ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1561ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1562819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1563819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1564d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1565819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1566687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
15678182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
15688182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
15698182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
15708182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
15718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
15728182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
15738182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
15758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
15768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15779cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
15789cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
15799cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
158073e714eb766617ce06757829a3c0b345c7963faareed                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
15819cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
15829cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1583819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1584819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1585819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1586819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1587819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
158890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
1589687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
15908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
15918182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
15928182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
1593c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
159490c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
159590c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
159690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
15975c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
15985c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1599754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
16001f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1601754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1602754de5f65b466f721d952a379194cc94de376f42reed@google.com
16035c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
16041f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
16055c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16065c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16073b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
16081607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1609116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1610116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
16111f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
16128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
16138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16151f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.hasPerspective()) {
1616a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
16171f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&dst, rect);
1618b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1619a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1620c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1621d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1622a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1623c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1624c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1625a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1626a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1627c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1628a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1629a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1630a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
16318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16343b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
16353b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
16368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16383b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1639bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
16408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
16418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
16428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1644d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1645d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
16461f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
164772dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
164872dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
164972dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1650d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1651d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1652d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
165349f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1654bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
16553b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
16563b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1657fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
16588f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
16598f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1665bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
16661f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1667bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1668bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1669bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1670bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1671bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1672bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1673bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
167449f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1675bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1676bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1677bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1678bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1679bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
16811f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
16828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16845c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
16851f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
16865c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16875c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16889c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
16899c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
16909c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessRenderTarget() : NULL;
16919c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
16929c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1693644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1694644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1695644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
169649f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
1697644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
169849f085dddff10473b6ebf832a974288300224e60bsalomon        if (renderTarget) {
1699644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1700644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1701644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1702644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1703644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1704644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1705644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1706644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1707e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1708ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1709ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
17109881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1711ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1712ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1713ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1714ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1715ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1716ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1717ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1718ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1719ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1720ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1721ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1722ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1723ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1724ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1725ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1726ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1727ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1728ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
172941af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
173041af966ab338e95eee81ab618ab28195075338f7reed
173141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
173241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
173341af966ab338e95eee81ab618ab28195075338f7reed}
173441af966ab338e95eee81ab618ab28195075338f7reed
173541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
173641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
173741af966ab338e95eee81ab618ab28195075338f7reed}
173841af966ab338e95eee81ab618ab28195075338f7reed
173941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
174041af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
174141af966ab338e95eee81ab618ab28195075338f7reed}
174241af966ab338e95eee81ab618ab28195075338f7reed
174341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
174441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
174541af966ab338e95eee81ab618ab28195075338f7reed}
174641af966ab338e95eee81ab618ab28195075338f7reed
174741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
174841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
174941af966ab338e95eee81ab618ab28195075338f7reed}
175041af966ab338e95eee81ab618ab28195075338f7reed
175141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
175241af966ab338e95eee81ab618ab28195075338f7reed                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
175341af966ab338e95eee81ab618ab28195075338f7reed                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
175441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
175541af966ab338e95eee81ab618ab28195075338f7reed                         indices, indexCount, paint);
175641af966ab338e95eee81ab618ab28195075338f7reed}
175741af966ab338e95eee81ab618ab28195075338f7reed
175841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
175941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
176041af966ab338e95eee81ab618ab28195075338f7reed}
176141af966ab338e95eee81ab618ab28195075338f7reed
1762a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1763a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
176441af966ab338e95eee81ab618ab28195075338f7reed}
176541af966ab338e95eee81ab618ab28195075338f7reed
176641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
176741af966ab338e95eee81ab618ab28195075338f7reed                             const SkPaint* paint) {
1768a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (dst.isEmpty()) {
1769a85d4d0814818e4ddabb9237da209d61d6cd5854reed        return;
1770a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
177141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawImageRect(image, src, dst, paint);
177241af966ab338e95eee81ab618ab28195075338f7reed}
177341af966ab338e95eee81ab618ab28195075338f7reed
177441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
17752df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    if (bitmap.empty()) {
17762df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
17772df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
177841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
177941af966ab338e95eee81ab618ab28195075338f7reed}
178041af966ab338e95eee81ab618ab28195075338f7reed
178141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
178241af966ab338e95eee81ab618ab28195075338f7reed                                    const SkPaint* paint, DrawBitmapRectFlags flags) {
17832df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    if (bitmap.empty()) {
17842df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
17852df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
178641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmapRect(bitmap, src, dst, paint, flags);
178741af966ab338e95eee81ab618ab28195075338f7reed}
178841af966ab338e95eee81ab618ab28195075338f7reed
178941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
179041af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
17912df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    if (bitmap.empty()) {
17922df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
17932df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
179441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmapNine(bitmap, center, dst, paint);
179541af966ab338e95eee81ab618ab28195075338f7reed}
179641af966ab338e95eee81ab618ab28195075338f7reed
179741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
17982df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    if (bitmap.empty()) {
17992df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18002df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
180141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawSprite(bitmap, left, top, paint);
180241af966ab338e95eee81ab618ab28195075338f7reed}
180341af966ab338e95eee81ab618ab28195075338f7reed
180471c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
180571c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkColor colors[], int count, SkXfermode::Mode mode,
180671c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
180771c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
180871c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
180971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
181071c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(atlas);
181171c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(xform);
181271c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
181371c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
181471c3c760a83123ee0b3127b8c65c6394ce541c50reed}
181571c3c760a83123ee0b3127b8c65c6394ce541c50reed
18168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
18178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
182028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
182149f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
182228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
182328361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
182428361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
182528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
182641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
18279881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1828fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1829fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1830fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1831fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
183278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
18368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18384e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
184141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
184241af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
18439881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
18468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
184878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
184978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1850a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1851a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1852a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1853a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1854a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1855a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1856a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
185778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
185878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
1859a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
1860a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1861fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1862a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
18638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
18648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
186578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
18664b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
18698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
18714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
187441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
18759881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
187678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
187778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
18788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
18798432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
18808432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
18818432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
18828432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
18838432808ad8898ac7137bc7ce1d9df6005e866401reed
18848432808ad8898ac7137bc7ce1d9df6005e866401reed        bounds = &paint.computeFastBounds(tmp, &storage);
188578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
18868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
18878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
18888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18894b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
189078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
18918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
18948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
189941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
19009881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
190178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
190278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
19034ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
190478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
190578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19064ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
19074ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
19084ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1909306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
191078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
191146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
191246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
191346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
191446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
191546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
191646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
19174ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
19184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
191941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
19209881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
192178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
192278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
19234ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
192478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
192578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19264ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
19274ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
19284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
19294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
19304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
19314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
19324ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1933f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
1934f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
19354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
1936f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1937f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
19384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1939f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
194078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1941f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1942f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
1943f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1944f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
1945f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1946f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
19474ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
19484ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1949ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1950ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
1951ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
1952ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    const SkRect* bounds = NULL;
1953ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
1954ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1955ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        if (this->quickReject(*bounds)) {
1956ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org            return;
1957ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        }
1958ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
195925c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1960ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
196125c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1962ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
1963ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1964ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
196525c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1966ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
1967ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
19684ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
196941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
19709881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
19719364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
19729364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
19739364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
19749364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
197578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
197678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1977fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
197878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
197978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
198078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
19828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19840b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
19850b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
19860b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
19876803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
1988fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
1989fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
1990fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
1991fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
19928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
199378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
19948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
19964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
19978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2002a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
20039881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2004a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2005a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2006a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint || paint->canComputeFastBounds()) {
2007a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (paint) {
2008a85d4d0814818e4ddabb9237da209d61d6cd5854reed            paint->computeFastBounds(bounds, &bounds);
2009a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2010a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (this->quickReject(bounds)) {
2011a85d4d0814818e4ddabb9237da209d61d6cd5854reed            return;
2012a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2013a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2014a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2015a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
2016a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint) {
2017a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2018a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2019a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2020a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds)
2021a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2022a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2023a85d4d0814818e4ddabb9237da209d61d6cd5854reed        iter.fDevice->drawImage(iter, image, x, y, looper.paint());
2024a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2025a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2026a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2027b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2028b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
202941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
203041af966ab338e95eee81ab618ab28195075338f7reed                               const SkPaint* paint) {
20319881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2032a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect storage;
2033a85d4d0814818e4ddabb9237da209d61d6cd5854reed    const SkRect* bounds = &dst;
2034a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint || paint->canComputeFastBounds()) {
2035a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (paint) {
2036a85d4d0814818e4ddabb9237da209d61d6cd5854reed            bounds = &paint->computeFastBounds(dst, &storage);
2037a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2038a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (this->quickReject(*bounds)) {
2039a85d4d0814818e4ddabb9237da209d61d6cd5854reed            return;
2040a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2041a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2042a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
2043a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint) {
2044a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2045a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2046a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2047a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
2048a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2049a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2050a85d4d0814818e4ddabb9237da209d61d6cd5854reed        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint());
2051a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2052a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2053a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2054b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2055b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
205641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
20579881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
20588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20603d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
20619efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
20629efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
20639efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
20649efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
20659efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
20669efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
20679efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
20689efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
20693b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
20708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
20718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
20728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20734b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
20758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
20769bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
20778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20799987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
20807112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2081eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2082eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      DrawBitmapRectFlags flags) {
208350b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
20848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
208674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
208778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
208878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
20893d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
20909efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
20919efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
20929efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
20933b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
20943d60812865bb034851da777a91413ab584929887reed@google.com            return;
20953d60812865bb034851da777a91413ab584929887reed@google.com        }
20968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20973d60812865bb034851da777a91413ab584929887reed@google.com
209833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
209933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
210033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
21018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21027064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
210378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
21047064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
210533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2106eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
2107f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
21087064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
210933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
211241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
211341af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint, DrawBitmapRectFlags flags) {
21149881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
21159987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2116eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
21179987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21189987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21199987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
21209987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkIRect& center, const SkRect& dst,
21219987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkPaint* paint) {
212250b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
212350b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org        return;
212450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    }
21253d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
212660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        SkRect storage;
212760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        const SkRect* bounds = &dst;
212860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
212960abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
213060abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
21313b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
21323d60812865bb034851da777a91413ab584929887reed@google.com            return;
21333d60812865bb034851da777a91413ab584929887reed@google.com        }
21343d60812865bb034851da777a91413ab584929887reed@google.com    }
21353d60812865bb034851da777a91413ab584929887reed@google.com
21369987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t w = bitmap.width();
21379987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t h = bitmap.height();
21389987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21399987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkIRect c = center;
21409987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // pin center to the bounds of the bitmap
21419987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fLeft = SkMax32(0, center.fLeft);
21429987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fTop = SkMax32(0, center.fTop);
21439987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fRight = SkPin32(center.fRight, c.fLeft, w);
21449987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
21459987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21467112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcX[4] = {
21477d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
21487112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
21497112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcY[4] = {
21507d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
21517112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
21529987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstX[4] = {
21539987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
21549987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
21559987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
21569987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstY[4] = {
21579987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
21589987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
21599987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
216074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21619987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstX[1] > dstX[2]) {
21629987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
21639987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[2] = dstX[1];
21649987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
216574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21669987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstY[1] > dstY[2]) {
21679987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
21689987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[2] = dstY[1];
21699987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
217074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21719987ec3791336bad6af5cbe513564786b2df55aareed@google.com    for (int y = 0; y < 3; y++) {
21727112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com        SkRect s, d;
21737112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com
21749987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fTop = srcY[y];
21759987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fBottom = srcY[y+1];
21769987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fTop = dstY[y];
21779987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fBottom = dstY[y+1];
21789987ec3791336bad6af5cbe513564786b2df55aareed@google.com        for (int x = 0; x < 3; x++) {
21799987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fLeft = srcX[x];
21809987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fRight = srcX[x+1];
21819987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fLeft = dstX[x];
21829987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fRight = dstX[x+1];
2183eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org            this->internalDrawBitmapRect(bitmap, &s, d, paint,
218431acc11977815402e4ef2681350f8559285bec97robertphillips@google.com                                         kNone_DrawBitmapRectFlag);
21859987ec3791336bad6af5cbe513564786b2df55aareed@google.com        }
21869987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
21879987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21889987ec3791336bad6af5cbe513564786b2df55aareed@google.com
218941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
219041af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
21919881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
21929987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
21939987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21949987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // Need a device entry-point, so gpu can use a mesh
21959987ec3791336bad6af5cbe513564786b2df55aareed@google.com    this->internalDrawBitmapNine(bitmap, center, dst, paint);
21969987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21979987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2198f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2199f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
22001f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2201112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2202112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2203a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2204112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2205f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2206f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2207f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2208f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2209f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2210f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2211f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2212f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2213f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
22142c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
22152c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2216f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2217f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
221852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
221952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
222017b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
222152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
222252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
222352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
222417b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
222552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
222652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
222752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
222852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
222952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
223052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
223152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
223252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
223352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
223452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
223552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
223652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
223752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
223852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
223952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
224052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
224252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
224352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
224552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
224652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
224752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
224852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
225052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
225152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
225252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
225352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
225452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
225552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
225652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
225752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
225852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
225952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
226052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
226152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
226252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
226352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
226452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
226552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
226652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
226752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
226852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
226952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
227052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
227152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
227252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
227352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
227452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
227552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
227652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
227752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
227852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
227952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
228052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
228152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
228252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
228352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
228452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
228552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
228652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
228752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
228852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
228952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2290e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2291e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
229278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
22938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2296f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
229752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
229852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
22998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2304e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2305e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
230605c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
230705c4a4322e7d4f3417b7df33825bab8603d52051fmalita
230878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
230987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
231205c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2313f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
23148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2315b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
23164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2319e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2320e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
232105c4a4322e7d4f3417b7df33825bab8603d52051fmalita
232205c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
232305c4a4322e7d4f3417b7df33825bab8603d52051fmalita
232478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
232587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23274e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
232805c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2329f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
23308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2331b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
23324e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2335e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2336e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
233778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
233887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
23414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
23428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2343b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2344945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
23454325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
23464325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
234700d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
234800d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
23497ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
235085d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
235185d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    const SkRect* bounds = NULL;
235219653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
235385d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
235485d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        bounds = &paint.computeFastBounds(storage, &storage);
23557ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
235685d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        if (this->quickReject(*bounds)) {
23577ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita            return;
23587ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        }
23597ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
23607ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2361024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2362024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2363024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
2364024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = NULL;
2365024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
236685d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
236700d5c2c6523321d25b32905ff4822f083a4173eefmalita
2368aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2369aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2370024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
237100d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
237200d5c2c6523321d25b32905ff4822f083a4173eefmalita
2373aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2374024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2375024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
237600d5c2c6523321d25b32905ff4822f083a4173eefmalita}
237700d5c2c6523321d25b32905ff4822f083a4173eefmalita
2378e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2379e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2380e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
23819881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2382e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2383e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2384e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2385e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
23869881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2387e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2388e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2389e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2390e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
23919881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2392e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2393e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2394e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2395e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
23969881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2397e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2398e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
239900d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
240000d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
24019881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
240249f085dddff10473b6ebf832a974288300224e60bsalomon    if (blob) {
240300d5c2c6523321d25b32905ff4822f083a4173eefmalita        this->onDrawTextBlob(blob, x, y, paint);
240400d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
240500d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2406e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
240741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
240841af966ab338e95eee81ab618ab28195075338f7reed                              const SkPoint verts[], const SkPoint texs[],
240941af966ab338e95eee81ab618ab28195075338f7reed                              const SkColor colors[], SkXfermode* xmode,
241041af966ab338e95eee81ab618ab28195075338f7reed                              const uint16_t indices[], int indexCount,
241141af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint& paint) {
24129881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
241378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
24144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
24174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
24184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
24198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2424b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2425b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
24269881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2427b3c9d1c33caf325aada244204215eb790c228c12dandov    if (NULL == cubics) {
2428b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2429b3c9d1c33caf325aada244204215eb790c228c12dandov    }
24306cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2431ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2432ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2433ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2434b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2435ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2436ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2437ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
24386cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2439b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2440b3c9d1c33caf325aada244204215eb790c228c12dandov}
2441b3c9d1c33caf325aada244204215eb790c228c12dandov
2442b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2443b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2444b3c9d1c33caf325aada244204215eb790c228c12dandov
2445ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
24466cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2447ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2448b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2449ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
24506cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2451ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2452ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2453ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
24543cb3840c9af6f70896cf5565a38d4ee03c02d767reedvoid SkCanvas::drawDrawable(SkDrawable* dr) {
24556be2aa9a251bf6022570a03140f956655b3ef1dareed    if (dr && !this->quickReject(dr->getBounds())) {
24566be2aa9a251bf6022570a03140f956655b3ef1dareed        this->onDrawDrawable(dr);
24576a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
24586a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
24596a070dc06af4e9f305f9d08a69e34d18ade473cbreed
24603cb3840c9af6f70896cf5565a38d4ee03c02d767reedvoid SkCanvas::onDrawDrawable(SkDrawable* dr) {
24616a070dc06af4e9f305f9d08a69e34d18ade473cbreed    dr->draw(this);
24626a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
24636a070dc06af4e9f305f9d08a69e34d18ade473cbreed
246471c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
246571c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkColor colors[], int count, SkXfermode::Mode mode,
246671c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
246771c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
246871c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
246971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
247071c3c760a83123ee0b3127b8c65c6394ce541c50reed
247171c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
247271c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
247371c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
247471c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
247571c3c760a83123ee0b3127b8c65c6394ce541c50reed
247671c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, NULL)
247771c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
247871c3c760a83123ee0b3127b8c65c6394ce541c50reed        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt);
247971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
248071c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
248171c3c760a83123ee0b3127b8c65c6394ce541c50reed}
248271c3c760a83123ee0b3127b8c65c6394ce541c50reed
24838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
24848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
24858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
24868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
24878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2489845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
24909881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
24918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
24928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2494845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
24950baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
24968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
24988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2500845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
25019881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
25038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2505845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
25060baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
25078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
25098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
25129881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
25138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
25144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
25168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
25178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
25209881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
25218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
25228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
25234b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
25258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
25268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
25278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
25308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
25319881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
25328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
25334b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
25358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
25368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
25378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
25408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
25418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
25429881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
25438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
25448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
25468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
25478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
25508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
25519881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
25528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
25538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
25548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
25578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
25584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
25598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
25628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
25639881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
25648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
25658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
25668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
25673b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
25688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
25698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
25708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
25724ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
25734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
25748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
25758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
25768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
25808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
25818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
25829881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
25838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
25848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
25858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
25868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
25878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
25888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
25898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
25918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
25928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
25938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
25958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
25998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
26008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
26019881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
26028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
26034b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
26058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
26068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2608f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
26091c2c441fede0ae9573afc098017011e3439624a9reed
26101c2c441fede0ae9573afc098017011e3439624a9reed/**
26111c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
26121c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
26131c2c441fede0ae9573afc098017011e3439624a9reed *
26141c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
26151c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
26161c2c441fede0ae9573afc098017011e3439624a9reed */
26171c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
26189b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2619d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
26201c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
262149f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2622d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix && matrix->isIdentity()) {
2623d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            matrix = NULL;
2624d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
26251c2c441fede0ae9573afc098017011e3439624a9reed        if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
26261c2c441fede0ae9573afc098017011e3439624a9reed            SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
26271c2c441fede0ae9573afc098017011e3439624a9reed            picture->playback(this);
26281c2c441fede0ae9573afc098017011e3439624a9reed        } else {
26291c2c441fede0ae9573afc098017011e3439624a9reed            this->onDrawPicture(picture, matrix, paint);
26301c2c441fede0ae9573afc098017011e3439624a9reed        }
2631d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2632d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
26339b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2634d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2635d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2636145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
263749f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2638145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2639145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2640d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2641145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2642145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2643145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2644145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
2645a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2646c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
26478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
26508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
26518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2653d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
26548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
26568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
26588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
26598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
26628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
26638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
26668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
26678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26691f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
26708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
26718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
26748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
26758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
26788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
26798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
26808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
26818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
26838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
26868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
26878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
268820a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
268920a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
269020a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2691c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
26923107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26933107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
26943107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26953107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
26963107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
26973107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
26983107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
26993107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
27003107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
27013107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
27023107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
27033107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
27043107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
27053107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
27063107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
270728fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
27083107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
27093107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
27103107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
27113107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
27123107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
27133107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
27143107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
27153107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
271642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
271742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
271842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
271942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2720eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
272142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
272242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
272342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
272442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
272542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
272642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2727d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2728d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2729d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2730d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2731a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2732d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2733d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2734d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
273549f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2736a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2737d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2738a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2739d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2740a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
274149f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2742d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2743d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
27446cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
274549f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2746d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2747d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2748d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2749d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2750d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2751d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2752d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2753