SkCanvas.cpp revision 884e97cb04db7ed053a866567ee9c6e4c01f993a
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"
129c39744a00573b7133fc765b0a9d50a0ceace7b8senorblanco@chromium.org#include "SkDeviceImageFilterProxy.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
143cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
175f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt#include "SkErrorInternals.h"
18b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
1974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
2045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com#include "SkPathOps.h"
21b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
230017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
2496472deea70169396b8e1f576e470138f55fdb1freed#include "SkReadPixelsRec.h"
254ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
297ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
3052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
31a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
328f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
36644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
37644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
38644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
39d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
40d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
41d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
42d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
43d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
44d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
45d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
46d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
470acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
480acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
490acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
500acf1b4b3645772d220c720313821bac389751b5reed}
510acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
520acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
530acf1b4b3645772d220c720313821bac389751b5reed}
540acf1b4b3645772d220c720313821bac389751b5reed
55da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
56da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
5715e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
812c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
822c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
8397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comvoid SkCanvas::predrawNotify() {
8497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
85c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode);
8697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
8797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
8897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
914a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
924a8126e7f81384526629b1e21bf89b632ea13cd9reed    const uint32_t propFlags = props.flags();
934a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
944a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kDither_Flag;
954a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
964a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
974a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kAntiAlias_Flag;
984a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
994a8126e7f81384526629b1e21bf89b632ea13cd9reed    return flags;
1004a8126e7f81384526629b1e21bf89b632ea13cd9reed}
1014a8126e7f81384526629b1e21bf89b632ea13cd9reed
1024a8126e7f81384526629b1e21bf89b632ea13cd9reed///////////////////////////////////////////////////////////////////////////////
1034a8126e7f81384526629b1e21bf89b632ea13cd9reed
1041f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1131f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
114045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1156f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
11661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const SkMatrix*     fMatrix;
11761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    SkMatrix            fMatrixStorage;
11861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const bool          fDeviceIsBitmapDevice;
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12096e657d0e103b8358a77ecd913f6086929f792b8reed    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
12186a17e7716c8db858e219a46b9db3817bb770beereed             bool conservativeRasterClip, bool deviceIsBitmapDevice)
122d954498c01ccf0417feacf89e45d0c62a06a813breed        : fNext(NULL)
123d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
12461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
125d954498c01ccf0417feacf89e45d0c62a06a813breed    {
126d954498c01ccf0417feacf89e45d0c62a06a813breed        if (NULL != device) {
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
12840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1304b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
13288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
13549f085dddff10473b6ebf832a974288300224e60bsalomon        if (fDevice) {
13640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com        SkDELETE(fPaint);
14088edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1414b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
142feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
143feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
144feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
145feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
146feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
147feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
148feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
150045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
1516f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
1526f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
1554b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
1644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
1714b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
173045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1764b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1773fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
1783fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
186f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1981f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
199d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2062ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    DeviceCM*       fTopLayer;
2072ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRasterClip    fRasterClip;
2082ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkMatrix        fMatrix;
2092ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int             fDeferredSaveCount;
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
211d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
212d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter     = NULL;
213d954498c01ccf0417feacf89e45d0c62a06a813breed        fLayer      = NULL;
214d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer   = NULL;
2152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
2162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
217b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
218d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
219d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
220d954498c01ccf0417feacf89e45d0c62a06a813breed    }
2212ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
222d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLayer = NULL;
224d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
2252ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
226b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
23182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDELETE(fLayer);
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
235feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
236feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
237feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
238feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
239feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
240feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
241feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
242feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
243feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2488a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
2494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
2508a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
253687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack = canvas->fClipStack;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
2558a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2574b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
266f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
267f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
270045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
271045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fBitmap = &fDevice->accessBitmap(true);
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
275f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // fCurrLayer may be NULL now
279199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2851f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
2866f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
2876f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
2916f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
303dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
304dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
305dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
306dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
307dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
308dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
309dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  colorfilter, else return NULL.
310dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
311dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkColorFilter* image_to_color_filter(const SkPaint& paint) {
312dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
313dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
314dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return NULL;
315dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
316dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
317dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* imgCF;
318dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf->asAColorFilter(&imgCF)) {
319dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return NULL;
320dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
321dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
322dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
323dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (NULL == paintCF) {
324dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
325dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
326dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
327dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
328dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
329dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
330dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
331dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
332dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
333dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3364a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
33778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
33878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   const SkRect* bounds = NULL) : fOrigPaint(paint) {
3394e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
3414a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
3424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
3435c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
3444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
346dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
347dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
348dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
349dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setColorFilter(simplifiedCF)->unref();
350dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setImageFilter(NULL);
351dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
352dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
353dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
354dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
3555c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
3565c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
3575c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
3585c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
3595c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
3605c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
3615c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
3625c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
3635c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
3645c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
3655c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
3665c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
3675c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
3685c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
3695c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
3708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
371dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setImageFilter(fPaint->getImageFilter());
372dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setXfermode(fPaint->getXfermode());
373e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org            (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
37476033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
3755c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
3765c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
3778926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
3788926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
37979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
38079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
38179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
38279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
383129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
384129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
38579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = NULL;
386129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
3875c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
389b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
3904a8126e7f81384526629b1e21bf89b632ea13cd9reed        uint32_t oldFlags = paint.getFlags();
3914a8126e7f81384526629b1e21bf89b632ea13cd9reed        fNewPaintFlags = filter_paint_flags(props, oldFlags);
3924a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (fIsSimple && (fNewPaintFlags != oldFlags)) {
393dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
3944a8126e7f81384526629b1e21bf89b632ea13cd9reed            paint->setFlags(fNewPaintFlags);
3954a8126e7f81384526629b1e21bf89b632ea13cd9reed            fPaint = paint;
3964a8126e7f81384526629b1e21bf89b632ea13cd9reed            // if we're not simple, doNext() will take care of calling setFlags()
3974a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
39974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4004e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
4015c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
4028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
4038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
40674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4074e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
4084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
4094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
4104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
41174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
412129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
413129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
414129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
415129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
416129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
417129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
418129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
419129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
420129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
421fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
42274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
424dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintInit; // base paint storage in case we need to modify it
425dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
4262c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
4272c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
4282c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
4292c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
4302c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
4314a8126e7f81384526629b1e21bf89b632ea13cd9reed    uint32_t        fNewPaintFlags;
4325c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
4332c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
434129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
43579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
43679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
437129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
438129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
441129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
442632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    fPaint = NULL;
443129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
4445c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
445632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
446dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
447dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
4484a8126e7f81384526629b1e21bf89b632ea13cd9reed    paint->setFlags(fNewPaintFlags);
4498926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
4505c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
451129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        paint->setImageFilter(NULL);
4525c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        paint->setXfermode(NULL);
453129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
4548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
45579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
456129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
457129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
458129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
459129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
460971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
461971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
462971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
463971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
46479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (NULL == fLooperContext) {
465129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
466632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
467632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
468129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
469129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
4708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
471129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
47279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
4734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
4744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
476632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
477632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
4784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fPaint = NULL;
4794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
4804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
4814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
4824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
4834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
48797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
4884a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, true);              \
4898926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
4908926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
4918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
49278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
49397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
4944a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
4954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
4974b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
4984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
502feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
503feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
504feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBounds.setEmpty();
505feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBoundsDirty = true;
506feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fClipStack->reset();
507feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
508feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
509feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
510feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
511feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
512feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
513feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
514d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
515d954498c01ccf0417feacf89e45d0c62a06a813breed    fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
516c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
517c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
5188f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
51945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
520f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
5212ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
52274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    fMetaData = NULL;
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
524687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack.reset(SkNEW(SkClipStack));
525687fa1c745febb57f42b0d5f03d7c1f4be2530careed
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
527d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
529a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
530a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
53186a17e7716c8db858e219a46b9db3817bb770beereed    new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, false);
532b679ca8926a832274b14fdb512f88f64b61d32eareed
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fSurfaceBase = NULL;
536f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
537f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
538b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        device->initForRootLayer(fProps.pixelGeometry());
5394a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (device->forceConservativeRasterClip()) {
5404a8126e7f81384526629b1e21bf89b632ea13cd9reed            fConservativeRasterClip = true;
5414a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
542f92c86642a1875da54d54b447f006cb9dfbbb35creed        device->onAttachToCanvas(this);
543f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
54478e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
545f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
546f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
549cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
550e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
5514a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
552e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
5538d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
554ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
555d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(NULL, kDefault_InitFlags);
5568d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
5578d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
558d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
559d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
560d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
561d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
562d954498c01ccf0417feacf89e45d0c62a06a813breed}
563d954498c01ccf0417feacf89e45d0c62a06a813breed
564d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
565d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
56678e276889795454891cbba48ab11927968114953reed    SkNoPixelsBitmapDevice(const SkIRect& bounds)
56778e276889795454891cbba48ab11927968114953reed        : INHERITED(make_nopixels(bounds.width(), bounds.height()))
56878e276889795454891cbba48ab11927968114953reed    {
56978e276889795454891cbba48ab11927968114953reed        this->setOrigin(bounds.x(), bounds.y());
57078e276889795454891cbba48ab11927968114953reed    }
571d954498c01ccf0417feacf89e45d0c62a06a813breed
572d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
573b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
574d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
575d954498c01ccf0417feacf89e45d0c62a06a813breed};
576d954498c01ccf0417feacf89e45d0c62a06a813breed
57796a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
578e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
57996a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
580e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
581e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
582b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
58378e276889795454891cbba48ab11927968114953reed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice,
58478e276889795454891cbba48ab11927968114953reed                          (SkIRect::MakeWH(width, height))), kDefault_InitFlags)->unref();
585d954498c01ccf0417feacf89e45d0c62a06a813breed}
586e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
58778e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
588d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
5894a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
590d954498c01ccf0417feacf89e45d0c62a06a813breed{
591d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
592b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
59378e276889795454891cbba48ab11927968114953reed    this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (bounds)), flags)->unref();
59427a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5964a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags)
59727a5e656c3d6ef22f9cb34de18e1b960da3aa241reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
5984a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfacePropsCopyOrDefault(props))
59927a5e656c3d6ef22f9cb34de18e1b960da3aa241reed{
60027a5e656c3d6ef22f9cb34de18e1b960da3aa241reed    inc_canvas();
601b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
602d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, flags);
603d954498c01ccf0417feacf89e45d0c62a06a813breed}
6046f09709519b79a1159f3826645f1c5fbc101ee11reed
605d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
606d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6074a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
608d954498c01ccf0417feacf89e45d0c62a06a813breed{
609d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
610b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
611d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6144a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
6153716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6164a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
6173716fd067a5621bb94a6cb08d72afec8bf3acedareed{
6183716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
619b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
6204a8126e7f81384526629b1e21bf89b632ea13cd9reed    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
6214a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
6224a8126e7f81384526629b1e21bf89b632ea13cd9reed}
62329c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
6244a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap)
6254a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6264a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
6274a8126e7f81384526629b1e21bf89b632ea13cd9reed{
6284a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
629b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
6304a8126e7f81384526629b1e21bf89b632ea13cd9reed    SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
6314a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
6377c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
64074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    SkDELETE(fMetaData);
641b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
65051985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
65674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
65774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
65874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    if (NULL == fMetaData) {
65974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
66074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
66174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
66274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
66374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
666bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
6671f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
668bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
669bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
670bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
671bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
672bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
6734ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
6744ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
6754ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
6764ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
6774ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
6784ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
6794ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
6804ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
6814ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
6824ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
6834ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
6841f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
685210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
686210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
687210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
6881f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
690c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6951f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
6960b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
6970b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
6980b53d59a24f667350b4282f88470713902409030reed@google.com    }
6999266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
7009266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
7019266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
702a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
703a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
704a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
705a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
706a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
707a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
708a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (NULL == bitmap->pixelRef()) {
709848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
710a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
711a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
712a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
713a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
714a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
715cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
716cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap->requestLock(&unlocker)) {
717cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
718cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
719cf01e31df6bbda270dca2ee3b4967caf51e465dcreed            return true;
720cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        }
721a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
722a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
723a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
724a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->setPixelRef(NULL);
725a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
726a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
727a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
72851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
729c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
730a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
731a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
732a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
733a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
734ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
735ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
73674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
737848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
738a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
739a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
740a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
741a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
742a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
743daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
744c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
745a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
746a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
747c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
74896472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
749a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
750a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
751a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
752a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
753a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
754f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
75596472deea70169396b8e1f576e470138f55fdb1freed    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
75696472deea70169396b8e1f576e470138f55fdb1freed    if (!rec.trim(size.width(), size.height())) {
757a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
758a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
759db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
760a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
76196472deea70169396b8e1f576e470138f55fdb1freed    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
76251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
76351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
7644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
7654cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
7664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7674cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
768cf01e31df6bbda270dca2ee3b4967caf51e465dcreed
769cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
770cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap.requestLock(&unlocker)) {
771cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
772cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
7734cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7744cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
7754cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
7764cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7774cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
7784cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
7794cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
7804cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
7814cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
7824cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
7834cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
7844cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
7854cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7864cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
7874cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7884cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7894cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7904cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
7914cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
7924cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
7934cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7944cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
7954cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
7964cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
7974cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
7984cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
7994cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8004cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8014cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
802e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
8034cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8044cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
8054cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
8064cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
8074cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8084cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
8094cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
8104cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8114cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
8124cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
8134cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
8144af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
8154af35f348b2e2f6c428819118eb7a2f2fff53a74reed    this->predrawNotify();
8164af35f348b2e2f6c428819118eb7a2f2fff53a74reed
8174cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
8184ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
8194cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
82051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8214370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
8224370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
8234370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
8244370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
8301f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
8324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (NULL == layer->fNext) {   // only one layer
834687fa1c745febb57f42b0d5f03d7c1f4be2530careed            layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL);
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
836045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
838687fa1c745febb57f42b0d5f03d7c1f4be2530careed                layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while ((layer = layer->fNext) != NULL);
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8472ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
8482ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
8492ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
8502ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8512ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
8522ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
853f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
8542ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
8552ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
8562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
8572ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
8582ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
8592ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
8602ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
8612ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
8622ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
8632ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8642ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
8652ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
8662ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
867f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
868f0090cb80ab10a49e511aa5450ae38917fa058d9reed
869f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
8702ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
8712ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
8722ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
8732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
8742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
8752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
876f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
877a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
878a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
879a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
8802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
881f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
882f0090cb80ab10a49e511aa5450ae38917fa058d9reed
883f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
8842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
8852ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
8862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
8872ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
8882ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
8892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
8902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
8912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
8922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
893a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
8942ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
8952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
8962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
897f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
898f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
899f0090cb80ab10a49e511aa5450ae38917fa058d9reed
900f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
901f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
902f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
903f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
904f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
905f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
906f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
907f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
908f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
909f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
910f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
911f0090cb80ab10a49e511aa5450ae38917fa058d9reed
9122ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
914d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
9164b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
917687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->save();
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
921b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
923b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
924b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
925b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
928a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
9299b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
930bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
931bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
932a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
933f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
934c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
93596e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
93696e657d0e103b8358a77ecd913f6086929f792b8reed
937c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
93896e657d0e103b8358a77ecd913f6086929f792b8reed        imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
939c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
940bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
94149f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
9434b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
94496e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
948bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
9499b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                fCachedLocalClipBoundsDirty = true;
9501f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
951bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
952a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
957180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
95989f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
960180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
9619b3aa54bc9605257c701cf465813f5fb1d7ba39ereed        fCachedLocalClipBoundsDirty = true;
962687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
963180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
964a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
965a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
966a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
967a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
968a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
969a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
970a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
971a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
972d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
973d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
974d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed        bounds = NULL;
975d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
976d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
977a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
97876033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy);
9792ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
980d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
981d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
9822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
983d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
984d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed        bounds = NULL;
985d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
986e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
987a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
98876033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, flags, strategy);
9892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
9908926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
9918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
9922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
99376033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                 SaveLayerStrategy strategy) {
994b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
9952a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    flags |= kClipToLayer_SaveFlag;
996b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
997b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
998a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
999a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
10002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1001a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1002a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
1003a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1004a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
1005daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
10062ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1009e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1010e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1011e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
10122ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1013e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1014e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
101576033be81b82c44fd5d4fdf2672eb22e505da1f0reed    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
10168dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
10178dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
101876033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1019daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
102076033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
10218dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1022b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1023b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
102415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
102515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1027b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    SkBaseDevice* device = this->getTopDevice();
1028b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    if (NULL == device) {
1029b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
10302ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1031b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1032b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
103361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    bool forceSpriteOnRestore = false;
103461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
1035daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
103661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo);
103761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
103861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        if (NULL == newDev) {
103961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
104061f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            newDev = SkBitmapDevice::Create(createInfo.fInfo);
104161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            if (NULL == newDev) {
104261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                SkErrorInternals::SetError(kInternalError_SkError,
104361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                           "Unable to create device for layer.");
104461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                return;
104561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            }
104661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            forceSpriteOnRestore = true;
104761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
104861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        device = newDev;
1049e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
1050e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
10516f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
105261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip,
105386a17e7716c8db858e219a46b9db3817bb770beereed                                            forceSpriteOnRestore));
10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1061d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1062d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
1063d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1064d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, NULL, flags);
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1080c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1082687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->restore();
10836c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
108488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = NULL;
10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
109849f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
11006f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
11018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
110261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                     layer->fPaint, layer->fDeviceIsBitmapDevice);
11038926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
1105b679ca8926a832274b14fdb512f88f64b61d32eareed            SkDELETE(layer);
1106b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1107b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1108a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1109b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
111188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11144a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
11154a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (NULL == props) {
11164a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
11174a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
11184a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
111976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
112076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
11214a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
112276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
11234a8126e7f81384526629b1e21bf89b632ea13cd9reed    return dev ? dev->newSurface(info, props) : NULL;
112476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
112576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1126c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1127c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1128c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1129c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1130c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1131900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1132c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1133c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1134c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1135c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1136884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1137884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onPeekPixels(&pmap)) {
1138884e97cb04db7ed053a866567ee9c6e4c01f993areed        return NULL;
1139884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1140884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1141884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1142884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1143884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1144884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1145884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1146884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.addr();
1147c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1148c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1149884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1150c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1151884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1152c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1153c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
11546b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1155884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1156884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
1157884e97cb04db7ed053a866567ee9c6e4c01f993areed        return NULL;
1158884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1159884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1160884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1161884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1162884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1163884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1164884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1165884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
11666b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
11676b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1168884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
11699c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
11709c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1171884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
11729c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1173884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
11749c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
11759c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1176c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1177c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
1178c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (NULL == fAddr) {
1179c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1180848250415eddc54075f7eb8795e8db79e749c6abreed        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
1181c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1182c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1183c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
1184c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org            return; // failure, fAddr is NULL
1185c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1186c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1187c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1188c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1189c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1190c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1191c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1192c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1193c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
119400f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1195c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1196c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1197c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1198c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1199c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1200c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1201520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
12029bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.comvoid SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkMatrix& matrix, const SkPaint* paint) {
120450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12082c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint lazy;
12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12102c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org        paint = lazy.init();
12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12129bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12139bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    SkDEBUGCODE(bitmap.validate();)
12149bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
121578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
121678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
121778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    if (paint && paint->canComputeFastBounds()) {
121878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bitmap.getBounds(&storage);
121978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        matrix.mapRect(&storage);
122078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint->computeFastBounds(storage, &storage);
122178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    }
122278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org
122378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
12249bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12259bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    while (iter.next()) {
12269bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
12279bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    }
12289bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com
12299bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    LOOPER_END
12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12321f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
123361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                  const SkPaint* paint, bool deviceIsBitmapDevice) {
12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12384b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
12398926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
12411f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
124276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
124376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
124476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
12462d97bc139a7de5813468bd3dbfd0037351ae5606fmalita            SkDeviceImageFilterProxy proxy(dstDev, fProps);
124776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
12486776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1249b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1250fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1251d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
12524cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1253be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
125455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
12554cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
12565efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
12575efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
12586776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
12596776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
126076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
126161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        } else if (deviceIsBitmapDevice) {
126261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            const SkBitmap& src = srcDev->accessBitmap(false);
126361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
126476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1265b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
126676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
127141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) {
12720acf1b4b3645772d220c720313821bac389751b5reed    if (gTreatSpriteAsBitmap) {
12730acf1b4b3645772d220c720313821bac389751b5reed        this->save();
12740acf1b4b3645772d220c720313821bac389751b5reed        this->resetMatrix();
12750acf1b4b3645772d220c720313821bac389751b5reed        this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint);
12760acf1b4b3645772d220c720313821bac389751b5reed        this->restore();
12770acf1b4b3645772d220c720313821bac389751b5reed        return;
12780acf1b4b3645772d220c720313821bac389751b5reed    }
12790acf1b4b3645772d220c720313821bac389751b5reed
12809881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()");
128150b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
12828926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
12838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
128450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
1285fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
12878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    if (NULL == paint) {
12888926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
12898926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1290fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1292fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12938926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
12948926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
12958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
12968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
12978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
12982d97bc139a7de5813468bd3dbfd0037351ae5606fmalita            SkDeviceImageFilterProxy proxy(iter.fDevice, fProps);
12998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
13006776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1301fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1302d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1303f622a6c8fd176acf9944de8df00d7f0bb56b67d3halcanary            const SkIRect clipBounds = bitmap.bounds();
1304be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
130555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
13064cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
13075efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
13085efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                tmpUnfiltered.setImageFilter(NULL);
13096776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
13105efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
13118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
13128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
13138926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
13148926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
13158926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
13168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
13178926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
13188926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
132092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1321d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1322d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1323d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
132692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1327d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1328d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1329d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
133292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1333d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1334d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1335d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
133892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1339d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1340d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1341d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
134244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
134344c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
134492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1345d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1346d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1347d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1348d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
13492ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1351c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13521f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
135344c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
135444c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
135544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
135644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
135786a17e7716c8db858e219a46b9db3817bb770beereedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
135886a17e7716c8db858e219a46b9db3817bb770beereed    this->checkForDeferredSave();
13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1360c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13611f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
136244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
13674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1374759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
13752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
13768f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
13778f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
13788f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
13798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
13808f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1381da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1382da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
13831f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1384da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1385da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1386da17f758442f16747af39f8fbaed9c097048519creed@google.com
13873b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1388da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1389c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1390da17f758442f16747af39f8fbaed9c097048519creed@google.com
1391687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
13921f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1393da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1394da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1395da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1396da17f758442f16747af39f8fbaed9c097048519creed@google.com
13975c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
13985c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1400c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14018f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
14028f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
14038f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14051f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.rectStaysRect()) {
1406123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
140798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
140898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
140998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14121f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&r, rect);
1413687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1414d954498c01ccf0417feacf89e45d0c62a06a813breed        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1416123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
141798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
141898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
141998de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
14238f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
142773e714eb766617ce06757829a3c0b345c7963faareedstatic void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
142873e714eb766617ce06757829a3c0b345c7963faareed                            SkRegion::Op op, bool doAA) {
1429d64c9487135094c83f658319f53ea2005ecc08b2reed    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1430819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1431819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1432759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
14332ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14348f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
14368f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
14378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14388f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
14394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
14408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
144114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
14428f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
144314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
14441f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
144514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
144614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
144714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
144814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
14498f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
14508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
14518f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
145214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1453687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
145414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
145514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
145614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
145714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
145873e714eb766617ce06757829a3c0b345c7963faareed        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
14598f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
146014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
146114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
146214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
146314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
146414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
14658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
14664ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
14674ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1468759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
14692ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14708f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14718f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
14728f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
14738f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
14748f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14758f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
14768f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
14778f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14788f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
14798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1480da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1481da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
14821f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1483da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1484da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1485fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
14863b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1487da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1488c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1489fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1490687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
14911f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1492da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1493da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1494da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1495da17f758442f16747af39f8fbaed9c097048519creed@google.com
14965c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14975c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
14988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1499c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15008f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
15018f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
15028f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
15051f836ee096bb988adef4b9757b2629c7afeda36dreed    path.transform(fMCRec->fMatrix, &devPath);
15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1507fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1508fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1509fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1510fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1511fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1512fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1513fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1514fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1515fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1516fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
15175c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
1518687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
15195c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
152045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
15211a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        bool clipIsAA = getClipStack()->asPath(&devPath);
15221a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        if (clipIsAA) {
15231a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita            edgeStyle = kSoft_ClipEdgeStyle;
152445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
15251a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita
152645a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
152745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
152845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
152973e714eb766617ce06757829a3c0b345c7963faareed    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
15308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1532759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
15332ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15348f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
15358f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15368f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
15385c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15395c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1541c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15435c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
15445c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1545687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevRect(rgn.getBounds(), op);
15465c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15471f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1550819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1551819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1552819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
15531f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1554ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
15555c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1556ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1557ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1558ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1559819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1560819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1561d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1562819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1563687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
15648182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
15658182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
15668182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
15678182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
15688182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
15698182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
15708182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
15728182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
15738182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
15749cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
15759cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
15769cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
157773e714eb766617ce06757829a3c0b345c7963faareed                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
15789cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
15799cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1580819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1581819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1582819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1583819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1584819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
158590c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
1586687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
15878182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
15888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
15898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    while ((element = iter.next()) != NULL) {
1590c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
159190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
159290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
159390c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
15945c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
15955c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1596754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
15971f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1598754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1599754de5f65b466f721d952a379194cc94de376f42reed@google.com
16005c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
16011f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
16025c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16035c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16043b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
16051607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1606116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1607116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
16081f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
16098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
16108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16121f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.hasPerspective()) {
1613a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
16141f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&dst, rect);
1615b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1616a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1617c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1618d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1619a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1620c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1621c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1622a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1623a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1624c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1625a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1626a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1627a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16313b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
16323b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16353b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1636bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
16378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
16388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
16398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1641d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1642d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
16431f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
164472dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
164572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
164672dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1647d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1648d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1649d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
165049f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1651bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
16523b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
16533b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1654fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
16558f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
16568f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1662bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
16631f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1664bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1665bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1666bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1667bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1668bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1669bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1670bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
167149f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1672bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1673bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1674bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1675bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1676bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
16778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
16781f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
16798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16815c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
16821f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
16835c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
16845c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
16859c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
16869c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
16879c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    return dev ? dev->accessRenderTarget() : NULL;
16889c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
16899c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1690644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1691644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1692644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
169349f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
1694644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
169549f085dddff10473b6ebf832a974288300224e60bsalomon        if (renderTarget) {
1696644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1697644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1698644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1699644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1700644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1701644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    return NULL;
1702644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1703644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1704e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1705ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1706ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
17079881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1708ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1709ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1710ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1711ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1712ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1713ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1714ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1715ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1716ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1717ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1718ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1719ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1720ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1721ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1722ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1723ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1724ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1725ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
172641af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
172741af966ab338e95eee81ab618ab28195075338f7reed
172841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
172941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
173041af966ab338e95eee81ab618ab28195075338f7reed}
173141af966ab338e95eee81ab618ab28195075338f7reed
173241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
173341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
173441af966ab338e95eee81ab618ab28195075338f7reed}
173541af966ab338e95eee81ab618ab28195075338f7reed
173641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
173741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
173841af966ab338e95eee81ab618ab28195075338f7reed}
173941af966ab338e95eee81ab618ab28195075338f7reed
174041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
174141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
174241af966ab338e95eee81ab618ab28195075338f7reed}
174341af966ab338e95eee81ab618ab28195075338f7reed
174441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
174541af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
174641af966ab338e95eee81ab618ab28195075338f7reed}
174741af966ab338e95eee81ab618ab28195075338f7reed
174841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
174941af966ab338e95eee81ab618ab28195075338f7reed                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
175041af966ab338e95eee81ab618ab28195075338f7reed                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
175141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
175241af966ab338e95eee81ab618ab28195075338f7reed                         indices, indexCount, paint);
175341af966ab338e95eee81ab618ab28195075338f7reed}
175441af966ab338e95eee81ab618ab28195075338f7reed
175541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
175641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
175741af966ab338e95eee81ab618ab28195075338f7reed}
175841af966ab338e95eee81ab618ab28195075338f7reed
1759a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1760a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
176141af966ab338e95eee81ab618ab28195075338f7reed}
176241af966ab338e95eee81ab618ab28195075338f7reed
176341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
176441af966ab338e95eee81ab618ab28195075338f7reed                             const SkPaint* paint) {
1765a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (dst.isEmpty()) {
1766a85d4d0814818e4ddabb9237da209d61d6cd5854reed        return;
1767a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
176841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawImageRect(image, src, dst, paint);
176941af966ab338e95eee81ab618ab28195075338f7reed}
177041af966ab338e95eee81ab618ab28195075338f7reed
177141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
17722df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    if (bitmap.empty()) {
17732df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
17742df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
177541af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
177641af966ab338e95eee81ab618ab28195075338f7reed}
177741af966ab338e95eee81ab618ab28195075338f7reed
177841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
177941af966ab338e95eee81ab618ab28195075338f7reed                                    const SkPaint* paint, DrawBitmapRectFlags flags) {
17802df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    if (bitmap.empty()) {
17812df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
17822df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
178341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmapRect(bitmap, src, dst, paint, flags);
178441af966ab338e95eee81ab618ab28195075338f7reed}
178541af966ab338e95eee81ab618ab28195075338f7reed
178641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
178741af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
17882df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    if (bitmap.empty()) {
17892df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
17902df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
179141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmapNine(bitmap, center, dst, paint);
179241af966ab338e95eee81ab618ab28195075338f7reed}
179341af966ab338e95eee81ab618ab28195075338f7reed
179441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
17952df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    if (bitmap.empty()) {
17962df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
17972df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
179841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawSprite(bitmap, left, top, paint);
179941af966ab338e95eee81ab618ab28195075338f7reed}
180041af966ab338e95eee81ab618ab28195075338f7reed
18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
180528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
180649f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
180728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
180828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
180928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
181028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
181141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
18129881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1813fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1814fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1815fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1816fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
181778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
182641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
182741af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
18289881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
18308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
18318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
183378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
183478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1835a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1836a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1837a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1838a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1839a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1840a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1841a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
184278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastStrokeBounds(r, &storage);
184378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
1844a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            return;
1845a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1846fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1847a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
18488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(pts != NULL);
18498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
185078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
18514b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18534e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
18548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18554b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
18564e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
185941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
18609881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
186178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
186278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
18638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
18648432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
18658432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
18668432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
18678432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
18688432808ad8898ac7137bc7ce1d9df6005e866401reed
18698432808ad8898ac7137bc7ce1d9df6005e866401reed        bounds = &paint.computeFastBounds(tmp, &storage);
187078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
187578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
18768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
18784e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
18798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
18828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
18859881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
188678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
188778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
18884ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
188978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(oval, &storage);
189078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
18914ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
18924ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
18934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1894306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
189578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
189646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
189746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
189846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
189946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
190046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
190146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
19024ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
19034ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
190441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
19059881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
190678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
190778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
19084ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
190978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
191078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19114ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com            return;
19124ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        }
19134ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
19144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
19154ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
19164ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
19174ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
1918f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
1919f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
19204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
1921f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
1922f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
19234ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
1924f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
192578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
1926f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1927f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
1928f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
1929f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
1930f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1931f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
19324ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
19334ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1934ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
1935ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
1936ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
1937ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    const SkRect* bounds = NULL;
1938ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
1939ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
1940ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        if (this->quickReject(*bounds)) {
1941ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org            return;
1942ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        }
1943ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
194425c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1945ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
194625c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1947ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
1948ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
1949ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
195025c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
1951ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
1952ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
19534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
195441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
19559881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
19569364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
19579364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
19589364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
19599364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
196078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
196178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = NULL;
1962fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
196378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
196478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        bounds = &paint.computeFastBounds(pathBounds, &storage);
196578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        if (this->quickReject(*bounds)) {
19668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
19678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
19688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19690b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
19700b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
19710b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
19726803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
1973fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
1974fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
1975fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        return;
1976fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
19778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
197878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
19798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
19814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
19828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1987a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
19889881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
1989a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
1990a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
1991a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint || paint->canComputeFastBounds()) {
1992a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (paint) {
1993a85d4d0814818e4ddabb9237da209d61d6cd5854reed            paint->computeFastBounds(bounds, &bounds);
1994a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
1995a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (this->quickReject(bounds)) {
1996a85d4d0814818e4ddabb9237da209d61d6cd5854reed            return;
1997a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
1998a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
1999a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2000a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
2001a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint) {
2002a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2003a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2004a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2005a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds)
2006a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2007a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2008a85d4d0814818e4ddabb9237da209d61d6cd5854reed        iter.fDevice->drawImage(iter, image, x, y, looper.paint());
2009a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2010a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2011a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2012b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2013b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
201441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
201541af966ab338e95eee81ab618ab28195075338f7reed                               const SkPaint* paint) {
20169881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2017a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect storage;
2018a85d4d0814818e4ddabb9237da209d61d6cd5854reed    const SkRect* bounds = &dst;
2019a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint || paint->canComputeFastBounds()) {
2020a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (paint) {
2021a85d4d0814818e4ddabb9237da209d61d6cd5854reed            bounds = &paint->computeFastBounds(dst, &storage);
2022a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2023a85d4d0814818e4ddabb9237da209d61d6cd5854reed        if (this->quickReject(*bounds)) {
2024a85d4d0814818e4ddabb9237da209d61d6cd5854reed            return;
2025a85d4d0814818e4ddabb9237da209d61d6cd5854reed        }
2026a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2027a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
2028a85d4d0814818e4ddabb9237da209d61d6cd5854reed    if (NULL == paint) {
2029a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2030a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2031a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2032a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
2033a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2034a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2035a85d4d0814818e4ddabb9237da209d61d6cd5854reed        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint());
2036a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2037a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2038a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2039b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2040b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
204141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
20429881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
20438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
20448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20453d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
20469efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkRect bounds = {
20479efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x, y,
20489efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            x + SkIntToScalar(bitmap.width()),
20499efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            y + SkIntToScalar(bitmap.height())
20509efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        };
20519efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
20529efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            (void)paint->computeFastBounds(bounds, &bounds);
20539efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
20543b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(bounds)) {
20558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
20568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
20578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20584b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
20608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(x, y);
20619bf380ce7f848dfb5886dd52b82746521454b739robertphillips@google.com    this->internalDrawBitmap(bitmap, matrix, paint);
20628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20649987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
20657112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2066eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2067eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      DrawBitmapRectFlags flags) {
206850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
20698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
20708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
207174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
207278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
207378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
20743d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
20759efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (paint) {
20769efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            bounds = &paint->computeFastBounds(dst, &storage);
20779efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        }
20783b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
20793d60812865bb034851da777a91413ab584929887reed@google.com            return;
20803d60812865bb034851da777a91413ab584929887reed@google.com        }
20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20823d60812865bb034851da777a91413ab584929887reed@google.com
208333535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
208433535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    if (NULL == paint) {
208533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
20868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20877064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
208878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
20897064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
209033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2091eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
2092f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
20937064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
209433535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
20958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
209741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
209841af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint, DrawBitmapRectFlags flags) {
20999881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
21009987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2101eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org    this->internalDrawBitmapRect(bitmap, src, dst, paint, flags);
21029987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21039987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21049987ec3791336bad6af5cbe513564786b2df55aareed@google.comvoid SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
21059987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkIRect& center, const SkRect& dst,
21069987ec3791336bad6af5cbe513564786b2df55aareed@google.com                                      const SkPaint* paint) {
210750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
210850b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org        return;
210950b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    }
21103d60812865bb034851da777a91413ab584929887reed@google.com    if (NULL == paint || paint->canComputeFastBounds()) {
211160abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        SkRect storage;
211260abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        const SkRect* bounds = &dst;
211360abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        if (paint) {
211460abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com            bounds = &paint->computeFastBounds(dst, &storage);
211560abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com        }
21163b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(*bounds)) {
21173d60812865bb034851da777a91413ab584929887reed@google.com            return;
21183d60812865bb034851da777a91413ab584929887reed@google.com        }
21193d60812865bb034851da777a91413ab584929887reed@google.com    }
21203d60812865bb034851da777a91413ab584929887reed@google.com
21219987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t w = bitmap.width();
21229987ec3791336bad6af5cbe513564786b2df55aareed@google.com    const int32_t h = bitmap.height();
21239987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21249987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkIRect c = center;
21259987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // pin center to the bounds of the bitmap
21269987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fLeft = SkMax32(0, center.fLeft);
21279987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fTop = SkMax32(0, center.fTop);
21289987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fRight = SkPin32(center.fRight, c.fLeft, w);
21299987ec3791336bad6af5cbe513564786b2df55aareed@google.com    c.fBottom = SkPin32(center.fBottom, c.fTop, h);
21309987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21317112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcX[4] = {
21327d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
21337112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
21347112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    const SkScalar srcY[4] = {
21357d474f8a84a74421bd8d119124daa64ec1710f76rmistry@google.com        0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
21367112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com    };
21379987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstX[4] = {
21389987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
21399987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
21409987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
21419987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkScalar dstY[4] = {
21429987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
21439987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
21449987ec3791336bad6af5cbe513564786b2df55aareed@google.com    };
214574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21469987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstX[1] > dstX[2]) {
21479987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
21489987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstX[2] = dstX[1];
21499987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
215074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21519987ec3791336bad6af5cbe513564786b2df55aareed@google.com    if (dstY[1] > dstY[2]) {
21529987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
21539987ec3791336bad6af5cbe513564786b2df55aareed@google.com        dstY[2] = dstY[1];
21549987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
215574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
21569987ec3791336bad6af5cbe513564786b2df55aareed@google.com    for (int y = 0; y < 3; y++) {
21577112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com        SkRect s, d;
21587112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com
21599987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fTop = srcY[y];
21609987ec3791336bad6af5cbe513564786b2df55aareed@google.com        s.fBottom = srcY[y+1];
21619987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fTop = dstY[y];
21629987ec3791336bad6af5cbe513564786b2df55aareed@google.com        d.fBottom = dstY[y+1];
21639987ec3791336bad6af5cbe513564786b2df55aareed@google.com        for (int x = 0; x < 3; x++) {
21649987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fLeft = srcX[x];
21659987ec3791336bad6af5cbe513564786b2df55aareed@google.com            s.fRight = srcX[x+1];
21669987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fLeft = dstX[x];
21679987ec3791336bad6af5cbe513564786b2df55aareed@google.com            d.fRight = dstX[x+1];
2168eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org            this->internalDrawBitmapRect(bitmap, &s, d, paint,
216931acc11977815402e4ef2681350f8559285bec97robertphillips@google.com                                         kNone_DrawBitmapRectFlag);
21709987ec3791336bad6af5cbe513564786b2df55aareed@google.com        }
21719987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
21729987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21739987ec3791336bad6af5cbe513564786b2df55aareed@google.com
217441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
217541af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
21769881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
21779987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
21789987ec3791336bad6af5cbe513564786b2df55aareed@google.com
21799987ec3791336bad6af5cbe513564786b2df55aareed@google.com    // Need a device entry-point, so gpu can use a mesh
21809987ec3791336bad6af5cbe513564786b2df55aareed@google.com    this->internalDrawBitmapNine(bitmap, center, dst, paint);
21819987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
21829987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2183f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2184f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
21851f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2186112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2187112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2188a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2189112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2190f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2191f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2192f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2193f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2194f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2195f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2196f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2197f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2198f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
21992c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
22002c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2201f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2202f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
220352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
220452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
220517b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
220652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
220752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
220852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
220917b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
221052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
221152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
221252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
221352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
221452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
221552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
221652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
221752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkASSERT(byteLength == 0 || text != NULL);
221852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
221952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
222052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (text == NULL || byteLength == 0 ||
222152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
222252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
222352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
222452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
222552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
222652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
222752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
222852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
222952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
223052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
223152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
223252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
223352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
223452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
223552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
223652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
223752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
223852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
223952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
224052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
224152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
224252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
224452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
224552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
224652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
224852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
224952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
225052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
225152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
225252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
225352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
225452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
225552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
225652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
225752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
225852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
225952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
226052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
226152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
226252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
226352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
226452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
226552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
226652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
226752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
226852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
226952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
227052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
227152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
227252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
227352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
227452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2275e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2276e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
227778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
22788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2281f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
228252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
228352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
22848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
22878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2289e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2290e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
229105c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
229205c4a4322e7d4f3417b7df33825bab8603d52051fmalita
229378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
229487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
22958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
229705c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2298f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
22998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2300b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
23014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2304e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2305e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
230605c4a4322e7d4f3417b7df33825bab8603d52051fmalita
230705c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
230805c4a4322e7d4f3417b7df33825bab8603d52051fmalita
230978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
231087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23124e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
231305c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2314f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
23158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2316b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
23174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2320e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2321e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
232278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
232387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
23248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
23264e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
23278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2328b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2329945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
23304325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
23314325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
233200d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
233300d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
23347ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
233585d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
233685d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    const SkRect* bounds = NULL;
233719653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
233885d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
233985d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        bounds = &paint.computeFastBounds(storage, &storage);
23407ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
234185d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        if (this->quickReject(*bounds)) {
23427ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita            return;
23437ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita        }
23447ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
23457ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2346024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2347024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2348024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
2349024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = NULL;
2350024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
235185d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
235200d5c2c6523321d25b32905ff4822f083a4173eefmalita
2353aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2354aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2355024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
235600d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
235700d5c2c6523321d25b32905ff4822f083a4173eefmalita
2358aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2359024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2360024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
236100d5c2c6523321d25b32905ff4822f083a4173eefmalita}
236200d5c2c6523321d25b32905ff4822f083a4173eefmalita
2363e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2364e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2365e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
23669881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2367e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2368e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2369e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2370e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
23719881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2372e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2373e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2374e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2375e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
23769881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2377e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2378e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2379e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2380e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
23819881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2382e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2383e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
238400d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
238500d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
23869881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
238749f085dddff10473b6ebf832a974288300224e60bsalomon    if (blob) {
238800d5c2c6523321d25b32905ff4822f083a4173eefmalita        this->onDrawTextBlob(blob, x, y, paint);
238900d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
239000d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2391e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
239241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
239341af966ab338e95eee81ab618ab28195075338f7reed                              const SkPoint verts[], const SkPoint texs[],
239441af966ab338e95eee81ab618ab28195075338f7reed                              const SkColor colors[], SkXfermode* xmode,
239541af966ab338e95eee81ab618ab28195075338f7reed                              const uint16_t indices[], int indexCount,
239641af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint& paint) {
23979881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
239878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
23994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
24024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
24034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
24048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2409b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2410b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
24119881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2412b3c9d1c33caf325aada244204215eb790c228c12dandov    if (NULL == cubics) {
2413b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2414b3c9d1c33caf325aada244204215eb790c228c12dandov    }
24156cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2416ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2417ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2418ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2419b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2420ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2421ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2422ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
24236cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2424b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2425b3c9d1c33caf325aada244204215eb790c228c12dandov}
2426b3c9d1c33caf325aada244204215eb790c228c12dandov
2427b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2428b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2429b3c9d1c33caf325aada244204215eb790c228c12dandov
2430ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
24316cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2432ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2433b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2434ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
24356cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2436ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2437ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2438ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
24393cb3840c9af6f70896cf5565a38d4ee03c02d767reedvoid SkCanvas::drawDrawable(SkDrawable* dr) {
24406be2aa9a251bf6022570a03140f956655b3ef1dareed    if (dr && !this->quickReject(dr->getBounds())) {
24416be2aa9a251bf6022570a03140f956655b3ef1dareed        this->onDrawDrawable(dr);
24426a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
24436a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
24446a070dc06af4e9f305f9d08a69e34d18ade473cbreed
24453cb3840c9af6f70896cf5565a38d4ee03c02d767reedvoid SkCanvas::onDrawDrawable(SkDrawable* dr) {
24466a070dc06af4e9f305f9d08a69e34d18ade473cbreed    dr->draw(this);
24476a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
24486a070dc06af4e9f305f9d08a69e34d18ade473cbreed
24498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
24508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
24518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
24528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
24538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2455845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
24569881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
24578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
24588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2460845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
24610baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
24628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
24648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2466845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
24679881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
24688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
24698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2471845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
24720baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
24738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
24758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
24789881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
24798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
24804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
24828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
24838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
24869881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
24878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
24888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
24894b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
24908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
24918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
24928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
24938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
24968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
24979881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
24988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
24994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
25018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
25038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
25068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
25078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
25089881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
25098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
25108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
25128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
25138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
25168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
25179881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
25188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
25198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
25208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
25238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
25244ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
25258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
25288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
25299881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
25308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
25318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
25328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
25333b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
25348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
25358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
25368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25374ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
25384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
25394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
25408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
25418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
25428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
25468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
25478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
25489881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
25498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
25508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
25518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
25528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
25538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
25548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
25558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
25578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
25588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
25598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
25618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
25658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
25668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
25679881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
25688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
25694b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
25718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
25728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2574f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
25751c2c441fede0ae9573afc098017011e3439624a9reed
25761c2c441fede0ae9573afc098017011e3439624a9reed/**
25771c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
25781c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
25791c2c441fede0ae9573afc098017011e3439624a9reed *
25801c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
25811c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
25821c2c441fede0ae9573afc098017011e3439624a9reed */
25831c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
25849b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2585d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
25861c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
258749f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2588d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix && matrix->isIdentity()) {
2589d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed            matrix = NULL;
2590d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
25911c2c441fede0ae9573afc098017011e3439624a9reed        if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
25921c2c441fede0ae9573afc098017011e3439624a9reed            SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
25931c2c441fede0ae9573afc098017011e3439624a9reed            picture->playback(this);
25941c2c441fede0ae9573afc098017011e3439624a9reed        } else {
25951c2c441fede0ae9573afc098017011e3439624a9reed            this->onDrawPicture(picture, matrix, paint);
25961c2c441fede0ae9573afc098017011e3439624a9reed        }
2597d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2598d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
25999b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2600d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2601d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2602145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
260349f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2604145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2605145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2606d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2607145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2608145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2609145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2610145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
2611a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2612c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
26138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
26168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
26178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2619d642329293cce602ac24df8f585c14a98795da87reed@google.com    SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
26208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
26228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
26248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
26258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
26288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
26298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
26328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
26338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26351f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
26368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
26378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
26408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
26418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
26448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
26458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == paint) {
26468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
26478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
26498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
26528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
26538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
265420a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
265520a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
265620a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2657c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
26583107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26593107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
26603107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26613107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
26623107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
26633107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
26643107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
26653107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
26663107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
26673107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
26683107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
26693107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26703107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
26713107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
26723107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
267328fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
26743107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
26753107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
26763107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
26773107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
26783107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
26793107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
26803107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
26813107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
268242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
268342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
268442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
268542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2686eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
268742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
268842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
268942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org        return NULL;
269042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
269142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    return SkNEW_ARGS(SkCanvas, (bitmap));
269242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2693d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2694d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2695d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2696d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2697a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2698d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2699d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2700d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
270149f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2702a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2703d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2704a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2705d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2706a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
270749f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2708d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2709d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
27106cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
271149f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2712d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2713d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2714d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2715d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2716d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2717d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2718d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2719