SkCanvas.cpp revision 42b73eb00367c8315974b1c374308d20efa78897
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"
2074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
214c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkNinePatchIter.h"
22c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
23b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
250017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
2696472deea70169396b8e1f576e470138f55fdb1freed#include "SkReadPixelsRec.h"
274ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
2997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
307ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
3152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
32a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
338f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
34d3ebb48320cf1b7e969974673e4bd7743816985ebungeman
35d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include <new>
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
38644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
39644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
40644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
4187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco#define SK_SUPPORT_SRC_BOUNDS_BLOAT_FOR_IMAGEFILTERS
4287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco
43c83a29759a5c2966da5ab973e4fd90763e4c962breed/*
44c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Return true if the drawing this rect would hit every pixels in the canvas.
45c83a29759a5c2966da5ab973e4fd90763e4c962breed *
46c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Returns false if
47c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - rect does not contain the canvas' bounds
48c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint is not fill
49c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint would blur or otherwise change the coverage of the rect
50c83a29759a5c2966da5ab973e4fd90763e4c962breed */
51c83a29759a5c2966da5ab973e4fd90763e4c962breedbool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
52c83a29759a5c2966da5ab973e4fd90763e4c962breed                                           ShaderOverrideOpacity overrideOpacity) const {
5399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
5499fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNone_ShaderOverrideOpacity,
5599fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums0");
5699fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
5799fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kOpaque_ShaderOverrideOpacity,
5899fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums1");
5999fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
6099fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNotOpaque_ShaderOverrideOpacity,
6199fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums2");
62c83a29759a5c2966da5ab973e4fd90763e4c962breed
63c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkISize size = this->getBaseLayerSize();
64c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
65c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (!this->getClipStack()->quickContains(bounds)) {
66c83a29759a5c2966da5ab973e4fd90763e4c962breed        return false;
67c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
68c83a29759a5c2966da5ab973e4fd90763e4c962breed
69c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (rect) {
70c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!this->getTotalMatrix().rectStaysRect()) {
71c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
72c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
73c83a29759a5c2966da5ab973e4fd90763e4c962breed
74c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkRect devRect;
75c83a29759a5c2966da5ab973e4fd90763e4c962breed        this->getTotalMatrix().mapRect(&devRect, *rect);
768c0144ccb17220db9d5140ef5ee85d5bc7837513fmalita        if (!devRect.contains(bounds)) {
77c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
78c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
79c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
80c83a29759a5c2966da5ab973e4fd90763e4c962breed
81c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (paint) {
82c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkPaint::Style paintStyle = paint->getStyle();
83c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!(paintStyle == SkPaint::kFill_Style ||
84c83a29759a5c2966da5ab973e4fd90763e4c962breed              paintStyle == SkPaint::kStrokeAndFill_Style)) {
85c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
86c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
87c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (paint->getMaskFilter() || paint->getLooper()
88c83a29759a5c2966da5ab973e4fd90763e4c962breed            || paint->getPathEffect() || paint->getImageFilter()) {
89c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
90c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
91c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
92c83a29759a5c2966da5ab973e4fd90763e4c962breed    return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
93c83a29759a5c2966da5ab973e4fd90763e4c962breed}
94c83a29759a5c2966da5ab973e4fd90763e4c962breed
95c83a29759a5c2966da5ab973e4fd90763e4c962breed///////////////////////////////////////////////////////////////////////////////////////////////////
96c83a29759a5c2966da5ab973e4fd90763e4c962breed
97d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
98d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
99d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
100d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
101d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
102d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
103d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
104d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
1050acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
1060acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
1070acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
1080acf1b4b3645772d220c720313821bac389751b5reed}
1090acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
1100acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
1110acf1b4b3645772d220c720313821bac389751b5reed}
1120acf1b4b3645772d220c720313821bac389751b5reed
113da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
114da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
11515e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1392c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
1402c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
141c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(bool willOverwritesEntireSurface) {
14297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
143c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
144c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  ? SkSurface::kDiscard_ContentChangeMode
145c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  : SkSurface::kRetain_ContentChangeMode);
146c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
147c83a29759a5c2966da5ab973e4fd90763e4c962breed}
148c83a29759a5c2966da5ab973e4fd90763e4c962breed
149c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
150c83a29759a5c2966da5ab973e4fd90763e4c962breed                             ShaderOverrideOpacity overrideOpacity) {
151c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (fSurfaceBase) {
152c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode;
153c83a29759a5c2966da5ab973e4fd90763e4c962breed        // Since willOverwriteAllPixels() may not be complete free to call, we only do so if
154c83a29759a5c2966da5ab973e4fd90763e4c962breed        // there is an outstanding snapshot, since w/o that, there will be no copy-on-write
155c83a29759a5c2966da5ab973e4fd90763e4c962breed        // and therefore we don't care which mode we're in.
156c83a29759a5c2966da5ab973e4fd90763e4c962breed        //
157c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (fSurfaceBase->outstandingImageSnapshot()) {
158c83a29759a5c2966da5ab973e4fd90763e4c962breed            if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) {
159c83a29759a5c2966da5ab973e4fd90763e4c962breed                mode = SkSurface::kDiscard_ContentChangeMode;
160c83a29759a5c2966da5ab973e4fd90763e4c962breed            }
161c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
162c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(mode);
16397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
16497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
16597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1684a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
1694a8126e7f81384526629b1e21bf89b632ea13cd9reed    const uint32_t propFlags = props.flags();
1704a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
1714a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kDither_Flag;
1724a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
1734a8126e7f81384526629b1e21bf89b632ea13cd9reed    if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
1744a8126e7f81384526629b1e21bf89b632ea13cd9reed        flags &= ~SkPaint::kAntiAlias_Flag;
1754a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
1764a8126e7f81384526629b1e21bf89b632ea13cd9reed    return flags;
1774a8126e7f81384526629b1e21bf89b632ea13cd9reed}
1784a8126e7f81384526629b1e21bf89b632ea13cd9reed
1794a8126e7f81384526629b1e21bf89b632ea13cd9reed///////////////////////////////////////////////////////////////////////////////
1804a8126e7f81384526629b1e21bf89b632ea13cd9reed
1811f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1901f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1926f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
19361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const SkMatrix*     fMatrix;
19461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    SkMatrix            fMatrixStorage;
19561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const bool          fDeviceIsBitmapDevice;
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19796e657d0e103b8358a77ecd913f6086929f792b8reed    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
19886a17e7716c8db858e219a46b9db3817bb770beereed             bool conservativeRasterClip, bool deviceIsBitmapDevice)
19996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        : fNext(nullptr)
200d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
20161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
202d954498c01ccf0417feacf89e45d0c62a06a813breed    {
20396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr != device) {
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device->ref();
20540a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            device->onAttachToCanvas(canvas);
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2074b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
20896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = paint ? new SkPaint(*paint) : nullptr;
20988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
21249f085dddff10473b6ebf832a974288300224e60bsalomon        if (fDevice) {
21340a1ae4df28810aa5aa5cf2627d8387b2dfb867arobertphillips@google.com            fDevice->onDetachFromCanvas();
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice->unref();
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
216385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fPaint;
21788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2184b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
219feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
220feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
221feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
222feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
223feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
224feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
225feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
226045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
227045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                  const SkClipStack& clipStack, SkRasterClip* updateClip) {
2286f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
2296f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
2324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
2414b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
245045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
2484b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
250045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2534b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2543fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com        fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
2553fffb2ee9fa01ae61efb2395973eb7575eda4c96robertphillips@google.com
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
263f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2751f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
276d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2832ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    DeviceCM*       fTopLayer;
2842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRasterClip    fRasterClip;
2852ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkMatrix        fMatrix;
2862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int             fDeferredSaveCount;
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
28996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fFilter     = nullptr;
29096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer      = nullptr;
29196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fTopLayer   = nullptr;
2922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
2932ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
294b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
295d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
296d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
297d954498c01ccf0417feacf89e45d0c62a06a813breed    }
2982ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
299d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
30096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer = nullptr;
301d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
3022ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
303b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
30882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
309385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fLayer;
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
312feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
313feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
314feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
315feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
316feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
317feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
318feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
319feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
320feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3258a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com    SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
3264370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
3278a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fCanvas = canvas;
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
330687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack = canvas->fClipStack;
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
3328a0b0291ae4260ef2a46f4341c18a702c0ce3f8btomhudson@google.com        fSkipEmptyClips = skipEmptyClips;
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3344b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fSkipEmptyClips) {
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fCurrLayer = fCurrLayer->fNext;
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
343f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
344f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
347045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fClip   = &((SkRasterClip*)&rec->fClip)->forceGetBW();
348045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
35041e010cb901c0da9066c4df562030808c9ccd7f8reed            if (!fDevice->accessPixels(&fDst)) {
35196fcdcc219d2a0d3579719b84b28bede76efba64halcanary                fDst.reset(fDevice->imageInfo(), nullptr, 0);
35241e010cb901c0da9066c4df562030808c9ccd7f8reed            }
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
354f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
35796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // fCurrLayer may be nullptr now
358199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3641f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
3656f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3666f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion& getClip() const { return *fClip; }
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3706f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkCanvas*       fCanvas;
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool8         fSkipEmptyClips;
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
382dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
383dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
384dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
385dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
386dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
387dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
38896fcdcc219d2a0d3579719b84b28bede76efba64halcanary *  colorfilter, else return nullptr.
389dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
390dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkColorFilter* image_to_color_filter(const SkPaint& paint) {
391dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
392dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
39396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
394dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
395dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
396dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* imgCF;
397dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf->asAColorFilter(&imgCF)) {
39896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
399dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
400dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
401dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
40296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paintCF) {
403dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
404dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
405dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
406dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
407dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
408dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
409dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
410dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
411dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
412dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
41387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco/**
41487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * There are many bounds in skia. A circle's bounds is just its center extended by its radius.
41587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * However, if we stroke a circle, then the "bounds" of that is larger, since it will now draw
41687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * outside of its raw-bounds by 1/2 the stroke width.  SkPaint has lots of optional
41787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * effects/attributes that can modify the effective bounds of a given primitive -- maskfilters,
41887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * patheffects, stroking, etc.  This function takes a raw bounds and a paint, and returns the
41987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * conservative "effective" bounds based on the settings in the paint... with one exception. This
42087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * function does *not* look at the imagefilter, which can also modify the effective bounds. It is
42187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * deliberately ignored.
42287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco */
42387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblancostatic const SkRect& apply_paint_to_bounds_sans_imagefilter(const SkPaint& paint,
42487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            const SkRect& rawBounds,
42587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            SkRect* storage) {
42687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    SkPaint tmpUnfiltered(paint);
42787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    tmpUnfiltered.setImageFilter(nullptr);
42887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    if (tmpUnfiltered.canComputeFastBounds()) {
42987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return tmpUnfiltered.computeFastBounds(rawBounds, storage);
43087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    } else {
43187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return rawBounds;
43287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    }
43387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco}
43487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
43787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the
43887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // paint. It's used to determine the size of the offscreen layer for filters.
43987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // If null, the clip will be used instead.
4404a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
44178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org                   bool skipLayerForImageFilter = false,
44287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                   const SkRect* rawBounds = nullptr) : fOrigPaint(paint) {
4434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
4454a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
4464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
4475c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
4484e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
450dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
451dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
452dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
453dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            paint->setColorFilter(simplifiedCF)->unref();
45496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            paint->setImageFilter(nullptr);
455dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
456dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
457dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
458dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
4595c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
4605c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
4615c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
4625c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
4635c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
4645c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
4655c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
4665c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
4675c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
4685c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
4695c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
4705c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
4715c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
4725c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
4735c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
4748926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
475dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setImageFilter(fPaint->getImageFilter());
476dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setXfermode(fPaint->getXfermode());
47787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            SkRect storage;
47887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            if (rawBounds) {
47987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                // Make rawBounds include all paint outsets except for those due to image filters.
48087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage);
48187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            }
48287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            (void)canvas->internalSaveLayer(rawBounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
48376033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
4845c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
4855c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
4868926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
48879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
48979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
49079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
49179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
492129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
493129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
49496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fLooperContext = nullptr;
495129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
4965c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
498b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
4994a8126e7f81384526629b1e21bf89b632ea13cd9reed        uint32_t oldFlags = paint.getFlags();
5004a8126e7f81384526629b1e21bf89b632ea13cd9reed        fNewPaintFlags = filter_paint_flags(props, oldFlags);
5014a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (fIsSimple && (fNewPaintFlags != oldFlags)) {
502dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
5034a8126e7f81384526629b1e21bf89b632ea13cd9reed            paint->setFlags(fNewPaintFlags);
5044a8126e7f81384526629b1e21bf89b632ea13cd9reed            fPaint = paint;
5054a8126e7f81384526629b1e21bf89b632ea13cd9reed            // if we're not simple, doNext() will take care of calling setFlags()
5064a8126e7f81384526629b1e21bf89b632ea13cd9reed        }
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
50874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
5105c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
5118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
5128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
5134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
51574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5164e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
5174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
5184e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
5194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
52074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
521129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
522129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
523129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
524129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
525129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
526129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
527129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
528129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
529129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
530fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
53174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
533dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintInit; // base paint storage in case we need to modify it
534dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
5352c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
5362c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
5372c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
5382c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
5392c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
5404a8126e7f81384526629b1e21bf89b632ea13cd9reed    uint32_t        fNewPaintFlags;
5415c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
5422c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
543129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
54479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
54579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
546129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
547129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
550129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
55196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fPaint = nullptr;
552129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5535c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
554632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
555dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
556dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5574a8126e7f81384526629b1e21bf89b632ea13cd9reed    paint->setFlags(fNewPaintFlags);
5588926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5595c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
56096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setImageFilter(nullptr);
56196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setXfermode(nullptr);
562129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5638926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
56479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
565129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
566129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
567129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
568129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
569971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
570971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
571971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
572971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
57396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fLooperContext) {
574129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
575632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
576632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
577129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
578129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
5798926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
580129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
58179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
5824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
5834e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
585632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
586632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
58796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = nullptr;
5884e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
5894e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5904e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
5914e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
5924e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
59697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5974a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, true);              \
5988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
5998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
6008926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
60178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
60297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
6034a8126e7f81384526629b1e21bf89b632ea13cd9reed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
6044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
6064b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
607c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
608c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
609c83a29759a5c2966da5ab973e4fd90763e4c962breed    AutoDrawLooper  looper(this, fProps, paint, false, bounds);     \
610c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
611c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
612c83a29759a5c2966da5ab973e4fd90763e4c962breed
6134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
617feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
618feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
619feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBounds.setEmpty();
620feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fCachedLocalClipBoundsDirty = true;
621feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fClipStack->reset();
622feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
623feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
624feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
625feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
626feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
627feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
628feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
629d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
63042b73eb00367c8315974b1c374308d20efa78897reed    if (device && device->forceConservativeRasterClip()) {
63142b73eb00367c8315974b1c374308d20efa78897reed        flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
63242b73eb00367c8315974b1c374308d20efa78897reed    }
63342b73eb00367c8315974b1c374308d20efa78897reed    // Since init() is only called once by our constructors, it is safe to perform this
63442b73eb00367c8315974b1c374308d20efa78897reed    // const-cast.
63542b73eb00367c8315974b1c374308d20efa78897reed    *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativeRasterClip_InitFlag);
63642b73eb00367c8315974b1c374308d20efa78897reed
637c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBounds.setEmpty();
638c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
6398f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
64045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
641f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
6422ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
64396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMetaData = nullptr;
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
645385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    fClipStack.reset(new SkClipStack);
646687fa1c745febb57f42b0d5f03d7c1f4be2530careed
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
648d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
650a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
651a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
65296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip, false);
653b679ca8926a832274b14fdb512f88f64b61d32eareed
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fSurfaceBase = nullptr;
657f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
658f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
659efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
660efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
661f92c86642a1875da54d54b447f006cb9dfbbb35creed        device->onAttachToCanvas(this);
662f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
66378e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
664f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
665f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
669e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6704a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
67142b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
672e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
6738d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
674ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
67596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    this->init(nullptr, kDefault_InitFlags);
6768d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
6778d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
678d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
679d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
680d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
681d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
682d954498c01ccf0417feacf89e45d0c62a06a813breed}
683d954498c01ccf0417feacf89e45d0c62a06a813breed
684d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
685d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
686fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps)
687fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips        : INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps)
68878e276889795454891cbba48ab11927968114953reed    {
68978e276889795454891cbba48ab11927968114953reed        this->setOrigin(bounds.x(), bounds.y());
69078e276889795454891cbba48ab11927968114953reed    }
691d954498c01ccf0417feacf89e45d0c62a06a813breed
692d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
693b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
694d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
695d954498c01ccf0417feacf89e45d0c62a06a813breed};
696d954498c01ccf0417feacf89e45d0c62a06a813breed
69796a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
698e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
69996a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
70042b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
701e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
702e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
703b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
704385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    this->init(new SkNoPixelsBitmapDevice(SkIRect::MakeWH(width, height), fProps),
705385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary               kDefault_InitFlags)->unref();
706d954498c01ccf0417feacf89e45d0c62a06a813breed}
707e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
70878e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
709d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7104a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
71142b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
712d954498c01ccf0417feacf89e45d0c62a06a813breed{
713d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
714b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
715385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    this->init(new SkNoPixelsBitmapDevice(bounds, fProps), flags)->unref();
71627a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
718d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
719d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7207b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
72142b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
722d954498c01ccf0417feacf89e45d0c62a06a813breed{
723d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
724b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
725d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
728fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
729fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7307b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
73142b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
732fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
733fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
734fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
735fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
736fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
737fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
7384a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
7393716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7404a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
74142b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
7423716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7433716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
744b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
745385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
7464a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7474a8126e7f81384526629b1e21bf89b632ea13cd9reed}
74829c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
7494a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap)
7504a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7514a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
75242b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
7534a8126e7f81384526629b1e21bf89b632ea13cd9reed{
7544a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
755b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
756385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
7574a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
7637c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
766385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete fMetaData;
767b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
77651985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
78174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
78274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
78374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
78496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fMetaData) {
78574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
78674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
78774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
78874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
78974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
792bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
7931f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
794bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
795bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
796bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
797bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
798bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
7994ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getTopLayerSize() const {
8004ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
8014ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
8024ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
8034ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
8044ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkIPoint SkCanvas::getTopLayerOrigin() const {
8054ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
8064ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
8074ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
8084ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
8094ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.comSkISize SkCanvas::getBaseLayerSize() const {
8101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* d = this->getDevice();
811210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
812210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
813210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
8141f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
816c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8211f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
8220b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
8230b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
8240b53d59a24f667350b4282f88470713902409030reed@google.com    }
8259266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
8269266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
8279266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
828a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
829a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
830a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
831a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
832a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
833a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
83496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == bitmap->pixelRef()) {
835848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
836a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
837a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
838a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
839a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
840a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
841cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
842cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap->requestLock(&unlocker)) {
843cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
844cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
845cf01e31df6bbda270dca2ee3b4967caf51e465dcreed            return true;
846cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        }
847a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
848a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
849a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
85096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        bitmap->setPixelRef(nullptr);
851a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
852a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
853a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
85451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
855c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
856a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
857a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
858a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
859a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
860ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
861ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
86274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
863848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
864a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
865a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
866a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
867a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
868a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
869daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
870c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
871a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
872a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
873c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
87496472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
875a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
876a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
877a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
878a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
879a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
880f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
88196472deea70169396b8e1f576e470138f55fdb1freed    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
88296472deea70169396b8e1f576e470138f55fdb1freed    if (!rec.trim(size.width(), size.height())) {
883a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
884a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
885db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
886a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
88796472deea70169396b8e1f576e470138f55fdb1freed    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
88851df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
88951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8904cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
8914cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (bitmap.getTexture()) {
8924cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8934cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
894cf01e31df6bbda270dca2ee3b4967caf51e465dcreed
895cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
896cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap.requestLock(&unlocker)) {
897cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
898cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
8994cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9004cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
9014cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
9024cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9034cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
9044cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
9054cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
9064cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
9074cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
9084cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
9094cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
9104cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
9114cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
91296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == pixels || rowBytes < origInfo.minRowBytes()) {
9134cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9144cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9154cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9164cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
9174cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
9184cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
9194cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9204cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9224cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
9234cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
9244cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9254cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9264cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9274cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
928e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
9294cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9304cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
9314cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
9324cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
9334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9344cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
9354cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
9364cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9374cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
9384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
9394cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9404af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
941c83a29759a5c2966da5ab973e4fd90763e4c962breed    const bool completeOverwrite = info.dimensions() == size;
942c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
9434af35f348b2e2f6c428819118eb7a2f2fff53a74reed
9444cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
9454ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
9464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
94751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9484370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
9494370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
9504370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9514370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
9571f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
9594b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
96096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == layer->fNext) {   // only one layer
96196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            layer->updateMC(totalMatrix, totalClip, *fClipStack, nullptr);
9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
963045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
965687fa1c745febb57f42b0d5f03d7c1f4be2530careed                layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
96696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            } while ((layer = layer->fNext) != nullptr);
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
9752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9762ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
9772ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
9782ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9792ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
980f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
9812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
9822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
9832ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
9842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
9852ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
9862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
9872ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
9882ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
9892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
9902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
9912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
9922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
9932ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
994f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
995f0090cb80ab10a49e511aa5450ae38917fa058d9reed
996f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
9972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
9982ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
9992ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
10002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
10012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
10022ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
1003f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
1004a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
1005a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
1006a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
10072ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1008f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1009f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1010f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
10112ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
10122ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
10132ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
10142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
10152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
10162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
10172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
10182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
10192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
1020a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
10212ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
10222ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
10232ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
1024f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1025f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1026f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1027f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
1028f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
1029f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
1030f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
1031f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1032f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
1033f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
1034f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
1035f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
1036f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1037f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1038f0090cb80ab10a49e511aa5450ae38917fa058d9reed
10392ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
1041d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
10434b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1044687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->save();
10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
1048b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
1050b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#else
1051b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com    return true;
1052b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1055a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.orgbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
10569b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
1057bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
1058bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
1059a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
1060f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1061c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
106296e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
106396e657d0e103b8358a77ecd913f6086929f792b8reed
106487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco// This is a temporary hack, until individual filters can do their own
106587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco// bloating, when this will be removed.
106687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco#ifdef SK_SUPPORT_SRC_BOUNDS_BLOAT_FOR_IMAGEFILTERS
106787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    SkRect storage;
106887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco#endif
1069c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
107096e657d0e103b8358a77ecd913f6086929f792b8reed        imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
107187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco#ifdef SK_SUPPORT_SRC_BOUNDS_BLOAT_FOR_IMAGEFILTERS
107287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (bounds && imageFilter->canComputeFastBounds()) {
107387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            imageFilter->computeFastBounds(*bounds, &storage);
107487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            bounds = &storage;
107587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        } else {
107687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            bounds = nullptr;
107787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
107887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco#endif
1079c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
1080bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
108149f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
10834b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
108496e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
1088bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            if (bounds_affects_clip(flags)) {
10899b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                fCachedLocalClipBoundsDirty = true;
10901f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
1091bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
1092a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1097180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
109989f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org    if (bounds_affects_clip(flags)) {
1100180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
11019b3aa54bc9605257c701cf465813f5fb1d7ba39ereed        fCachedLocalClipBoundsDirty = true;
1102687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
1103180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
1104a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1105a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1106a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
1107a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
1108a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1109a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
1110a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
1111a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1112d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
1113d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
111496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        bounds = nullptr;
1115d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
1116d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
1117a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
111876033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy);
11192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
1120d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1121d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
11222ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
1123d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
112496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        bounds = nullptr;
1125d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
1126e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
1127a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
112876033be81b82c44fd5d4fdf2672eb22e505da1f0reed    this->internalSaveLayer(bounds, paint, flags, strategy);
11292ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
11308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
11318926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
11322ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
113376033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                 SaveLayerStrategy strategy) {
1134b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
11352a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    flags |= kClipToLayer_SaveFlag;
1136b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#endif
1137b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com
1138a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1139a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
11402ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1141a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1142a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
1143a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1144a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
114596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : nullptr)) {
11462ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1149e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1150e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1151e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
11522ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1153e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1154e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
115576033be81b82c44fd5d4fdf2672eb22e505da1f0reed    bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
11568dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
11578dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
115876033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1159daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
116076033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
11618dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1162b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1163b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
116415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
116515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1167b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    SkBaseDevice* device = this->getTopDevice();
116896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == device) {
1169b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
11702ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1171b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1172b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
117361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    bool forceSpriteOnRestore = false;
117461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
1175daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
117661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo);
117761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
117896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == newDev) {
117961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
11809a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry);
11819a53fd7c41554630124522f4b6eedc16912abbb7robertphillips            newDev = SkBitmapDevice::Create(createInfo.fInfo, surfaceProps);
118296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (nullptr == newDev) {
118361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                SkErrorInternals::SetError(kInternalError_SkError,
118461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                           "Unable to create device for layer.");
118561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                return;
118661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            }
118761f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            forceSpriteOnRestore = true;
118861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
118961f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        device = newDev;
1190e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
1191e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
11926f8f292aa768869a9e85c314b124875f57504f2creed@google.com    device->setOrigin(ir.fLeft, ir.fTop);
1193385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    DeviceCM* layer =
1194385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            new DeviceCM(device, paint, this, fConservativeRasterClip, forceSpriteOnRestore);
11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    device->unref();
11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1202d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1203d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org    return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
1204d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1205d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             SaveFlags flags) {
12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (0xFF == alpha) {
120996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return this->saveLayer(bounds, nullptr, flags);
12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPaint tmpPaint;
12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpPaint.setAlpha(alpha);
12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->saveLayer(bounds, &tmpPaint, flags);
12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1221c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1223687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->restore();
12246c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
122588edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
122896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fLayer = nullptr;
12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
123949f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
12416f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
12428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
124361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                     layer->fPaint, layer->fDeviceIsBitmapDevice);
12448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
1246385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete layer;
1247b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1248b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1249a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1250b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
125288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12554a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
125696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == props) {
12574a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
12584a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
12594a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
126076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
126176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
12624a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
126376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
126496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return dev ? dev->newSurface(info, props) : nullptr;
126576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
126676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1267c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1268c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1269c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1270c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1271c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1272900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1273c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1274c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1275c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1276c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1277884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1278884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onPeekPixels(&pmap)) {
127996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1280884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1281884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1282884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1283884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1284884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1285884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1286884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1287884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.addr();
1288c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1289c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1290884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1291c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1292884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1293c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1294c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
12956b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1296884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1297884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
129896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1299884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1300884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1301884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1302884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1303884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1304884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1305884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1306884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
13076b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
13086b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1309884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
13109c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
13119c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1312884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
13139c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1314884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
13159c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
13169c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1317c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
1318c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
131996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fAddr) {
1320c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fInfo = canvas->imageInfo();
1321848250415eddc54075f7eb8795e8db79e749c6abreed        if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
132296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return; // failure, fAddr is nullptr
1323c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1324c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        if (!canvas->readPixels(&fBitmap, 0, 0)) {
132596fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return; // failure, fAddr is nullptr
1326c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        }
1327c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fAddr = fBitmap.getPixels();
1328c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        fRowBytes = fBitmap.rowBytes();
1329c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1330c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkASSERT(fAddr);    // success
1331c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1332c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1333c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgbool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
1334c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (fAddr) {
133500f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
1336c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1337c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        bitmap->reset();
1338c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return false;
1339c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1340c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1341c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1342520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13441f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
134561f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed                                  const SkPaint* paint, bool deviceIsBitmapDevice) {
13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
134796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13518926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13531f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
135476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
135576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
135676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
13578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !dstDev->canHandleImageFilter(filter)) {
135888d064d0e481949184305c7b1d6b282dddffac39reed            SkImageFilter::DeviceProxy proxy(dstDev);
135976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            SkBitmap dst;
13606776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1361b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            const SkBitmap& src = srcDev->accessBitmap(false);
1362fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1363d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
13644cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
1365be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
1366c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            SkImageFilter::Context ctx(matrix, clipBounds, cache.get(),
1367c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed                                       SkImageFilter::kApprox_SizeConstraint);
13684cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
13695efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
137096fcdcc219d2a0d3579719b84b28bede76efba64halcanary                tmpUnfiltered.setImageFilter(nullptr);
13716776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
13726776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                                   tmpUnfiltered);
137376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com            }
137461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        } else if (deviceIsBitmapDevice) {
13759572a10c9a6a868bbb8f71d7806d0a45f183333freed            const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap;
137661f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
137776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1378b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
137976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) {
13850acf1b4b3645772d220c720313821bac389751b5reed    if (gTreatSpriteAsBitmap) {
13860acf1b4b3645772d220c720313821bac389751b5reed        this->save();
13870acf1b4b3645772d220c720313821bac389751b5reed        this->resetMatrix();
13880acf1b4b3645772d220c720313821bac389751b5reed        this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint);
13890acf1b4b3645772d220c720313821bac389751b5reed        this->restore();
13900acf1b4b3645772d220c720313821bac389751b5reed        return;
13910acf1b4b3645772d220c720313821bac389751b5reed    }
13920acf1b4b3645772d220c720313821bac389751b5reed
13939881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()");
139450b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing()) {
13958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        return;
13968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
139750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    SkDEBUGCODE(bitmap.validate();)
1398fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13998926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    SkPaint tmp;
140096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
14018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &tmp;
14028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
1403fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
14048926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1405fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
14068926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (iter.next()) {
14078926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        paint = &looper.paint();
14088926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkImageFilter* filter = paint->getImageFilter();
14098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
14108926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
141188d064d0e481949184305c7b1d6b282dddffac39reed            SkImageFilter::DeviceProxy proxy(iter.fDevice);
14128926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkBitmap dst;
14136776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org            SkIPoint offset = SkIPoint::Make(0, 0);
1414fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            SkMatrix matrix = *iter.fMatrix;
1415d5424a425bc21280afe2161f6ac1e5d9eb97e6b2senorblanco@chromium.org            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1416f622a6c8fd176acf9944de8df00d7f0bb56b67d3halcanary            const SkIRect clipBounds = bitmap.bounds();
1417be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco            SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache());
1418c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            SkImageFilter::Context ctx(matrix, clipBounds, cache.get(),
1419c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed                                       SkImageFilter::kApprox_SizeConstraint);
14204cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org            if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
14215efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                SkPaint tmpUnfiltered(*paint);
142296fcdcc219d2a0d3579719b84b28bede76efba64halcanary                tmpUnfiltered.setImageFilter(nullptr);
14236776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org                iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
14245efe0cb04961ef98fbe520ee732fbe50b4195ad3tomhudson@google.com                                         tmpUnfiltered);
14258926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            }
14268926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        } else {
14278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
14288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
14298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    }
14308926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_END
14318926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
14328926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
143492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1435d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1436d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setTranslate(dx, dy);
1437d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
144092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1441d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1442d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1443d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
144692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1447d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1448d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1449d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
145292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1453d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1454d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1455d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
145644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
145744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
145892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1459d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1460d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1461d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1462d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
14632ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1465c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14661f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
146744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
146844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
146944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
147044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
147186a17e7716c8db858e219a46b9db3817bb770beereedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
147286a17e7716c8db858e219a46b9db3817bb770beereed    this->checkForDeferredSave();
14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1474c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
14751f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
147644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
14808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix matrix;
14814b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.reset();
14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setMatrix(matrix);
14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1488759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
14892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14908f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14918f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
14928f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14938f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
14948f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1495da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1496da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
14971f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1498da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1499da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1500da17f758442f16747af39f8fbaed9c097048519creed@google.com
15013b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1502da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1503c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1504da17f758442f16747af39f8fbaed9c097048519creed@google.com
1505687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
15061f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1507da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1508da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1509da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1510da17f758442f16747af39f8fbaed9c097048519creed@google.com
15115c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15125c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1514c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
15158f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
15168f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
15178f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15191f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.rectStaysRect()) {
1520123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // for these simpler matrices, we can stay a rect even after applying
152198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the matrix. This means we don't have to a) make a path, and b) tell
152298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // the region code to scan-convert the path, only to discover that it
152398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // is really just a rect.
15248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect      r;
15258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15261f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&r, rect);
1527687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1528d954498c01ccf0417feacf89e45d0c62a06a813breed        fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
15298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1530123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
153198de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
153298de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
153398de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
15348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
15358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
15378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
15388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
154173e714eb766617ce06757829a3c0b345c7963faareedstatic void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
154273e714eb766617ce06757829a3c0b345c7963faareed                            SkRegion::Op op, bool doAA) {
1543d64c9487135094c83f658319f53ea2005ecc08b2reed    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1544819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1545819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1546759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
15472ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15488f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
15508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
15518f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
15528f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
15534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
15548f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
155514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
15568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
155714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
15581f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
155914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
156014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
156114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
156214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fCachedLocalClipBoundsDirty = true;
15638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
15648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
15658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
156614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1567687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
156814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
156914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        SkPath devPath;
157014e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        devPath.addRRect(transformedRRect);
157114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
157273e714eb766617ce06757829a3c0b345c7963faareed        rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
15738f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
157414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
157514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
157614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
157714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
157814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
15798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
15804ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
15814ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1582759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
15832ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15848f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15858f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    SkRect r;
15868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!path.isInverseFillType() && path.isRect(&r)) {
15878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(r, op, edgeStyle);
15888f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
15898f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipPath(path, op, edgeStyle);
15908f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
15918f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15928f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15938f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1594da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1595da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
15961f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
1597da17f758442f16747af39f8fbaed9c097048519creed@google.com            return false;
1598da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1599fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
16003b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1601da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1602c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1603fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1604687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
16051f836ee096bb988adef4b9757b2629c7afeda36dreed            return fMCRec->fRasterClip.setEmpty();
1606da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1607da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1608da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1609da17f758442f16747af39f8fbaed9c097048519creed@google.com
16105c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16115c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1613c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
16148f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
16158f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
16168f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
16178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
16191f836ee096bb988adef4b9757b2629c7afeda36dreed    path.transform(fMCRec->fMatrix, &devPath);
16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1621fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1622fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1623fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1624fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1625fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1626fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1627fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1628fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1629fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1630fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
16315c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
1632687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
16335c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
163445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
16351a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        bool clipIsAA = getClipStack()->asPath(&devPath);
16361a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        if (clipIsAA) {
16371a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita            edgeStyle = kSoft_ClipEdgeStyle;
163845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
16391a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita
164045a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
164145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
164245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
164373e714eb766617ce06757829a3c0b345c7963faareed    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
16448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1646759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
16472ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16488f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
16498f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16508f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
16518f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
16525c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16535c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1655c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com    fCachedLocalClipBoundsDirty = true;
16568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16575c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
16585c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1659687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevRect(rgn.getBounds(), op);
16605c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16611f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1664819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1665819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1666819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
16671f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1668ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
16695c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1670ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1671ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1672ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1673819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1674819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1675d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1676819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1677687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
16788182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
167996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    while ((element = iter.next()) != nullptr) {
16808182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
16818182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
16828182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
16838182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
16848182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
16858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
16868182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
16878182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
16889cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
16899cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
16909cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
169173e714eb766617ce06757829a3c0b345c7963faareed                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
16929cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
16939cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1694819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1695819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1696819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1697819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1698819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
169990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
1700687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
17018182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
17028182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
170396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    while ((element = iter.next()) != nullptr) {
1704c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
170590c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
170690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
170790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
17085c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
17095c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1710754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
17111f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1712754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1713754de5f65b466f721d952a379194cc94de376f42reed@google.com
17145c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
17151f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
17165c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17175c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17183b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkRect& rect) const {
17191607863b608b7db6c813228768ed5d72997bbc82reed@google.com    if (!rect.isFinite())
1720116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org        return true;
1721116b2bcd2c4c4d4670c7b7e2ea597414713c37fbwjmaclean@chromium.org
17221f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17261f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fMatrix.hasPerspective()) {
1727a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        SkRect dst;
17281f836ee096bb988adef4b9757b2629c7afeda36dreed        fMCRec->fMatrix.mapRect(&dst, rect);
1729b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1730a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com    } else {
1731c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        const SkRect& clipR = this->getLocalClipBounds();
1732d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
1733a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        // for speed, do the most likely reject compares first
1734c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        // TODO: should we use | instead, or compare all 4 at once?
1735c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1736a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1737a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1738c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1739a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com            return true;
1740a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        }
1741a380ae4a9ac209f5676c06aeaceacc1b08817edareed@android.com        return false;
17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17453b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
17463b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
17478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17493b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1750bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
17518f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
17528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
17538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1755d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1756d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
17571f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
175872dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
175972dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
176072dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1761d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1762d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1763d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
176449f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1765bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
17663b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
17673b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1768fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
17698f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
17708f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
17728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
17748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1776bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
17771f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1778bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1779bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1780bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1781bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1782bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1783bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1784bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
178549f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1786bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1787bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1788bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1789bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1790bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
17918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
17921f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
17938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17955c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
17961f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
17975c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17985c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
17999c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comGrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
18009c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
180196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return dev ? dev->accessRenderTarget() : nullptr;
18029c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
18039c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1804644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1805644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
1806644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
180749f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
1808644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        GrRenderTarget* renderTarget = device->accessRenderTarget();
180949f085dddff10473b6ebf832a974288300224e60bsalomon        if (renderTarget) {
1810644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org            return renderTarget->getContext();
1811644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org        }
1812644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    }
1813644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
1814644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
181596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
1816644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
1817644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1818e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1819ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1820ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
18219881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1822ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1823ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1824ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1825ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1826ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1827ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1828ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1829ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1830ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1831ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1832ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1833ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1834ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1835ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1836ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1837ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1838ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1839ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
184041af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
184141af966ab338e95eee81ab618ab28195075338f7reed
184241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
184341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
184441af966ab338e95eee81ab618ab28195075338f7reed}
184541af966ab338e95eee81ab618ab28195075338f7reed
184641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
184741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
184841af966ab338e95eee81ab618ab28195075338f7reed}
184941af966ab338e95eee81ab618ab28195075338f7reed
185041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
185141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
185241af966ab338e95eee81ab618ab28195075338f7reed}
185341af966ab338e95eee81ab618ab28195075338f7reed
185441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
185541af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
185641af966ab338e95eee81ab618ab28195075338f7reed}
185741af966ab338e95eee81ab618ab28195075338f7reed
185841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
185941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
186041af966ab338e95eee81ab618ab28195075338f7reed}
186141af966ab338e95eee81ab618ab28195075338f7reed
186241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
186341af966ab338e95eee81ab618ab28195075338f7reed                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
186441af966ab338e95eee81ab618ab28195075338f7reed                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
186541af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
186641af966ab338e95eee81ab618ab28195075338f7reed                         indices, indexCount, paint);
186741af966ab338e95eee81ab618ab28195075338f7reed}
186841af966ab338e95eee81ab618ab28195075338f7reed
186941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
187041af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
187141af966ab338e95eee81ab618ab28195075338f7reed}
187241af966ab338e95eee81ab618ab28195075338f7reed
1873a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1874a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
187541af966ab338e95eee81ab618ab28195075338f7reed}
187641af966ab338e95eee81ab618ab28195075338f7reed
1877e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1878e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             const SkPaint* paint, SrcRectConstraint constraint) {
1879e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (dst.isEmpty() || src.isEmpty()) {
1880e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
1881e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1882e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawImageRect(image, &src, dst, paint, constraint);
1883e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
188441af966ab338e95eee81ab618ab28195075338f7reed
188584984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
188684984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1887e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
188884984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
188984984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
1890e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1891e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             SrcRectConstraint constraint) {
1892e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1893e47829b6b1eeb6b0c97ccb3df3016d197046824creed                        constraint);
1894e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1895e47829b6b1eeb6b0c97ccb3df3016d197046824creed
18964c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
18974c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
18984c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
18994c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
19004c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
19014c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) {
1902e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, dst, paint);
19034c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
19044c21dc5ddf3b482293ed34eead876d8d61a662c3reed    this->onDrawImageNine(image, center, dst, paint);
19054c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
19064c21dc5ddf3b482293ed34eead876d8d61a662c3reed
190741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
19084c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
19092df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19102df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
191141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
191241af966ab338e95eee81ab618ab28195075338f7reed}
191341af966ab338e95eee81ab618ab28195075338f7reed
1914e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1915a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1916e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1917a5517e2b190a8083b38964972b031c13e99f1012reed        return;
1918a5517e2b190a8083b38964972b031c13e99f1012reed    }
1919e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
192041af966ab338e95eee81ab618ab28195075338f7reed}
192141af966ab338e95eee81ab618ab28195075338f7reed
192284984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
192384984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1924e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1925e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1926e47829b6b1eeb6b0c97ccb3df3016d197046824creed
1927e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1928e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              SrcRectConstraint constraint) {
1929e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1930e47829b6b1eeb6b0c97ccb3df3016d197046824creed                         constraint);
193184984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
193284984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
193341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
193441af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
19354c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
19362df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19372df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
19384c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) {
1939a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
19404c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
194141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmapNine(bitmap, center, dst, paint);
194241af966ab338e95eee81ab618ab28195075338f7reed}
194341af966ab338e95eee81ab618ab28195075338f7reed
194441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
19454c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
19462df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
19472df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
194841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawSprite(bitmap, left, top, paint);
194941af966ab338e95eee81ab618ab28195075338f7reed}
195041af966ab338e95eee81ab618ab28195075338f7reed
195171c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
195271c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkColor colors[], int count, SkXfermode::Mode mode,
195371c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
195471c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
195571c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
195671c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
195771c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(atlas);
195871c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(xform);
195971c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
196071c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
196171c3c760a83123ee0b3127b8c65c6394ce541c50reed}
196271c3c760a83123ee0b3127b8c65c6394ce541c50reed
1963e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1964e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                    const SkPaint* paint, SrcRectConstraint constraint) {
1965e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1966e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, *src, dst, paint, constraint);
1967e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1968e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1969e47829b6b1eeb6b0c97ccb3df3016d197046824creed                            dst, paint, constraint);
1970e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1971e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1972e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1973e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                     const SkPaint* paint, SrcRectConstraint constraint) {
1974e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1975e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1976e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1977e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1978e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             dst, paint, constraint);
1979e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1980e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1981e47829b6b1eeb6b0c97ccb3df3016d197046824creed
19828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
19848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
198749f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
198828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
198928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
199028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
199128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
199241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
19939881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1994fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1995fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1996fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1997fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
199896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
19998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
200741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
200841af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
20099881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
20108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
20118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
201478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
201596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2016a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
2017a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
2018a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
2019a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
2020a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
2021a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
2022a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
202387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
202487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
202587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
202687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
2027fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
2028a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
202996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(pts != nullptr);
20308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
203178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
20324b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20344e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
20358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20374e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
204041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
20419881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
204278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
204396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
20448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
20458432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
20468432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
20478432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
20488432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
20498432808ad8898ac7137bc7ce1d9df6005e866401reed
205087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
205187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
205287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
205387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
20548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20554b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2056c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false)
20578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
20594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawRect(iter, r, looper.paint());
20608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20624e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
206541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
20669881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
206778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
206896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
20694ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
207087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
207187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
207287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
207387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &oval;
20744ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2075306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
207678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
207746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
207846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
207946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
208046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
208146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
208246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
20834ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20844ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
208541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
20869881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
208778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
208896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
20894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
209087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
209187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
209287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
209387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &rrect.getBounds();
20944ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
20954ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
20964ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
20974ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
20984ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2099f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2100f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
21014ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2102f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2103f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
21044ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2105f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
210678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2107f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2108f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2109f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2110f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2111f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2112f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
21134ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
21144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2115ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2116ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
2117ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
211896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2119ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
212087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
212187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
212287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
212387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &outer.getBounds();
2124ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
212525c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2126ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
212725c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2128ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2129ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2130ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
213125c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2132ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2133ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
21344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
213541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
21369881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
21379364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
21389364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
21399364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
21409364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
214178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
214296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2143fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
214478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
214587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
214687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
214787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
214887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &pathBounds;
21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21500b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
21510b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
21520b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
21536803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2154fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
21556651a3238dd6affa4276ada42ab613abf1d42d1dcaryclark            return;
2156fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2157fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
21588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
215978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
21608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21624e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
21638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2168a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
21699881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2170a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2171a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
217296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
217387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = bounds;
217487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
217587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(tmp, &tmp);
217687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
217787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(tmp)) {
217887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
217987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2180a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2181a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2182a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
218396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2184a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2185a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2186a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2187a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds)
2188a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2189a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2190a85d4d0814818e4ddabb9237da209d61d6cd5854reed        iter.fDevice->drawImage(iter, image, x, y, looper.paint());
2191a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2192a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2193a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2194b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2195b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
219641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2197562fe4767cc73e08a4e039362bc0336aea66ecfbreed                               const SkPaint* paint, SrcRectConstraint constraint) {
21989881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2199a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect storage;
2200a85d4d0814818e4ddabb9237da209d61d6cd5854reed    const SkRect* bounds = &dst;
220196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
220287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        storage = dst;
220387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
220487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(dst, &storage);
220587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
220687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(storage)) {
220787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
220887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2209a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2210a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
221196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2212a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2213a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2214a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2215c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, bounds,
2216c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
2217a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2218a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2219a5517e2b190a8083b38964972b031c13e99f1012reed        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
2220a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2221a85d4d0814818e4ddabb9237da209d61d6cd5854reed
2222a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2223b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2224b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
222541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
22269881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
22278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
22288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
222933366974d43eae80e22284a2e445225c343859dareed    if (bitmap.drawsNothing()) {
223033366974d43eae80e22284a2e445225c343859dareed        return;
223133366974d43eae80e22284a2e445225c343859dareed    }
223233366974d43eae80e22284a2e445225c343859dareed
223333366974d43eae80e22284a2e445225c343859dareed    SkLazyPaint lazy;
223433366974d43eae80e22284a2e445225c343859dareed    if (nullptr == paint) {
223533366974d43eae80e22284a2e445225c343859dareed        paint = lazy.init();
223633366974d43eae80e22284a2e445225c343859dareed    }
223733366974d43eae80e22284a2e445225c343859dareed
223833366974d43eae80e22284a2e445225c343859dareed    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
223933366974d43eae80e22284a2e445225c343859dareed
224033366974d43eae80e22284a2e445225c343859dareed    SkRect storage;
224133366974d43eae80e22284a2e445225c343859dareed    const SkRect* bounds = nullptr;
224233366974d43eae80e22284a2e445225c343859dareed    if (paint->canComputeFastBounds()) {
224333366974d43eae80e22284a2e445225c343859dareed        bitmap.getBounds(&storage);
224433366974d43eae80e22284a2e445225c343859dareed        matrix.mapRect(&storage);
224587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = storage;
224687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) {
224787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
224887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
224987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
22508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22514b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
225233366974d43eae80e22284a2e445225c343859dareed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
225333366974d43eae80e22284a2e445225c343859dareed
225433366974d43eae80e22284a2e445225c343859dareed    while (iter.next()) {
225533366974d43eae80e22284a2e445225c343859dareed        iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
225633366974d43eae80e22284a2e445225c343859dareed    }
225733366974d43eae80e22284a2e445225c343859dareed
225833366974d43eae80e22284a2e445225c343859dareed    LOOPER_END
22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22619987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
22627112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2263eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2264a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
226550b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
22668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
22678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
226874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
226978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
227078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    const SkRect* bounds = &dst;
227196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
227287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
227387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
227487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22763d60812865bb034851da777a91413ab584929887reed@google.com
227733535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
227896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
227933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
22808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22817064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2282c83a29759a5c2966da5ab973e4fd90763e4c962breed    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, bounds,
2283c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
22847064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
228533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2286562fe4767cc73e08a4e039362bc0336aea66ecfbreed        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
2287f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
22887064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
228933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
22908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
229241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2293562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                const SkPaint* paint, SrcRectConstraint constraint) {
22949881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
22959987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2296562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
22979987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
22989987ec3791336bad6af5cbe513564786b2df55aareed@google.com
22994c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
23004c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
23014c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
23024c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23034c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkRect storage;
23044c21dc5ddf3b482293ed34eead876d8d61a662c3reed    const SkRect* bounds = &dst;
230596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
230687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
230787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
230887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23093d60812865bb034851da777a91413ab584929887reed@google.com    }
23104c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23114c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
231296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
23134c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23144c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23154c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23164c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
23174c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23184c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
23194c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
23209987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
23214c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23224c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23239987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23249987ec3791336bad6af5cbe513564786b2df55aareed@google.com
232541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
232641af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
23279881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
23289987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
23299987ec3791336bad6af5cbe513564786b2df55aareed@google.com
23304c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkRect storage;
23314c21dc5ddf3b482293ed34eead876d8d61a662c3reed    const SkRect* bounds = &dst;
233296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
233387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
233487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
233587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23364c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23374c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23384c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
233996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
23404c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23414c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23424c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23434c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
23444c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23454c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
23464c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
23474c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23484c21dc5ddf3b482293ed34eead876d8d61a662c3reed
23494c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23509987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23519987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2352f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2353f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
23541f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2355112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2356112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2357a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2358112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2359f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2360f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2361f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2362f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2363f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2364f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2365f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2366f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2367f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
23682c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
23692c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2370f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2371f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
237252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
237352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
237417b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
237552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
237652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
237752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
237817b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
237952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
238052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
238152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
238252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
238352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
238452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
238552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
238696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(byteLength == 0 || text != nullptr);
238752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
238852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
238996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (text == nullptr || byteLength == 0 ||
239052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fClip->isEmpty() ||
239196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) {
239252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
239352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
239452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
239552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
239652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
239752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
239852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
239952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
240052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
240152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
240252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
240352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
240452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
240552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
240652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
240752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
240852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
240952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
241052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
241152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
241252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
241352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
241452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
241552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
241652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
241752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
241852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
241952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
242052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
242152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
242252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
242352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
242452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
242552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
242652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
242752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
242852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
242952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
243052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
243152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
243252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
243352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
243452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
243552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
243652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
243752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
243852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
243952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            DrawRect(draw, paint, r, textSize);
244052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
244152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
244252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
244352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2444e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2445e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
244696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
24478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24494e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2450f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
245152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
245252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
24538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2458e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2459e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
246005c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
246105c4a4322e7d4f3417b7df33825bab8603d52051fmalita
246296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
246387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
246605c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2467f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2469b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2473e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2474e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
247505c4a4322e7d4f3417b7df33825bab8603d52051fmalita
247605c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
247705c4a4322e7d4f3417b7df33825bab8603d52051fmalita
247896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
247987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
248205c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2483f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2485b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2489e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2490e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
249196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
249287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
24954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
24968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2497b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2498945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
24994325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
25004325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
250100d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
250200d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
25037ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
250485d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
250596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
250619653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
250785d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
250887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp;
250987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
251087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
251187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
251287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
25137ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
25147ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2515024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2516024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2517024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
251896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fFilter = nullptr;
2519024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
252085d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
252100d5c2c6523321d25b32905ff4822f083a4173eefmalita
2522aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2523aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2524024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
252500d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
252600d5c2c6523321d25b32905ff4822f083a4173eefmalita
2527aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2528024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2529024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
253000d5c2c6523321d25b32905ff4822f083a4173eefmalita}
253100d5c2c6523321d25b32905ff4822f083a4173eefmalita
2532e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2533e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2534e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
25359881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2536e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawText(text, byteLength, x, y, paint);
2537e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2538e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2539e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
25409881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2541e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosText(text, byteLength, pos, paint);
2542e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2543e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2544e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
25459881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2546e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2547e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2548e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2549e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
25509881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2551e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2552e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
255300d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
255400d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
25559881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
255649f085dddff10473b6ebf832a974288300224e60bsalomon    if (blob) {
255700d5c2c6523321d25b32905ff4822f083a4173eefmalita        this->onDrawTextBlob(blob, x, y, paint);
255800d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
255900d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2560e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
256141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
256241af966ab338e95eee81ab618ab28195075338f7reed                              const SkPoint verts[], const SkPoint texs[],
256341af966ab338e95eee81ab618ab28195075338f7reed                              const SkColor colors[], SkXfermode* xmode,
256441af966ab338e95eee81ab618ab28195075338f7reed                              const uint16_t indices[], int indexCount,
256541af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint& paint) {
25669881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
256796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
25684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
25708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
25714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
25724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
25738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25744b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
25754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2578b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2579b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
25809881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
258196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == cubics) {
2582b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2583b3c9d1c33caf325aada244204215eb790c228c12dandov    }
25846cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2585ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2586ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2587ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2588b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2589ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2590ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2591ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
25926cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2593b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2594b3c9d1c33caf325aada244204215eb790c228c12dandov}
2595b3c9d1c33caf325aada244204215eb790c228c12dandov
2596b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2597b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2598b3c9d1c33caf325aada244204215eb790c228c12dandov
259996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
26006cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2601ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2602b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2603ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26046cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2605ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2606ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2607ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2608a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2609a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (dr) {
2610a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        if (x || y) {
2611a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2612a8db72864a43ad1fbba3c2892cf5cd88060a43efreed            this->onDrawDrawable(dr, &matrix);
2613a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        } else {
261496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            this->onDrawDrawable(dr, nullptr);
2615a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        }
2616a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2617a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
2618a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
2619a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2620a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (dr) {
2621a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        if (matrix && matrix->isIdentity()) {
262296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            matrix = nullptr;
2623a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        }
2624a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        this->onDrawDrawable(dr, matrix);
26256a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
26266a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26276a070dc06af4e9f305f9d08a69e34d18ade473cbreed
2628a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2629a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    SkRect bounds = dr->getBounds();
2630a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (matrix) {
2631a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        matrix->mapRect(&bounds);
2632a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2633a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (this->quickReject(bounds)) {
2634a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        return;
2635a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2636a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
26376a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26386a070dc06af4e9f305f9d08a69e34d18ade473cbreed
263971c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
264071c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkColor colors[], int count, SkXfermode::Mode mode,
264171c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
264271c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
264371c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
264471c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
264571c3c760a83123ee0b3127b8c65c6394ce541c50reed
264671c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
264771c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
264871c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
264971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
265071c3c760a83123ee0b3127b8c65c6394ce541c50reed
265196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
265271c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
265371c3c760a83123ee0b3127b8c65c6394ce541c50reed        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt);
265471c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
265571c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
265671c3c760a83123ee0b3127b8c65c6394ce541c50reed}
265771c3c760a83123ee0b3127b8c65c6394ce541c50reed
26588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
26598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
26608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
26618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
26628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2664845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
26659881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
26668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2669845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
26700baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
26718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
26738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2675845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
26769881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
26778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2680845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
26810baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
26828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
26848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
26879881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
26888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
26894b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
26918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
26928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
26959881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
26968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
26978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
26984b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
26998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
27008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
27018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
27028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
27058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
27069881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
27078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
27084b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
27108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
27118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
27128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
27158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
27168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
27179881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
27188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
27198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
27218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
27228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
27258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
27269881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
27278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
27288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
27298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
27328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
27334ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
27348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
27378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
27389881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
27398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
27408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (paint.canComputeFastBounds()) {
27418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRect storage;
27423b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
27438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return;
27448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
27458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
27464ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
27474ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
27484ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
27498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
27508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
27518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
27558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
27568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
27579881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
27588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
27598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawOval(oval, paint);
27608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
27618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
27628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
27638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.moveTo(oval.centerX(), oval.centerY());
27648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
27658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
27668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (useCenter) {
27678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            path.close();
27688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
27698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawPath(path, paint);
27708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
27748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
27758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
27769881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
27778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
27784b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
27808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
27818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2783f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
27841c2c441fede0ae9573afc098017011e3439624a9reed
27851c2c441fede0ae9573afc098017011e3439624a9reed/**
27861c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
27871c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
27881c2c441fede0ae9573afc098017011e3439624a9reed *
27891c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
27901c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
27911c2c441fede0ae9573afc098017011e3439624a9reed */
27921c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
27939b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2794d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
27951c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
279649f085dddff10473b6ebf832a974288300224e60bsalomon    if (picture) {
2797d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix && matrix->isIdentity()) {
279896fcdcc219d2a0d3579719b84b28bede76efba64halcanary            matrix = nullptr;
2799d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
28001c2c441fede0ae9573afc098017011e3439624a9reed        if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
28011c2c441fede0ae9573afc098017011e3439624a9reed            SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
28021c2c441fede0ae9573afc098017011e3439624a9reed            picture->playback(this);
28031c2c441fede0ae9573afc098017011e3439624a9reed        } else {
28041c2c441fede0ae9573afc098017011e3439624a9reed            this->onDrawPicture(picture, matrix, paint);
28051c2c441fede0ae9573afc098017011e3439624a9reed        }
2806d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2807d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
28089b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2809d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2810d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2811d028180f0310cf2b23f9744256a41697b0683e67fmalita    if (!paint || paint->canComputeFastBounds()) {
2812d028180f0310cf2b23f9744256a41697b0683e67fmalita        SkRect bounds = picture->cullRect();
2813d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (paint) {
2814d028180f0310cf2b23f9744256a41697b0683e67fmalita            paint->computeFastBounds(bounds, &bounds);
2815d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2816d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (matrix) {
2817d028180f0310cf2b23f9744256a41697b0683e67fmalita            matrix->mapRect(&bounds);
2818d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2819d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (this->quickReject(bounds)) {
2820d028180f0310cf2b23f9744256a41697b0683e67fmalita            return;
2821d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2822d028180f0310cf2b23f9744256a41697b0683e67fmalita    }
2823d028180f0310cf2b23f9744256a41697b0683e67fmalita
2824145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
282549f085dddff10473b6ebf832a974288300224e60bsalomon    if (device) {
2826145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // Canvas has to first give the device the opportunity to render
2827145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        // the picture itself.
2828d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2829145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org            return; // the device has rendered the entire picture
2830145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org        }
2831145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org    }
2832145d1c0fdcef63991d7f910cc067a653a8aa2c4ccommit-bot@chromium.org
2833a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2834c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
28358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
28388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
28398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
284199fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
28428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
28448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
28468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
28478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
28508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
28518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
28548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
28558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28571f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
28588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
28598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
28628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
28638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
28668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
286796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
28688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
28698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
28718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
28748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
28758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
287620a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
287720a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
287820a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
2879c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
28803107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28813107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
28823107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28833107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
28843107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
28853107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
28863107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
28873107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28883107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28893107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28903107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28913107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28923107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
28933107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
28943107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
289528fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
28963107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28973107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28983107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28993107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
29003107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
29013107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
29023107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
29033107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
290442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
290542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
290696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
290742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2908eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
290942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
291042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
291196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
291242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2913385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkCanvas(bitmap);
291442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2915d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2916d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2917d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2918d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2919a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2920d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2921d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2922d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
292349f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2924a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2925d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2926a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2927d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2928a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
292949f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2930d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2931d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
29326cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
293349f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2934d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2935d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2936d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2937d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2938d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2939d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2940d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2941