SkCanvas.cpp revision 53d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896c
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
8d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkBitmapDevice.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
10d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
11d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkClipStack.h"
12dbc3cefb0b624808ddb86d444e6103f216e12fa5reed#include "SkColorFilter.h"
13d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkDevice.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
153cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
185f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt#include "SkErrorInternals.h"
19b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
20262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkImage_Base.h"
21262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkMatrixUtils.h"
2274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
234c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkNinePatchIter.h"
24c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
25b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
270017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
2896472deea70169396b8e1f576e470138f55fdb1freed#include "SkReadPixelsRec.h"
294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
3079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
3197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
327ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
3352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
34a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
358f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
36d3ebb48320cf1b7e969974673e4bd7743816985ebungeman
37d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include <new>
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
39644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
407354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#include "GrContext.h"
41644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
427354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#include "SkGr.h"
43644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
44644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
45e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed#define RETURN_ON_NULL(ptr)     do { if (nullptr == (ptr)) return; } while (0)
46e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
47c83a29759a5c2966da5ab973e4fd90763e4c962breed/*
48c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Return true if the drawing this rect would hit every pixels in the canvas.
49c83a29759a5c2966da5ab973e4fd90763e4c962breed *
50c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Returns false if
51c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - rect does not contain the canvas' bounds
52c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint is not fill
53c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint would blur or otherwise change the coverage of the rect
54c83a29759a5c2966da5ab973e4fd90763e4c962breed */
55c83a29759a5c2966da5ab973e4fd90763e4c962breedbool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
56c83a29759a5c2966da5ab973e4fd90763e4c962breed                                           ShaderOverrideOpacity overrideOpacity) const {
5799fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
5899fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNone_ShaderOverrideOpacity,
5999fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums0");
6099fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
6199fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kOpaque_ShaderOverrideOpacity,
6299fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums1");
6399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
6499fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNotOpaque_ShaderOverrideOpacity,
6599fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums2");
66c83a29759a5c2966da5ab973e4fd90763e4c962breed
67c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkISize size = this->getBaseLayerSize();
68c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
69c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (!this->getClipStack()->quickContains(bounds)) {
70c83a29759a5c2966da5ab973e4fd90763e4c962breed        return false;
71c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
72c83a29759a5c2966da5ab973e4fd90763e4c962breed
73c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (rect) {
74c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!this->getTotalMatrix().rectStaysRect()) {
75c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
76c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
77c83a29759a5c2966da5ab973e4fd90763e4c962breed
78c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkRect devRect;
79c83a29759a5c2966da5ab973e4fd90763e4c962breed        this->getTotalMatrix().mapRect(&devRect, *rect);
808c0144ccb17220db9d5140ef5ee85d5bc7837513fmalita        if (!devRect.contains(bounds)) {
81c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
82c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
83c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
84c83a29759a5c2966da5ab973e4fd90763e4c962breed
85c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (paint) {
86c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkPaint::Style paintStyle = paint->getStyle();
87c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!(paintStyle == SkPaint::kFill_Style ||
88c83a29759a5c2966da5ab973e4fd90763e4c962breed              paintStyle == SkPaint::kStrokeAndFill_Style)) {
89c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
90c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
91c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (paint->getMaskFilter() || paint->getLooper()
92c83a29759a5c2966da5ab973e4fd90763e4c962breed            || paint->getPathEffect() || paint->getImageFilter()) {
93c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
94c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
95c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
96c83a29759a5c2966da5ab973e4fd90763e4c962breed    return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
97c83a29759a5c2966da5ab973e4fd90763e4c962breed}
98c83a29759a5c2966da5ab973e4fd90763e4c962breed
99c83a29759a5c2966da5ab973e4fd90763e4c962breed///////////////////////////////////////////////////////////////////////////////////////////////////
100c83a29759a5c2966da5ab973e4fd90763e4c962breed
101d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
102d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
103d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
104d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
105d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
106d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
107d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
108d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
1090acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
1100acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
1110acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
1120acf1b4b3645772d220c720313821bac389751b5reed}
1130acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
1140acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
1150acf1b4b3645772d220c720313821bac389751b5reed}
1160acf1b4b3645772d220c720313821bac389751b5reed
117da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
118da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1422c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
1432c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
144c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(bool willOverwritesEntireSurface) {
14597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
146c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
147c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  ? SkSurface::kDiscard_ContentChangeMode
148c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  : SkSurface::kRetain_ContentChangeMode);
149c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
150c83a29759a5c2966da5ab973e4fd90763e4c962breed}
151c83a29759a5c2966da5ab973e4fd90763e4c962breed
152c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
153c83a29759a5c2966da5ab973e4fd90763e4c962breed                             ShaderOverrideOpacity overrideOpacity) {
154c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (fSurfaceBase) {
155c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode;
156c83a29759a5c2966da5ab973e4fd90763e4c962breed        // Since willOverwriteAllPixels() may not be complete free to call, we only do so if
157c83a29759a5c2966da5ab973e4fd90763e4c962breed        // there is an outstanding snapshot, since w/o that, there will be no copy-on-write
158c83a29759a5c2966da5ab973e4fd90763e4c962breed        // and therefore we don't care which mode we're in.
159c83a29759a5c2966da5ab973e4fd90763e4c962breed        //
160c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (fSurfaceBase->outstandingImageSnapshot()) {
161c83a29759a5c2966da5ab973e4fd90763e4c962breed            if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) {
162c83a29759a5c2966da5ab973e4fd90763e4c962breed                mode = SkSurface::kDiscard_ContentChangeMode;
163c83a29759a5c2966da5ab973e4fd90763e4c962breed            }
164c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
165c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(mode);
16697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
16797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
16897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1714a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
1724a8126e7f81384526629b1e21bf89b632ea13cd9reed    const uint32_t propFlags = props.flags();
1734a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
1744a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kDither_Flag;
1754a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
1764a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
1774a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kAntiAlias_Flag;
1784a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
1794a8126e7f81384526629b1e21bf89b632ea13cd9reed    return flags;
1804a8126e7f81384526629b1e21bf89b632ea13cd9reed}
1814a8126e7f81384526629b1e21bf89b632ea13cd9reed
1824a8126e7f81384526629b1e21bf89b632ea13cd9reed///////////////////////////////////////////////////////////////////////////////
1834a8126e7f81384526629b1e21bf89b632ea13cd9reed
1841f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1931f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1956f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
19661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const SkMatrix*     fMatrix;
19761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    SkMatrix            fMatrixStorage;
19861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const bool          fDeviceIsBitmapDevice;
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20096e657d0e103b8358a77ecd913f6086929f792b8reed    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
20186a17e7716c8db858e219a46b9db3817bb770beereed             bool conservativeRasterClip, bool deviceIsBitmapDevice)
20296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        : fNext(nullptr)
203d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
20461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
205d954498c01ccf0417feacf89e45d0c62a06a813breed    {
20696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr != device) {
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
20840a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2104b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
21196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = paint ? new SkPaint(*paint) : nullptr;
21288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
21549f085dddff10473b6ebf832a974288300224e60bsalomon        if (fDevice) {
21640a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
219385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fPaint;
22088edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2214b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
222feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
223feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
224feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
225feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
226feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
227feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
228feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
229045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
230045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
2316f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
2326f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
2354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
2444b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
2514b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
253045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2564b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2573fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
2583fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
266f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2781f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
279d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    DeviceCM*       fTopLayer;
2872ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRasterClip    fRasterClip;
2882ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkMatrix        fMatrix;
2892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int             fDeferredSaveCount;
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
291d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
29296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fFilter     = nullptr;
29396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer      = nullptr;
29496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fTopLayer   = nullptr;
2952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
2962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
297b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
298d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
299d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
300d954498c01ccf0417feacf89e45d0c62a06a813breed    }
3012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
302d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
30396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer = nullptr;
304d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
3052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
306b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
31182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
312385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fLayer;
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
315feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
316feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
317feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
318feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
319feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
320feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
321feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
322feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
323feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3288a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
3294370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
3308a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
333687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack = canvas->fClipStack;
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
3358a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
346f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
347f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
350045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
351045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
35341e010cb901c0da9066c4df562030808c9ccd7f8reed            if (!fDevice->accessPixels(&fDst)) {
35496fcdcc219d2a0d3579719b84b28bede76efba64halcanary                fDst.reset(fDevice->imageInfo(), nullptr, 0);
35541e010cb901c0da9066c4df562030808c9ccd7f8reed            }
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
357f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
36096fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // fCurrLayer may be nullptr now
361199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3664b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3671f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
3686f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3696f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3736f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
385dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
386dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
387dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
388dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
389dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
390dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
39196fcdcc219d2a0d3579719b84b28bede76efba64halcanary *  colorfilter, else return nullptr.
392dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
393dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkColorFilter* image_to_color_filter(const SkPaint& paint) {
394dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
395dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
39696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
397dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
398dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
399dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* imgCF;
400dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf->asAColorFilter(&imgCF)) {
40196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
402dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
403dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
404dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
40596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paintCF) {
406dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
407dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
408dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
409dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
410dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
411dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
412dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
413dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
414dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
415dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
41687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco/**
41787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * There are many bounds in skia. A circle's bounds is just its center extended by its radius.
41887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * However, if we stroke a circle, then the "bounds" of that is larger, since it will now draw
41987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * outside of its raw-bounds by 1/2 the stroke width.  SkPaint has lots of optional
42087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * effects/attributes that can modify the effective bounds of a given primitive -- maskfilters,
42187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * patheffects, stroking, etc.  This function takes a raw bounds and a paint, and returns the
42287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * conservative "effective" bounds based on the settings in the paint... with one exception. This
42387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * function does *not* look at the imagefilter, which can also modify the effective bounds. It is
42487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * deliberately ignored.
42587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco */
42687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblancostatic const SkRect& apply_paint_to_bounds_sans_imagefilter(const SkPaint& paint,
42787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            const SkRect& rawBounds,
42887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            SkRect* storage) {
42987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    SkPaint tmpUnfiltered(paint);
43087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    tmpUnfiltered.setImageFilter(nullptr);
43187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    if (tmpUnfiltered.canComputeFastBounds()) {
43287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return tmpUnfiltered.computeFastBounds(rawBounds, storage);
43387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    } else {
43487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return rawBounds;
43587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    }
43687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco}
43787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
44087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the
44187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // paint. It's used to determine the size of the offscreen layer for filters.
44287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // If null, the clip will be used instead.
4434a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
44478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
44587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                   const SkRect* rawBounds = nullptr) : fOrigPaint(paint) {
4464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
44753d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
4497765000709dc64eb23be7df47d1f995d1f787115fmalita#else
4507765000709dc64eb23be7df47d1f995d1f787115fmalita        fFilter = nullptr;
4517765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
4524a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
4534e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
4545c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
4554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
457dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
458dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
459dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
460dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setColorFilter(simplifiedCF)->unref();
46196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            paint->setImageFilter(nullptr);
462dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
463dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
464dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
465dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
4665c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
4675c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
4685c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
4695c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
4705c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
4715c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
4725c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
4735c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
4745c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
4755c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
4765c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
4775c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
4785c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
4795c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
4805c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
4818926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
482dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setImageFilter(fPaint->getImageFilter());
483dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setXfermode(fPaint->getXfermode());
48487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            SkRect storage;
48587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            if (rawBounds) {
48687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                // Make rawBounds include all paint outsets except for those due to image filters.
48787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage);
48887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            }
489bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed            (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp),
49076033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
4915c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
4925c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
4938926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4948926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
49579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
49679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
49779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
49879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
499129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
500129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
50196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fLooperContext = nullptr;
502129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
5035c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
505b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
5064a8126e7f81384526629b1e21bf89b632ea13cd9reed        uint32_t oldFlags = paint.getFlags();
5074a8126e7f81384526629b1e21bf89b632ea13cd9reed        fNewPaintFlags = filter_paint_flags(props, oldFlags);
5084a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (fIsSimple && (fNewPaintFlags != oldFlags)) {
509dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
5104a8126e7f81384526629b1e21bf89b632ea13cd9reed            paint->setFlags(fNewPaintFlags);
5114a8126e7f81384526629b1e21bf89b632ea13cd9reed            fPaint = paint;
5124a8126e7f81384526629b1e21bf89b632ea13cd9reed            // if we're not simple, doNext() will take care of calling setFlags()
5134a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
51574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
5175c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
5188926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
5198926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
5204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
52274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
5244e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
5254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
5264e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
52774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
528129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
529129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
530129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
531129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
532129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
533129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
534129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
535129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
536129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
537fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
53874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
540dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintInit; // base paint storage in case we need to modify it
541dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
5422c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
5432c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
5442c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
5452c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
5462c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
5474a8126e7f81384526629b1e21bf89b632ea13cd9reed    uint32_t        fNewPaintFlags;
5485c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
5492c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
550129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
55179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
55279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
553129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
554129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
557129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
55896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fPaint = nullptr;
559129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5605c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
561632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
562dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
563dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5644a8126e7f81384526629b1e21bf89b632ea13cd9reed    paint->setFlags(fNewPaintFlags);
5658926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5665c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
56796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setImageFilter(nullptr);
56896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setXfermode(nullptr);
569129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5708926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
57179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
572129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
573129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
574129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
575129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
576971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
577971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
578971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
579971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
58096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fLooperContext) {
581129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
582632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
583632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
584129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
585129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
5868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
587129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
58879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
5894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
5904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
592632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
593632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
59496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = nullptr;
5954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
5964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5974e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
5984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
5994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
602262a71b7f95ce98ff3dd8dba845afbd724470903reed#define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds)          \
603262a71b7f95ce98ff3dd8dba845afbd724470903reed    this->predrawNotify();                                                  \
604262a71b7f95ce98ff3dd8dba845afbd724470903reed    AutoDrawLooper looper(this, fProps, paint, skipLayerForFilter, bounds); \
605262a71b7f95ce98ff3dd8dba845afbd724470903reed    while (looper.next(SkDrawFilter::kBitmap_Type)) {                       \
606262a71b7f95ce98ff3dd8dba845afbd724470903reed        SkDrawIter iter(this);
607262a71b7f95ce98ff3dd8dba845afbd724470903reed
608262a71b7f95ce98ff3dd8dba845afbd724470903reed
6098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
61097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
6114a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, true);              \
6128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
6138926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
6148926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
61578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
61697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
6174a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
6184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
6204b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
621c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
622c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
623c83a29759a5c2966da5ab973e4fd90763e4c962breed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
624c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
625c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
626c83a29759a5c2966da5ab973e4fd90763e4c962breed
6274e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
631feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
632feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
633feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBounds.setEmpty();
634feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBoundsDirty = true;
635feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fClipStack->reset();
636feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
637feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
638feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
639feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
640feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
641feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
642feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
643d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
64442b73eb00367c8315974b1c374308d20efa78897reed    if (device && device->forceConservativeRasterClip()) {
64542b73eb00367c8315974b1c374308d20efa78897reed        flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
64642b73eb00367c8315974b1c374308d20efa78897reed    }
64742b73eb00367c8315974b1c374308d20efa78897reed    // Since init() is only called once by our constructors, it is safe to perform this
64842b73eb00367c8315974b1c374308d20efa78897reed    // const-cast.
64942b73eb00367c8315974b1c374308d20efa78897reed    *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativeRasterClip_InitFlag);
65042b73eb00367c8315974b1c374308d20efa78897reed
651c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
652c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
6538f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
65445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
655f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
6562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
65796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMetaData = nullptr;
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
659385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    fClipStack.reset(new SkClipStack);
660687fa1c745febb57f42b0d5f03d7c1f4be2530careed
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
662d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
664a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
665a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
66696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip, false);
667b679ca8926a832274b14fdb512f88f64b61d32eareed
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fSurfaceBase = nullptr;
671f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
672f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
673efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
674efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
675f92c86642a1875da54d54b447f006cb9dfbbb35creed        device->onAttachToCanvas(this);
676f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
67778e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
678f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
679f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
682cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
683e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6844a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
68542b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
686e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
6878d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
688ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
68996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    this->init(nullptr, kDefault_InitFlags);
6908d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
6918d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
692d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
693d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
694d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
695d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
696d954498c01ccf0417feacf89e45d0c62a06a813breed}
697d954498c01ccf0417feacf89e45d0c62a06a813breed
698d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
699d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
700fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps)
701fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips        : INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps)
70278e276889795454891cbba48ab11927968114953reed    {
70378e276889795454891cbba48ab11927968114953reed        this->setOrigin(bounds.x(), bounds.y());
70478e276889795454891cbba48ab11927968114953reed    }
705d954498c01ccf0417feacf89e45d0c62a06a813breed
706d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
707b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
708d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
709d954498c01ccf0417feacf89e45d0c62a06a813breed};
710d954498c01ccf0417feacf89e45d0c62a06a813breed
71196a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
712e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
71396a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
71442b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
715e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
716e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
717b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
718385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    this->init(new SkNoPixelsBitmapDevice(SkIRect::MakeWH(width, height), fProps),
719385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary               kDefault_InitFlags)->unref();
720d954498c01ccf0417feacf89e45d0c62a06a813breed}
721e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
72278e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
723d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7244a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
72542b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
726d954498c01ccf0417feacf89e45d0c62a06a813breed{
727d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
728b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
729385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    this->init(new SkNoPixelsBitmapDevice(bounds, fProps), flags)->unref();
73027a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
732d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
733d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7347b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
73542b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
736d954498c01ccf0417feacf89e45d0c62a06a813breed{
737d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
738b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
739d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
742fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
743fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7447b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
74542b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
746fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
747fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
748fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
749fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
750fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
751fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
7524a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
7533716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7544a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
75542b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
7563716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7573716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
758b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
759385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
7604a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7614a8126e7f81384526629b1e21bf89b632ea13cd9reed}
76229c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
7634a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap)
7644a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7654a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
76642b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
7674a8126e7f81384526629b1e21bf89b632ea13cd9reed{
7684a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
769b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
770385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
7714a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
7777c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
780385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete fMetaData;
781b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
78553d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
79151985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7957765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
79774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
79874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
79974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
80096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fMetaData) {
80174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
80274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
80374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
80474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
80574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
808bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
8091f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
810bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
811bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
812bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
813bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
814bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
8154ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
8164ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
8174ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
8184ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
8194ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
8204ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
8214ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
8224ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
8234ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
8244ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
8254ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
8261f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
827210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
828210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
829210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
8301f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
832c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8371f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
8380b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
8390b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
8400b53d59a24f667350b4282f88470713902409030reed@google.com    }
8419266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
8429266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
8439266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
844a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
845a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
846a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
847a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
848a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
849a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
85096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == bitmap->pixelRef()) {
851848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
852a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
853a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
854a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
855a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
856a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
857cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
858cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap->requestLock(&unlocker)) {
859cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
860cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
861cf01e31df6bbda270dca2ee3b4967caf51e465dcreed            return true;
862cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        }
863a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
864a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
865a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
86696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        bitmap->setPixelRef(nullptr);
867a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
868a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
869a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
87051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
871c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
872a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
873a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
874a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
875a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
876ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
877ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
87874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
879848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
880a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
881a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
882a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
883a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
884a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
885daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
886c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
887a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
888a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
889c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
89096472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
891a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
892a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
893a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
894a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
895a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
896f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
89796472deea70169396b8e1f576e470138f55fdb1freed    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
89896472deea70169396b8e1f576e470138f55fdb1freed    if (!rec.trim(size.width(), size.height())) {
899a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
900a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
901db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
902a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
90396472deea70169396b8e1f576e470138f55fdb1freed    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
90451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
90551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9064cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
9074cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
9084cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9094cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
910cf01e31df6bbda270dca2ee3b4967caf51e465dcreed
911cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
912cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap.requestLock(&unlocker)) {
913cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
914cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
9154cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9164cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
9174cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
9184cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9194cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
9204cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
9214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
9224cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
9234cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
9244cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
9254cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
9264cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
9274cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
92896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == pixels || rowBytes < origInfo.minRowBytes()) {
9294cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9304cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9314cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9324cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
9334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
9344cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
9354cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9364cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9374cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
9394cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
9404cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9414cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9424cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9434cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
944e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
9454cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
9474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
9484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
9494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
9514cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
9524cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9534cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
9544cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
9554cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9564af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
957c83a29759a5c2966da5ab973e4fd90763e4c962breed    const bool completeOverwrite = info.dimensions() == size;
958c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
9594af35f348b2e2f6c428819118eb7a2f2fff53a74reed
9604cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
9614ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
9624cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
96351df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9644370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
9654370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
9664370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9674370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
9731f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
9754b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
97696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == layer->fNext) {   // only one layer
97796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            layer->updateMC(totalMatrix, totalClip, *fClipStack, nullptr);
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
979045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
981687fa1c745febb57f42b0d5f03d7c1f4be2530careed                layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
98296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            } while ((layer = layer->fNext) != nullptr);
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
9912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
9932ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
9942ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
996f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
9972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
9982ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
9992ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
10002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
10012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
10022ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
10032ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
10042ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
10052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
10062ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
10072ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
10082ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
10092ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
1010f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1011f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1012f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
10132ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
10142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
10152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
10162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
10172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
10182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
1019f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
1020a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
1021a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
1022a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
10232ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1024f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1025f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1026f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
10272ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
10282ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
10292ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
10302ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
10312ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
10322ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
10332ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
10342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
10352ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
1036a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
10372ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
10382ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
10392ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
1040f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1041f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1042f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1043f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
1044f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
1045f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
1046f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
1047f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1048f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
1049f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
1050f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
1051f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
1052f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1053f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1054f0090cb80ab10a49e511aa5450ae38917fa058d9reed
10552ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
1057d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
10594b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1060687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->save();
10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10634960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
1064b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
10654960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag);
1066b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
1067b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
1068b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10714960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
10729b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
1073bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
1074bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
1075a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
1076f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1077c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
107896e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
107996e657d0e103b8358a77ecd913f6086929f792b8reed
1080c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
108196e657d0e103b8358a77ecd913f6086929f792b8reed        imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
1082db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        if (bounds && !imageFilter->canComputeFastBounds()) {
1083db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco            bounds = nullptr;
1084db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        }
1085c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
1086bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
108749f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
10894b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
109096e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
10944960eeec4a1f2a772654883d7f3615d47bcd5dc3reed            if (BoundsAffectsClip(saveLayerFlags)) {
10959b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                fCachedLocalClipBoundsDirty = true;
10961f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
1097bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
1098a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1103180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11054960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (BoundsAffectsClip(saveLayerFlags)) {
1106180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
11079b3aa54bc9605257c701cf465813f5fb1d7ba39ereed        fCachedLocalClipBoundsDirty = true;
1108687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
1109180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
1110a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1111a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1112a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
1113a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
1114a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1115a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
1116a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
1117a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1118bada1885da479d948f065182d6dfa85a1140bda5reed#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
11194960eeec4a1f2a772654883d7f3615d47bcd5dc3reeduint32_t SkCanvas::SaveFlagsToSaveLayerFlags(SaveFlags flags) {
11204960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    uint32_t layerFlags = 0;
11214960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11224960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (0 == (flags & kClipToLayer_SaveFlag)) {
11234960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        layerFlags |= kDontClipToLayer_PrivateSaveLayerFlag;
1124d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
11254960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (0 == (flags & kHasAlphaLayer_SaveFlag)) {
11264960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        layerFlags |= kIsOpaque_SaveLayerFlag;
11274960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    }
11284960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return layerFlags;
11294960eeec4a1f2a772654883d7f3615d47bcd5dc3reed}
1130ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo
1131ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggouint32_t SkCanvas::SaveLayerFlagsToSaveFlags(SaveLayerFlags layerFlags) {
1132ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo    uint32_t saveFlags = 0;
1133ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo
1134ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo    if (0 == (layerFlags & kDontClipToLayer_PrivateSaveLayerFlag)) {
1135ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo        saveFlags |= kClipToLayer_SaveFlag;
1136ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo    }
1137ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo    if (0 == (layerFlags & kIsOpaque_SaveLayerFlag)) {
1138ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo        saveFlags |= kHasAlphaLayer_SaveFlag;
1139ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo    }
1140ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo    return saveFlags;
1141ffe031e65cda3f52e057dd7aafbc9407c25cbf8dscroggo}
1142bada1885da479d948f065182d6dfa85a1140bda5reed#endif
11434960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11444960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
11454960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, 0));
1146d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1147d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
1148bada1885da479d948f065182d6dfa85a1140bda5reed#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
11492ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
11504960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, SaveFlagsToSaveLayerFlags(flags)));
11514960eeec4a1f2a772654883d7f3615d47bcd5dc3reed}
1152bada1885da479d948f065182d6dfa85a1140bda5reed#endif
11534960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11544960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) {
11554960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag));
11564960eeec4a1f2a772654883d7f3615d47bcd5dc3reed}
11574960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11584960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SaveLayerRec& origRec) {
11594960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerRec rec(origRec);
1160d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
11614960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        rec.fBounds = nullptr;
1162d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
11634960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec);
1164a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
11654960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    this->internalSaveLayer(rec, strategy);
11662ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
11678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
11688926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
1169bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areedstatic void draw_filter_into_device(SkBaseDevice* src, const SkImageFilter* filter,
1170bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed                                    SkBaseDevice* dst, const SkMatrix& ctm) {
11717354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
11727354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    SkBitmap srcBM;
11737354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
11747354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#if SK_SUPPORT_GPU
11757354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    GrRenderTarget* srcRT = src->accessRenderTarget();
11767354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    if (srcRT && !srcRT->asTexture() && dst->accessRenderTarget()) {
11777354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        // When both the src & the dst are on the gpu but the src doesn't have a texture,
11787354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        // we create a temporary texture for the draw.
11797354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        // TODO: we should actually only copy the portion of the source needed to apply the image
11807354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        // filter
11817354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        GrContext* context = srcRT->getContext();
11827354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        SkAutoTUnref<GrTexture> tex(context->textureProvider()->createTexture(srcRT->desc(), true));
11837354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
11847354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        context->copySurface(tex, srcRT);
11857354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
11867354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        GrWrapTextureInBitmap(tex, src->width(), src->height(), src->isOpaque(), &srcBM);
11877354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    } else
11887354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#endif
11897354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    {
11907354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips        srcBM = src->accessBitmap(false);
11917354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    }
11927354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
11937354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    SkCanvas c(dst);
11947354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
1195bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    SkAutoTUnref<SkImageFilter> localF(filter->newWithLocalMatrix(ctm));
11967354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    SkPaint p;
1197bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    p.setImageFilter(localF);
1198bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    const SkScalar x = SkIntToScalar(src->getOrigin().x());
1199bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    const SkScalar y = SkIntToScalar(src->getOrigin().y());
1200bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    c.drawBitmap(srcBM, x, y, &p);
12017354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips}
120270ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed
12034960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
12044960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkRect* bounds = rec.fBounds;
12054960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkPaint* paint = rec.fPaint;
12064960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
12074960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
1208b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
12094960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag;
1210b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
1211b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
1212a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1213a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
12142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1215a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1216a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
1217a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1218a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
12194960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, paint ? paint->getImageFilter() : nullptr)) {
12202ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1223e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1224e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1225e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
12262ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1227e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1228e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
12294960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
12308dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
12318dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
123276033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1233daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
123476033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
12358dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1236b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1237b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
123815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
123915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1241b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    SkBaseDevice* device = this->getTopDevice();
124296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == device) {
1243b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
12442ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1245b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1246b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
124761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    bool forceSpriteOnRestore = false;
124861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
124970ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
12504960eeec4a1f2a772654883d7f3615d47bcd5dc3reed                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1251daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
125270ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
125370ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed                                                                            preserveLCDText, false);
125461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
125596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == newDev) {
125661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
12579a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry);
12589a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            newDev = SkBitmapDevice::Create(createInfo.fInfo, surfaceProps);
125996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (nullptr == newDev) {
126061f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                SkErrorInternals::SetError(kInternalError_SkError,
126161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                           "Unable to create device for layer.");
126261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                return;
126361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            }
126461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            forceSpriteOnRestore = true;
126561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
126661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        device = newDev;
1267e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
12686f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
12697354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
1270bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed    if (rec.fBackdrop) {
1271bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed        draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, device, fMCRec->fMatrix);
12727354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    }
12737354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
1274385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    DeviceCM* layer =
1275385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            new DeviceCM(device, paint, this, fConservativeRasterClip, forceSpriteOnRestore);
12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1283d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1284bada1885da479d948f065182d6dfa85a1140bda5reed    if (0xFF == alpha) {
1285bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, nullptr);
1286bada1885da479d948f065182d6dfa85a1140bda5reed    } else {
1287bada1885da479d948f065182d6dfa85a1140bda5reed        SkPaint tmpPaint;
1288bada1885da479d948f065182d6dfa85a1140bda5reed        tmpPaint.setAlpha(alpha);
1289bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, &tmpPaint);
1290bada1885da479d948f065182d6dfa85a1140bda5reed    }
1291d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1292d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
1293bada1885da479d948f065182d6dfa85a1140bda5reed#ifdef SK_SUPPORT_LEGACY_SAVEFLAGS
12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
129796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return this->saveLayer(bounds, nullptr, flags);
12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1304bada1885da479d948f065182d6dfa85a1140bda5reed#endif
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1310c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1312687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->restore();
13136c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
131488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
131796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fLayer = nullptr;
13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
132849f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
13306f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
13318926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
133261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                     layer->fPaint, layer->fDeviceIsBitmapDevice);
13338926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
1335385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete layer;
1336b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1337b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1338a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1339b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
134188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13444a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
134596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == props) {
13464a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
13474a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
13484a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
134976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
135076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
13514a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
135276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
135396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return dev ? dev->newSurface(info, props) : nullptr;
135476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
135576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1356c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1357c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1358c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1359c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1360c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1361900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1362c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1363c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1364c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1365c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1366884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1367884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onPeekPixels(&pmap)) {
136896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1369884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1370884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1371884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1372884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1373884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1374884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1375884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1376884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.addr();
1377c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1378c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1379884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1380c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1381884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1382c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1383c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
13846b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1385884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1386884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
138796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1388884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1389884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1390884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1391884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1392884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1393884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1394884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1395884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
13966b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
13976b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1398884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
13999c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
14009c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1401884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
14029c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1403884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
14049c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
14059c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1406520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14081f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
140961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                  const SkPaint* paint, bool deviceIsBitmapDevice) {
14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
141196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14144b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14158926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
14171f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
141876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
141976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
142076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
14218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
142288d064d0e481949184305c7b1d6b282dddffac39reed            SkImageFilter::DeviceProxy proxy(dstDev);
142376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
14246776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1425b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1426fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1427d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1428db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco            SkIRect clipBounds = iter.fClip->getBounds().makeOffset(-pos.x(), -pos.y());
1429be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
14304e23cdaa6b892afeaa150c6d74099dc6c2065b7ereed            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
14314cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
14325efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
143396fcdcc219d2a0d3579719b84b28bede76efba64halcanary                tmpUnfiltered.setImageFilter(nullptr);
14346776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
14356776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
143676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
143761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        } else if (deviceIsBitmapDevice) {
14389572a10c9a6a868bbb8f71d7806d0a45f183333freed            const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap;
143961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
144076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1441b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
144276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
144732704674f64cb6a14356dfebe060cd3484c06cc7reed/////////////////////////////////////////////////////////////////////////////
1448da420b976e61071cfe5de10556b4b23e519091d6reed
144992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1450d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1451d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1452d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
145592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1456d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1457d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1458d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
146192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1462d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1463d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1464d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
146792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1468d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1469d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1470d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
147144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
147244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
147392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1474d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1475d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1476d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1477d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
14782ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1480c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14811f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
148244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
148344c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
148444c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
148544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
148686a17e7716c8db858e219a46b9db3817bb770beereedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
148786a17e7716c8db858e219a46b9db3817bb770beereed    this->checkForDeferredSave();
14888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1489c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14901f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
149144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
14928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
14958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
14964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
14988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
14998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1503759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
15042ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15058f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15068f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
15078f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15088f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15098f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1510da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1511da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
15121f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1513da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1514da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1515da17f758442f16747af39f8fbaed9c097048519creed@google.com
15163b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1517da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1518c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1519da17f758442f16747af39f8fbaed9c097048519creed@google.com
1520687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
15211f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1522da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1523da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1524da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1525da17f758442f16747af39f8fbaed9c097048519creed@google.com
1526ac8cabd729c75fdf774c0701b6ea7fd3ea5b9382bsalomon    if (!fAllowSoftClip) {
1527ac8cabd729c75fdf774c0701b6ea7fd3ea5b9382bsalomon        edgeStyle = kHard_ClipEdgeStyle;
1528ac8cabd729c75fdf774c0701b6ea7fd3ea5b9382bsalomon    }
1529ac8cabd729c75fdf774c0701b6ea7fd3ea5b9382bsalomon
1530c64eff55049b1192052b791549a32a03be1c43e3reed    const bool rectStaysRect = fMCRec->fMatrix.rectStaysRect();
1531c64eff55049b1192052b791549a32a03be1c43e3reed    SkRect devR;
1532c64eff55049b1192052b791549a32a03be1c43e3reed    if (rectStaysRect) {
1533c64eff55049b1192052b791549a32a03be1c43e3reed        fMCRec->fMatrix.mapRect(&devR, rect);
1534c64eff55049b1192052b791549a32a03be1c43e3reed    }
1535c64eff55049b1192052b791549a32a03be1c43e3reed
1536c64eff55049b1192052b791549a32a03be1c43e3reed    // Check if we can quick-accept the clip call (and do nothing)
1537c64eff55049b1192052b791549a32a03be1c43e3reed    //
1538c64eff55049b1192052b791549a32a03be1c43e3reed    // TODO: investigate if a (conservative) version of this could be done in ::clipRect,
1539c64eff55049b1192052b791549a32a03be1c43e3reed    //       so that subclasses (like PictureRecording) didn't see unnecessary clips, which in turn
1540c64eff55049b1192052b791549a32a03be1c43e3reed    //       might allow lazy save/restores to eliminate entire save/restore blocks.
1541c64eff55049b1192052b791549a32a03be1c43e3reed    //
1542c64eff55049b1192052b791549a32a03be1c43e3reed    if (SkRegion::kIntersect_Op == op &&
1543c64eff55049b1192052b791549a32a03be1c43e3reed        kHard_ClipEdgeStyle == edgeStyle
1544c64eff55049b1192052b791549a32a03be1c43e3reed        && rectStaysRect)
1545c64eff55049b1192052b791549a32a03be1c43e3reed    {
1546c64eff55049b1192052b791549a32a03be1c43e3reed        if (devR.round().contains(fMCRec->fRasterClip.getBounds())) {
1547c64eff55049b1192052b791549a32a03be1c43e3reed#if 0
1548c64eff55049b1192052b791549a32a03be1c43e3reed            SkDebugf("------- ignored clipRect [%g %g %g %g]\n",
1549c64eff55049b1192052b791549a32a03be1c43e3reed                     rect.left(), rect.top(), rect.right(), rect.bottom());
1550c64eff55049b1192052b791549a32a03be1c43e3reed#endif
1551c64eff55049b1192052b791549a32a03be1c43e3reed            return;
1552c64eff55049b1192052b791549a32a03be1c43e3reed        }
1553c64eff55049b1192052b791549a32a03be1c43e3reed    }
1554c64eff55049b1192052b791549a32a03be1c43e3reed
1555c64eff55049b1192052b791549a32a03be1c43e3reed    AutoValidateClip avc(this);
1556c64eff55049b1192052b791549a32a03be1c43e3reed
1557c64eff55049b1192052b791549a32a03be1c43e3reed    fDeviceCMDirty = true;
1558c64eff55049b1192052b791549a32a03be1c43e3reed    fCachedLocalClipBoundsDirty = true;
15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1560c64eff55049b1192052b791549a32a03be1c43e3reed    if (rectStaysRect) {
1561c64eff55049b1192052b791549a32a03be1c43e3reed        const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1562c64eff55049b1192052b791549a32a03be1c43e3reed        fClipStack->clipDevRect(devR, op, isAA);
1563c64eff55049b1192052b791549a32a03be1c43e3reed        fMCRec->fRasterClip.op(devR, this->getBaseLayerSize(), op, isAA);
15648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1565123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
156698de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
156798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
156898de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
15708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
15728f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
15738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
157673e714eb766617ce06757829a3c0b345c7963faareedstatic void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
157773e714eb766617ce06757829a3c0b345c7963faareed                            SkRegion::Op op, bool doAA) {
1578d64c9487135094c83f658319f53ea2005ecc08b2reed    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1579819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1580819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1581759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
15822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15838f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15844ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
15858f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
15868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
15878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
15884ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
15898f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
159014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
15918f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
159214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
15931f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
159414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
159514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
159614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
159714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
15988f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
15998f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
16008f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
160114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1602687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
160314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1604125f19a2964c31a660256132acbce60e8a3e6752robertphillips        fMCRec->fRasterClip.op(transformedRRect, this->getBaseLayerSize(), op,
1605125f19a2964c31a660256132acbce60e8a3e6752robertphillips                               kSoft_ClipEdgeStyle == edgeStyle);
16068f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
160714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
160814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
160914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
161014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
161114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
16128f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
16134ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
16144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1615759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
16162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16178f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
161839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
161939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
162039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRect r;
162139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRect(&r)) {
162239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRect(r, op, edgeStyle);
162339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
162439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
162539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRRect rrect;
162639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isOval(&r)) {
162739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            rrect.setOval(r);
162839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
162939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
163039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
163139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRRect(&rrect)) {
163239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
163339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
163439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
16358f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
163639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
163739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    this->onClipPath(path, op, edgeStyle);
16388f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16398f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
16408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1641da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1642da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
16431f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1644da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1645da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1646fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
16473b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1648da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1649c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1650fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1651687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
16521f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1653da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1654da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1655da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1656da17f758442f16747af39f8fbaed9c097048519creed@google.com
16575c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16585c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1660c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
16618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
16628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
16638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
16648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
16661f836ee096bb988adef4b9757b2629c7afeda36dreed    path.transform(fMCRec->fMatrix, &devPath);
16678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1668fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1669fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1670fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1671fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1672fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1673fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1674fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1675fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1676fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1677fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
16785c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
1679687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
16805c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
168145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
16821a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        bool clipIsAA = getClipStack()->asPath(&devPath);
16831a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        if (clipIsAA) {
16841a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita            edgeStyle = kSoft_ClipEdgeStyle;
168545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
16861a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita
168745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
168845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
168945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
169073e714eb766617ce06757829a3c0b345c7963faareed    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1693759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
16942ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16958f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
16968f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16978f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
16988f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
16995c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
17005c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
17018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1702c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
17038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17045c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
17055c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1706687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevRect(rgn.getBounds(), op);
17075c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
17081f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
17098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1711819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1712819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1713819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
17141f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1715ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
17165c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1717ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1718ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1719ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1720819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1721819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1722d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1723819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1724687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
17258182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
172696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    while ((element = iter.next()) != nullptr) {
17278182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
17288182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
17298182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
17308182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
17318182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
17328182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
17338182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
17348182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
17359cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
17369cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
17379cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
173873e714eb766617ce06757829a3c0b345c7963faareed                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
17399cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
17409cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1741819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1742819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1743819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1744819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1745819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
174690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
1747687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
17488182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
17498182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
175096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    while ((element = iter.next()) != nullptr) {
1751c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
175290c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
175390c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
175490c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
17555c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
17565c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1757754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
17581f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1759754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1760754de5f65b466f721d952a379194cc94de376f42reed@google.com
17615c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
17621f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
17635c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17645c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17653b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
17661607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1767116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1768116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
17691f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17731f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.hasPerspective()) {
1774a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
17751f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&dst, rect);
1776b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1777a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1778c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1779d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1780a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1781c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1782c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1783a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1784a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1785c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1786a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1787a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1788a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17923b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
17933b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
17948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17963b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1797bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
17988f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1802d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1803d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
18041f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
180572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
180672dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
180772dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1808d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1809d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1810d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
181149f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1812bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
18133b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
18143b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1815fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
18168f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
18178f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1823bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
18241f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1825bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1826bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1827bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1828bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1829bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1830bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1831bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
183249f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1833bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1834bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1835bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1836bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1837bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
18388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
18391f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18425c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
18431f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
18445c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
18455c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
18469c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
18479c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
184896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return dev ? dev->accessRenderTarget() : nullptr;
18499c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
18509c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1851644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1852644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1853644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
185449f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
1855644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
185649f085dddff10473b6ebf832a974288300224e60bsalomon        if (renderTarget) {
1857644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1858644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1859644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1860644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1861644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
186296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
1863644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1864644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1865e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1866ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1867ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
18689881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1869ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1870ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1871ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1872ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1873ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1874ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1875ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1876ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1877ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1878ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1879ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1880ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1881ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1882ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1883ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1884ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1885ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1886ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
188741af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
188841af966ab338e95eee81ab618ab28195075338f7reed
188941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
189041af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
189141af966ab338e95eee81ab618ab28195075338f7reed}
189241af966ab338e95eee81ab618ab28195075338f7reed
189341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
189441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
189541af966ab338e95eee81ab618ab28195075338f7reed}
189641af966ab338e95eee81ab618ab28195075338f7reed
189741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
189841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
189941af966ab338e95eee81ab618ab28195075338f7reed}
190041af966ab338e95eee81ab618ab28195075338f7reed
190141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
190241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
190341af966ab338e95eee81ab618ab28195075338f7reed}
190441af966ab338e95eee81ab618ab28195075338f7reed
190541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
190641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
190741af966ab338e95eee81ab618ab28195075338f7reed}
190841af966ab338e95eee81ab618ab28195075338f7reed
190941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
191041af966ab338e95eee81ab618ab28195075338f7reed                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
191141af966ab338e95eee81ab618ab28195075338f7reed                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
191241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
191341af966ab338e95eee81ab618ab28195075338f7reed                         indices, indexCount, paint);
191441af966ab338e95eee81ab618ab28195075338f7reed}
191541af966ab338e95eee81ab618ab28195075338f7reed
191641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
191741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
191841af966ab338e95eee81ab618ab28195075338f7reed}
191941af966ab338e95eee81ab618ab28195075338f7reed
1920a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1921e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1922a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
192341af966ab338e95eee81ab618ab28195075338f7reed}
192441af966ab338e95eee81ab618ab28195075338f7reed
1925e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1926e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             const SkPaint* paint, SrcRectConstraint constraint) {
1927e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1928e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (dst.isEmpty() || src.isEmpty()) {
1929e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
1930e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1931e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawImageRect(image, &src, dst, paint, constraint);
1932e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
193341af966ab338e95eee81ab618ab28195075338f7reed
193484984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
193584984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1936e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1937e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
193884984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
193984984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
1940e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1941e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             SrcRectConstraint constraint) {
1942e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1943e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1944e47829b6b1eeb6b0c97ccb3df3016d197046824creed                        constraint);
1945e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1946e47829b6b1eeb6b0c97ccb3df3016d197046824creed
19474c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
19484c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
1949e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
19504c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
19514c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
19524c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
19534c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) {
1954e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, dst, paint);
19554c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
19564c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->onDrawImageNine(image, center, dst, paint);
19574c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
19584c21dc5ddf3b482293ed34eead876d8d61a662c3reed
195941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
19604c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
19612df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19622df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
196341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
196441af966ab338e95eee81ab618ab28195075338f7reed}
196541af966ab338e95eee81ab618ab28195075338f7reed
1966e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1967a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1968e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1969a5517e2b190a8083b38964972b031c13e99f1012reed        return;
1970a5517e2b190a8083b38964972b031c13e99f1012reed    }
1971e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
197241af966ab338e95eee81ab618ab28195075338f7reed}
197341af966ab338e95eee81ab618ab28195075338f7reed
197484984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
197584984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1976e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1977e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1978e47829b6b1eeb6b0c97ccb3df3016d197046824creed
1979e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1980e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              SrcRectConstraint constraint) {
1981e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1982e47829b6b1eeb6b0c97ccb3df3016d197046824creed                         constraint);
198384984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
198484984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
198541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
198641af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
19874c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
19882df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19892df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
19904c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) {
1991a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
19924c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
199341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmapNine(bitmap, center, dst, paint);
199441af966ab338e95eee81ab618ab28195075338f7reed}
199541af966ab338e95eee81ab618ab28195075338f7reed
199671c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
199771c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkColor colors[], int count, SkXfermode::Mode mode,
199871c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
1999e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(atlas);
200071c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
200171c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
200271c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
200371c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(atlas);
200471c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(xform);
200571c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
200671c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
200771c3c760a83123ee0b3127b8c65c6394ce541c50reed}
200871c3c760a83123ee0b3127b8c65c6394ce541c50reed
2009e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2010e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                    const SkPaint* paint, SrcRectConstraint constraint) {
2011e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
2012e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, *src, dst, paint, constraint);
2013e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
2014e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
2015e47829b6b1eeb6b0c97ccb3df3016d197046824creed                            dst, paint, constraint);
2016e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
2017e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2018e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2019e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                     const SkPaint* paint, SrcRectConstraint constraint) {
2020e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
2021e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
2022e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
2023e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
2024e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             dst, paint, constraint);
2025e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
2026e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2027e47829b6b1eeb6b0c97ccb3df3016d197046824creed
20288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
20298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
20308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
203228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
203349f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
203428361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
203528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
203628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
203728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
203841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
20399881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
2040fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
2041fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
2042fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
2043fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
204496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
20458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20474e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
20488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20504e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
205341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
205441af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
20559881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
20568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
20578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
20588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
206078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
206196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2062a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
2063a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
2064a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
2065a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
2066a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
2067a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
2068a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
206987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
207087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
207187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
207287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
2073fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
2074a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
207596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(pts != nullptr);
20768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
207778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
20784b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20824b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
208641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
20879881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
208878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
208996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
20908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
20918432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
20928432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
20938432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
20948432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
20958432808ad8898ac7137bc7ce1d9df6005e866401reed
209687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
209787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
209887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
209987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
21008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21014b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2102c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false)
21038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
21068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
211141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
21129881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
211378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
211496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
21154ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
211687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
211787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
211887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
211987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &oval;
21204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2121306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
212278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
212346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
212446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
212546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
212646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
212746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
212846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
21294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
21304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
213141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
21329881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
213378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
213496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
21354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
213687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
213787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
213887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
213987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &rrect.getBounds();
21404ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
21414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
21424ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
21434ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
21444ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2145f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2146f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
21474ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2148f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2149f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
21504ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2151f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
215278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2153f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2154f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2155f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2156f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2157f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2158f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
21594ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
21604ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2161ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2162ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
2163ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
216496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2165ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
216687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
216787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
216887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
216987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &outer.getBounds();
2170ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
217125c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2172ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
217325c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2174ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2175ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2176ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
217725c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2178ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2179ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
21804ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
218141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
21829881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
21839364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
21849364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
21859364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
21869364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
218778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
218896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2189fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
219078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
219187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
219287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
219387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
219487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &pathBounds;
21958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21960b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
21970b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
21980b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
21996803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2200fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
22016651a3238dd6affa4276ada42ab613abf1d42d1dcaryclark            return;
2202fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2203fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
220578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
22068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
22098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
22128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2214262a71b7f95ce98ff3dd8dba845afbd724470903reedbool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2215262a71b7f95ce98ff3dd8dba845afbd724470903reed    if (!paint.getImageFilter()) {
2216262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2217262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2218262a71b7f95ce98ff3dd8dba845afbd724470903reed
2219262a71b7f95ce98ff3dd8dba845afbd724470903reed    const SkMatrix& ctm = this->getTotalMatrix();
2220c7e211acd0c9201688de7ff0c9a2271c67440adffmalita    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2221262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2222262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2223262a71b7f95ce98ff3dd8dba845afbd724470903reed
2224262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2225262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Once we can filter and the filter will return a result larger than itself, we should be
2226262a71b7f95ce98ff3dd8dba845afbd724470903reed    // able to remove this constraint.
2227262a71b7f95ce98ff3dd8dba845afbd724470903reed    // skbug.com/4526
2228262a71b7f95ce98ff3dd8dba845afbd724470903reed    //
2229262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkPoint pt;
2230262a71b7f95ce98ff3dd8dba845afbd724470903reed    ctm.mapXY(x, y, &pt);
2231262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2232262a71b7f95ce98ff3dd8dba845afbd724470903reed    return ir.contains(fMCRec->fRasterClip.getBounds());
2233262a71b7f95ce98ff3dd8dba845afbd724470903reed}
2234262a71b7f95ce98ff3dd8dba845afbd724470903reed
2235a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
22369881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2237a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2238a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
223996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
224087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = bounds;
224187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
224287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(tmp, &tmp);
224387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
224487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(tmp)) {
224587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
224687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2247a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2248a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2249a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
225096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2251a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2252a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2253262a71b7f95ce98ff3dd8dba845afbd724470903reed
2254262a71b7f95ce98ff3dd8dba845afbd724470903reed    const bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2255262a71b7f95ce98ff3dd8dba845afbd724470903reed                                                          *paint);
2256262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2257262a71b7f95ce98ff3dd8dba845afbd724470903reed
2258a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2259262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2260262a71b7f95ce98ff3dd8dba845afbd724470903reed        if (drawAsSprite && pnt.getImageFilter()) {
2261262a71b7f95ce98ff3dd8dba845afbd724470903reed            SkBitmap bitmap;
2262262a71b7f95ce98ff3dd8dba845afbd724470903reed            if (as_IB(image)->asBitmapForImageFilters(&bitmap)) {
2263262a71b7f95ce98ff3dd8dba845afbd724470903reed                SkPoint pt;
2264262a71b7f95ce98ff3dd8dba845afbd724470903reed                iter.fMatrix->mapXY(x, y, &pt);
2265262a71b7f95ce98ff3dd8dba845afbd724470903reed                iter.fDevice->drawBitmapAsSprite(iter, bitmap,
2266262a71b7f95ce98ff3dd8dba845afbd724470903reed                                                 SkScalarRoundToInt(pt.fX),
2267262a71b7f95ce98ff3dd8dba845afbd724470903reed                                                 SkScalarRoundToInt(pt.fY), pnt);
2268262a71b7f95ce98ff3dd8dba845afbd724470903reed            }
2269262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2270262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fDevice->drawImage(iter, image, x, y, pnt);
2271262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
2272a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2273a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2274a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2275b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2276b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
227741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2278562fe4767cc73e08a4e039362bc0336aea66ecfbreed                               const SkPaint* paint, SrcRectConstraint constraint) {
22799881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
228096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2281c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage = dst;
228287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
228387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(dst, &storage);
228487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
228587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(storage)) {
228687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
228787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2288a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2289a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
229096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2291a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2292a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2293a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2294c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2295c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
2296a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2297a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2298a5517e2b190a8083b38964972b031c13e99f1012reed        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
2299a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2300a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2301a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2302b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2303b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
230441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
23059881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
23068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
23078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
230833366974d43eae80e22284a2e445225c343859dareed    if (bitmap.drawsNothing()) {
230933366974d43eae80e22284a2e445225c343859dareed        return;
231033366974d43eae80e22284a2e445225c343859dareed    }
231133366974d43eae80e22284a2e445225c343859dareed
231233366974d43eae80e22284a2e445225c343859dareed    SkLazyPaint lazy;
231333366974d43eae80e22284a2e445225c343859dareed    if (nullptr == paint) {
231433366974d43eae80e22284a2e445225c343859dareed        paint = lazy.init();
231533366974d43eae80e22284a2e445225c343859dareed    }
231633366974d43eae80e22284a2e445225c343859dareed
231733366974d43eae80e22284a2e445225c343859dareed    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
231833366974d43eae80e22284a2e445225c343859dareed
231933366974d43eae80e22284a2e445225c343859dareed    SkRect storage;
232033366974d43eae80e22284a2e445225c343859dareed    const SkRect* bounds = nullptr;
232133366974d43eae80e22284a2e445225c343859dareed    if (paint->canComputeFastBounds()) {
232233366974d43eae80e22284a2e445225c343859dareed        bitmap.getBounds(&storage);
232333366974d43eae80e22284a2e445225c343859dareed        matrix.mapRect(&storage);
232487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = storage;
232587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) {
232687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
232787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
232887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
23298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23304b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2331262a71b7f95ce98ff3dd8dba845afbd724470903reed    const bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2332262a71b7f95ce98ff3dd8dba845afbd724470903reed                                                                    bitmap.height(), *paint);
2333262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds)
233433366974d43eae80e22284a2e445225c343859dareed
233533366974d43eae80e22284a2e445225c343859dareed    while (iter.next()) {
2336262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2337262a71b7f95ce98ff3dd8dba845afbd724470903reed        if (drawAsSprite && pnt.getImageFilter()) {
2338262a71b7f95ce98ff3dd8dba845afbd724470903reed            SkPoint pt;
2339262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fMatrix->mapXY(x, y, &pt);
2340262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fDevice->drawBitmapAsSprite(iter, bitmap,
2341262a71b7f95ce98ff3dd8dba845afbd724470903reed                                             SkScalarRoundToInt(pt.fX),
2342262a71b7f95ce98ff3dd8dba845afbd724470903reed                                             SkScalarRoundToInt(pt.fY), pnt);
2343262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2344262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
2345262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
234633366974d43eae80e22284a2e445225c343859dareed    }
2347262a71b7f95ce98ff3dd8dba845afbd724470903reed
234833366974d43eae80e22284a2e445225c343859dareed    LOOPER_END
23498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23519987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
23527112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2353eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2354a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
235550b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
23568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
23578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
235874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
235996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2360c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
236187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
236287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
236387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23653d60812865bb034851da777a91413ab584929887reed@google.com
236633535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
236796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
236833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
23698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23707064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2371c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2372c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
23737064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
237433535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2375562fe4767cc73e08a4e039362bc0336aea66ecfbreed        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
2376f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
23777064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
237833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
23798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2382562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                const SkPaint* paint, SrcRectConstraint constraint) {
23839881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
23849987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2385562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
23869987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23879987ec3791336bad6af5cbe513564786b2df55aareed@google.com
23884c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
23894c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
23904c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
23914c21dc5ddf3b482293ed34eead876d8d61a662c3reed
239296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2393c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
239487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
239587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
239687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23973d60812865bb034851da777a91413ab584929887reed@google.com    }
23984c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23994c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
240096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
24014c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
24024c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
24034c21dc5ddf3b482293ed34eead876d8d61a662c3reed
2404c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
24054c21dc5ddf3b482293ed34eead876d8d61a662c3reed
24064c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
24074c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
24089987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
24094c21dc5ddf3b482293ed34eead876d8d61a662c3reed
24104c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
24119987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
24129987ec3791336bad6af5cbe513564786b2df55aareed@google.com
241341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
241441af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
24159881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
24169987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
24179987ec3791336bad6af5cbe513564786b2df55aareed@google.com
241896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2419c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
242087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
242187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
242287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
24234c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
24244c21dc5ddf3b482293ed34eead876d8d61a662c3reed
24254c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
242696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
24274c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
24284c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
24294c21dc5ddf3b482293ed34eead876d8d61a662c3reed
2430c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
24314c21dc5ddf3b482293ed34eead876d8d61a662c3reed
24324c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
24334c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
24344c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
24354c21dc5ddf3b482293ed34eead876d8d61a662c3reed
24364c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
24379987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
24389987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2439f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2440f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
24411f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2442112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2443112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2444a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2445112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2446f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2447f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2448f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2449f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2450f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2451f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2452f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2453f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2454f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
24552c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
24562c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2457f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2458f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
245952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
246052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
246117b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
246252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
246352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
246452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
246517b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
246652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
246752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
246852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
246952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
247052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
247152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
247252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
247396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(byteLength == 0 || text != nullptr);
247452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
247552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
247696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (text == nullptr || byteLength == 0 ||
247752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
247896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) {
247952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
248052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
248152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
248252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
248352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
248452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
248552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
248652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
248752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
248852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
248952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
249052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
249152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
249252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
249352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
249452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
249552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
249652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
249752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
249852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
249952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
250052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
250152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
250252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
250352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
250452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
250552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
250652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
250752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
250852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
250952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
251052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
251152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
251252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
251352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
251452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
251552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
251652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
251752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
251852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
2519fb56218292d6c7b509d382f39994c3783b2483a0caryclark            DrawRect(draw, paint, r, 1);
252052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
252152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
252252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
252352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
252452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
252552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
2526fb56218292d6c7b509d382f39994c3783b2483a0caryclark            DrawRect(draw, paint, r, 1);
252752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
252852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
252952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
253052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2531e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2532e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
253396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
25348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
25364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2537f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
253852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
253952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
25408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2545e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2546e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
254705c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
254805c4a4322e7d4f3417b7df33825bab8603d52051fmalita
254996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
255087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
25518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
25524e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
255305c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2554f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
25558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2556b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
25574e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2560e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2561e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
256205c4a4322e7d4f3417b7df33825bab8603d52051fmalita
256305c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
256405c4a4322e7d4f3417b7df33825bab8603d52051fmalita
256596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
256687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
25678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
25684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
256905c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2570f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
25718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2572b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
25734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2576e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2577e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
257896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
257987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
25808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
25818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
25824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
25838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2584b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2585945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
25864325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
25874325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
258800d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
258900d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
25907ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
259185d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
259296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
259319653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
259485d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
259587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp;
259687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
259787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
259887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
259987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
26007ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
26017ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2602024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2603024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2604024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
260596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fFilter = nullptr;
2606024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
260785d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
260800d5c2c6523321d25b32905ff4822f083a4173eefmalita
2609aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2610aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2611024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
261200d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
261300d5c2c6523321d25b32905ff4822f083a4173eefmalita
2614aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2615024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2616024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
261700d5c2c6523321d25b32905ff4822f083a4173eefmalita}
261800d5c2c6523321d25b32905ff4822f083a4173eefmalita
2619e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2620e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2621e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
26229881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2623e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2624e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2625e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2626e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
26279881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2628e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2629e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2630e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2631e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
26329881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2633e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2634e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2635e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2636e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
26379881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2638e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2639e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
264000d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
264100d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
2642e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(blob);
26439881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2644e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawTextBlob(blob, x, y, paint);
264500d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2646e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
264741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
264841af966ab338e95eee81ab618ab28195075338f7reed                              const SkPoint verts[], const SkPoint texs[],
264941af966ab338e95eee81ab618ab28195075338f7reed                              const SkColor colors[], SkXfermode* xmode,
265041af966ab338e95eee81ab618ab28195075338f7reed                              const uint16_t indices[], int indexCount,
265141af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint& paint) {
26529881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
265396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
26544b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
26568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
26574e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
26584e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
26598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26604b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26614e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
26628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2664b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2665b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
26669881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
266796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == cubics) {
2668b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2669b3c9d1c33caf325aada244204215eb790c228c12dandov    }
26706cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2671ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2672ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2673ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2674b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2675ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2676ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2677ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26786cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2679b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2680b3c9d1c33caf325aada244204215eb790c228c12dandov}
2681b3c9d1c33caf325aada244204215eb790c228c12dandov
2682b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2683b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2684b3c9d1c33caf325aada244204215eb790c228c12dandov
268596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
26866cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2687ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2688b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2689ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26906cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2691ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2692ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2693ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2694a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2695e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2696e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (x || y) {
2697e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2698e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, &matrix);
2699e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2700e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, nullptr);
2701a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2702a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
2703a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
2704a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2705e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2706e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2707e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
27086a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
2709e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawDrawable(dr, matrix);
27106a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
27116a070dc06af4e9f305f9d08a69e34d18ade473cbreed
2712a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2713a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    SkRect bounds = dr->getBounds();
2714a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (matrix) {
2715a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        matrix->mapRect(&bounds);
2716a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2717a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (this->quickReject(bounds)) {
2718a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        return;
2719a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2720a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
27216a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
27226a070dc06af4e9f305f9d08a69e34d18ade473cbreed
272371c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
272471c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkColor colors[], int count, SkXfermode::Mode mode,
272571c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
272671c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
272771c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
272871c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
272971c3c760a83123ee0b3127b8c65c6394ce541c50reed
273071c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
273171c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
273271c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
273371c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
273471c3c760a83123ee0b3127b8c65c6394ce541c50reed
273596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
273671c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
273771c3c760a83123ee0b3127b8c65c6394ce541c50reed        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt);
273871c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
273971c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
274071c3c760a83123ee0b3127b8c65c6394ce541c50reed}
274171c3c760a83123ee0b3127b8c65c6394ce541c50reed
27428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
27438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
27448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
27458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
27468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2748845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
27499881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
27508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
27518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2753845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
27540baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
27558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
27578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2759845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
27609881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
27618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
27628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2764845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
27650baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
27668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
27688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
27719881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
27728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
27734b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
27758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
27768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
27799881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
27808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
27818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
27824b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
27848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
27858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
27868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
27898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
27909881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
27918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
27924b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
27948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
27958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
27968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
27998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
28008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
28019881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
28028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
28038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
28058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
28068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
28098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
28109881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
28118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
28128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
28138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
28168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
28174ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
28188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
28218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
28229881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
28238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
28248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
28258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
28263b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
28278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
28288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
28298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
28304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
28314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
28324ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
28338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
28348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
28358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
28398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
28408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
28419881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
28428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
28438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
28448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
28458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
28468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
28478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
28488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
28498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
28508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
28518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
28528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
28538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
28548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
28588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
28598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
28609881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
28618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
28624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
28638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
28648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
28658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2867f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
28681c2c441fede0ae9573afc098017011e3439624a9reed
28691c2c441fede0ae9573afc098017011e3439624a9reed/**
28701c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
28711c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
28721c2c441fede0ae9573afc098017011e3439624a9reed *
28731c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
28741c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
28751c2c441fede0ae9573afc098017011e3439624a9reed */
28761c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
28779b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2878d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2879e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(picture);
2880e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
28811c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2882e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2883e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
2884e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    }
2885e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2886e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2887e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        picture->playback(this);
2888e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2889e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawPicture(picture, matrix, paint);
2890d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2891d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
28929b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2893d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2894d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2895d028180f0310cf2b23f9744256a41697b0683e67fmalita    if (!paint || paint->canComputeFastBounds()) {
2896d028180f0310cf2b23f9744256a41697b0683e67fmalita        SkRect bounds = picture->cullRect();
2897d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (paint) {
2898d028180f0310cf2b23f9744256a41697b0683e67fmalita            paint->computeFastBounds(bounds, &bounds);
2899d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2900d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (matrix) {
2901d028180f0310cf2b23f9744256a41697b0683e67fmalita            matrix->mapRect(&bounds);
2902d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2903d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (this->quickReject(bounds)) {
2904d028180f0310cf2b23f9744256a41697b0683e67fmalita            return;
2905d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2906d028180f0310cf2b23f9744256a41697b0683e67fmalita    }
2907d028180f0310cf2b23f9744256a41697b0683e67fmalita
2908145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
290949f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2910145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2911145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2912d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2913145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2914145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2915145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2916145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
2917a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2918c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
29198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
29228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
29238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
292599fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
29268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
29288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
29308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
29318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
29348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
29358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
29388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
29398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29411f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
29428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
29438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
29468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
29478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
29508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
295196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
29528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
29538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
29548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
29558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
29588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
29598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
296020a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
296120a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
296220a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2963c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
29643107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
29653107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
29663107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
29673107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
29683107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
29693107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
29703107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
29713107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
29723107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
29733107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
29743107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
29753107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
29763107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
29773107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
29783107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
297928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
29803107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
29813107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
29823107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
29833107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
29843107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
29853107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
29863107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
29873107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
298842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
298942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
299096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
299142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2992eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
299342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
299442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
299596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
299642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2997385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkCanvas(bitmap);
299842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2999d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3000d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
3001d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3002d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
3003a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
3004d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
3005d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
3006d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
300749f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
3008a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
3009d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
3010a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
3011d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
3012a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
301349f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
3014d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
3015d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
30166cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
301749f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
3018d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
3019d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
3020d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
3021d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3022d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3023d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
3024d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
3025