SkCanvas.cpp revision 3661bc997620899695041010a750d11dbe8a972d
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
873fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby#include "SkArenaAlloc.h"
9986480a71f4e860663ced7ad90a1fe346a164afbMike Reed#include "SkBitmapDevice.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
11d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
12d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkClipStack.h"
13dbc3cefb0b624808ddb86d444e6103f216e12fa5reed#include "SkColorFilter.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
153cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
18b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
19262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkImage_Base.h"
20900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilter.h"
21900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilterCache.h"
22c573a40ed5024b463e47088d307e3164a486dba5msarett#include "SkLatticeIter.h"
235df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed#include "SkMakeUnique.h"
24262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkMatrixUtils.h"
2574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
26ee424acbb87bf999be132a437527e656e37541d7Florin Malita#include "SkNoDrawCanvas.h"
27fbfa25802709139c2f14e304319c9541da65ca27msarett#include "SkNx.h"
28c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
29b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
31b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack#include "SkRadialShadowMapShader.h"
320017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
33356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#include "SkRasterHandleAllocator.h"
344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
35904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack#include "SkShadowPaintFilterCanvas.h"
36904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack#include "SkShadowShader.h"
374418dbac3386f26c8da62ab242be9c178961eb18robertphillips#include "SkSpecialImage.h"
3897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
397ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
4052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
41a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
428f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
43d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include <new>
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
467354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#include "GrContext.h"
47644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
48614d8f9a3c44e22d77fa909e82119e8a6746e1b1bsalomon#include "SkGrPriv.h"
49e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack
50644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
51ebfce6d9b42198e04288a15953f40c395a7b6139Mike Reed#include "SkClipOpPriv.h"
52199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon#include "SkVertices.h"
53644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
54e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed#define RETURN_ON_NULL(ptr)     do { if (nullptr == (ptr)) return; } while (0)
55e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
56c83a29759a5c2966da5ab973e4fd90763e4c962breed/*
57c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Return true if the drawing this rect would hit every pixels in the canvas.
58c83a29759a5c2966da5ab973e4fd90763e4c962breed *
59c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Returns false if
60c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - rect does not contain the canvas' bounds
61c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint is not fill
62c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint would blur or otherwise change the coverage of the rect
63c83a29759a5c2966da5ab973e4fd90763e4c962breed */
64c83a29759a5c2966da5ab973e4fd90763e4c962breedbool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
65c83a29759a5c2966da5ab973e4fd90763e4c962breed                                           ShaderOverrideOpacity overrideOpacity) const {
6699fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
6799fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNone_ShaderOverrideOpacity,
6899fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums0");
6999fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
7099fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kOpaque_ShaderOverrideOpacity,
7199fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums1");
7299fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
7399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNotOpaque_ShaderOverrideOpacity,
7499fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums2");
75c83a29759a5c2966da5ab973e4fd90763e4c962breed
76c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkISize size = this->getBaseLayerSize();
77c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
78c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (!this->getClipStack()->quickContains(bounds)) {
79c83a29759a5c2966da5ab973e4fd90763e4c962breed        return false;
80c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
81c83a29759a5c2966da5ab973e4fd90763e4c962breed
82c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (rect) {
83c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        if (!this->getTotalMatrix().isScaleTranslate()) {
84c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
85c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
86c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary
87c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        SkRect devRect;
88c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        this->getTotalMatrix().mapRectScaleTranslate(&devRect, *rect);
89c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        if (!devRect.contains(bounds)) {
90c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
91c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
92c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
93c83a29759a5c2966da5ab973e4fd90763e4c962breed
94c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (paint) {
95c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkPaint::Style paintStyle = paint->getStyle();
96c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!(paintStyle == SkPaint::kFill_Style ||
97c83a29759a5c2966da5ab973e4fd90763e4c962breed              paintStyle == SkPaint::kStrokeAndFill_Style)) {
98c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
99c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
100c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (paint->getMaskFilter() || paint->getLooper()
101c83a29759a5c2966da5ab973e4fd90763e4c962breed            || paint->getPathEffect() || paint->getImageFilter()) {
102c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
103c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
104c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
105c83a29759a5c2966da5ab973e4fd90763e4c962breed    return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
106c83a29759a5c2966da5ab973e4fd90763e4c962breed}
107c83a29759a5c2966da5ab973e4fd90763e4c962breed
108c83a29759a5c2966da5ab973e4fd90763e4c962breed///////////////////////////////////////////////////////////////////////////////////////////////////
109c83a29759a5c2966da5ab973e4fd90763e4c962breed
110d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
111d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
112d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
113d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
114d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
115d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
116d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
117d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
1180acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
1190acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
1200acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
1210acf1b4b3645772d220c720313821bac389751b5reed}
1220acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
1230acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
1240acf1b4b3645772d220c720313821bac389751b5reed}
1250acf1b4b3645772d220c720313821bac389751b5reed
126da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1502c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
1512c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
152c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(bool willOverwritesEntireSurface) {
15397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
154c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
155c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  ? SkSurface::kDiscard_ContentChangeMode
156c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  : SkSurface::kRetain_ContentChangeMode);
157c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
158c83a29759a5c2966da5ab973e4fd90763e4c962breed}
159c83a29759a5c2966da5ab973e4fd90763e4c962breed
160c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
161c83a29759a5c2966da5ab973e4fd90763e4c962breed                             ShaderOverrideOpacity overrideOpacity) {
162c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (fSurfaceBase) {
163c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode;
164c83a29759a5c2966da5ab973e4fd90763e4c962breed        // Since willOverwriteAllPixels() may not be complete free to call, we only do so if
165c83a29759a5c2966da5ab973e4fd90763e4c962breed        // there is an outstanding snapshot, since w/o that, there will be no copy-on-write
166c83a29759a5c2966da5ab973e4fd90763e4c962breed        // and therefore we don't care which mode we're in.
167c83a29759a5c2966da5ab973e4fd90763e4c962breed        //
168c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (fSurfaceBase->outstandingImageSnapshot()) {
169c83a29759a5c2966da5ab973e4fd90763e4c962breed            if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) {
170c83a29759a5c2966da5ab973e4fd90763e4c962breed                mode = SkSurface::kDiscard_ContentChangeMode;
171c83a29759a5c2966da5ab973e4fd90763e4c962breed            }
172c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
173c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(mode);
17497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
17597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
17697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1791f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM*           fNext;
1881f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice*       fDevice;
189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkRasterClip        fClip;
1906f8f292aa768869a9e85c314b124875f57504f2creed@google.com    SkPaint*            fPaint; // may be null (in the future)
19161f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    const SkMatrix*     fMatrix;
19261f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    SkMatrix            fMatrixStorage;
1938c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix            fStashedMatrix; // original CTM; used by imagefilter in saveLayer
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19596e657d0e103b8358a77ecd913f6086929f792b8reed    DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
1967503d60847c4ad22df87458aecd917772b23d293reed             bool conservativeRasterClip, const SkMatrix& stashed)
19796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        : fNext(nullptr)
198d954498c01ccf0417feacf89e45d0c62a06a813breed        , fClip(conservativeRasterClip)
1998c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        , fStashedMatrix(stashed)
200d954498c01ccf0417feacf89e45d0c62a06a813breed    {
2012c9e20055be772feb3f44986c1af0c0a979eff49reed        SkSafeRef(device);
2024b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com        fDevice = device;
20396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = paint ? new SkPaint(*paint) : nullptr;
20488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    ~DeviceCM() {
2072c9e20055be772feb3f44986c1af0c0a979eff49reed        SkSafeUnref(fDevice);
208385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fPaint;
20988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
2104b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
211feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
212feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
213feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
214feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
215feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
216feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
217feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
219de6c531e468197bb7746f1217a8ccb2ab175e0b8reed                  SkRasterClip* updateClip) {
2206f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int x = fDevice->getOrigin().x();
2216f8f292aa768869a9e85c314b124875f57504f2creed@google.com        int y = fDevice->getOrigin().y();
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int width = fDevice->width();
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = fDevice->height();
2244b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((x | y) == 0) {
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &totalMatrix;
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fClip = totalClip;
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage = totalMatrix;
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrixStorage.postTranslate(SkIntToScalar(-x),
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                         SkIntToScalar(-y));
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = &fMatrixStorage;
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
236045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
239c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        SkASSERT(*fMatrix == fDevice->ctm());
240c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // TODO: debug tiles-rt-8888 so we can enable this all the time
241c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed//        fDevice->validateDevBounds(fClip.getBounds());
242c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
243c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
2454b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
247045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
258f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2701f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
271d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2782ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    DeviceCM*       fTopLayer;
2792ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRasterClip    fRasterClip;
2802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkMatrix        fMatrix;
2812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int             fDeferredSaveCount;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
283e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    // This is the current cumulative depth (aggregate of all done translateZ calls)
284e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    SkScalar        fCurDrawDepth;
285e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
286d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
28796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fFilter     = nullptr;
28896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer      = nullptr;
28996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fTopLayer   = nullptr;
2902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
2912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
292e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack        fCurDrawDepth      = 0;
293b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
294d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
295d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
296d954498c01ccf0417feacf89e45d0c62a06a813breed    }
297e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix),
298e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack                               fCurDrawDepth(prev.fCurDrawDepth) {
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
32302f9ed74ead11fcb01a24faa7d93f853e869f1abreedstatic SkIRect compute_device_bounds(SkBaseDevice* device) {
32402f9ed74ead11fcb01a24faa7d93f853e869f1abreed    return SkIRect::MakeXYWH(device->getOrigin().x(), device->getOrigin().y(),
32502f9ed74ead11fcb01a24faa7d93f853e869f1abreed                             device->width(), device->height());
32602f9ed74ead11fcb01a24faa7d93f853e869f1abreed}
32702f9ed74ead11fcb01a24faa7d93f853e869f1abreed
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
33099330ba6227137866a0dbd63478d36f335203ebdMike Reed    SkDrawIter(SkCanvas* canvas) : fDevice(nullptr) {
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3336bd5284415bd983b0628c4941dff5def40018f5abungeman        fClipStack = canvas->getClipStack();
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
33502f9ed74ead11fcb01a24faa7d93f853e869f1abreed
33602f9ed74ead11fcb01a24faa7d93f853e869f1abreed        fMultiDeviceCS = nullptr;
33702f9ed74ead11fcb01a24faa7d93f853e869f1abreed        if (fCurrLayer->fNext) {
3386bd5284415bd983b0628c4941dff5def40018f5abungeman            fMultiDeviceCS = canvas->fClipStack.get();
33902f9ed74ead11fcb01a24faa7d93f853e869f1abreed            fMultiDeviceCS->save();
34002f9ed74ead11fcb01a24faa7d93f853e869f1abreed        }
341d519d484949161df6d4b2ecadc282427cab532cfMike Reed#ifdef SK_USE_DEVICE_CLIPPING
342d519d484949161df6d4b2ecadc282427cab532cfMike Reed        fClipStack = nullptr;   // for testing
343d519d484949161df6d4b2ecadc282427cab532cfMike Reed#endif
34402f9ed74ead11fcb01a24faa7d93f853e869f1abreed    }
34502f9ed74ead11fcb01a24faa7d93f853e869f1abreed
34602f9ed74ead11fcb01a24faa7d93f853e869f1abreed    ~SkDrawIter() {
34702f9ed74ead11fcb01a24faa7d93f853e869f1abreed        if (fMultiDeviceCS) {
34802f9ed74ead11fcb01a24faa7d93f853e869f1abreed            fMultiDeviceCS->restore();
34902f9ed74ead11fcb01a24faa7d93f853e869f1abreed        }
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3514b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
35302f9ed74ead11fcb01a24faa7d93f853e869f1abreed        if (fMultiDeviceCS && fDevice) {
35402f9ed74ead11fcb01a24faa7d93f853e869f1abreed            // remove the previous device's bounds
355c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed            fMultiDeviceCS->clipDevRect(compute_device_bounds(fDevice), kDifference_SkClipOp);
35602f9ed74ead11fcb01a24faa7d93f853e869f1abreed        }
35702f9ed74ead11fcb01a24faa7d93f853e869f1abreed
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
3593aafe111b6cc388400092851cc53bbbdfcb8a81creed        while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
3603aafe111b6cc388400092851cc53bbbdfcb8a81creed            fCurrLayer = fCurrLayer->fNext;
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
363f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
364f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
367045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
36941e010cb901c0da9066c4df562030808c9ccd7f8reed            if (!fDevice->accessPixels(&fDst)) {
37096fcdcc219d2a0d3579719b84b28bede76efba64halcanary                fDst.reset(fDevice->imageInfo(), nullptr, 0);
37141e010cb901c0da9066c4df562030808c9ccd7f8reed            }
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
373f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
37696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // fCurrLayer may be nullptr now
377199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3824b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3831e7f5e708e5daeb0c18ae49001c9e3cd5e3b13cbreed    const SkRasterClip& getClip() const { return *fRC; }
3846f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3856f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3886f8f292aa768869a9e85c314b124875f57504f2creed@google.com
38999330ba6227137866a0dbd63478d36f335203ebdMike Reed    SkBaseDevice*   fDevice;
39099330ba6227137866a0dbd63478d36f335203ebdMike Reed
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
39402f9ed74ead11fcb01a24faa7d93f853e869f1abreed    SkClipStack*    fMultiDeviceCS;
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3997627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#define FOR_EACH_TOP_DEVICE( code )                 \
4007627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    do {                                            \
4017627fa51044e35dc21251f925b56f6dd6887df97Mike Reed        DeviceCM* layer = fMCRec->fTopLayer;        \
4027627fa51044e35dc21251f925b56f6dd6887df97Mike Reed        while (layer) {                             \
4037627fa51044e35dc21251f925b56f6dd6887df97Mike Reed            SkBaseDevice* device = layer->fDevice;  \
404c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            if (device) {                           \
405c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed                code;                               \
406c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            }                                       \
4077627fa51044e35dc21251f925b56f6dd6887df97Mike Reed            layer = layer->fNext;                   \
4087627fa51044e35dc21251f925b56f6dd6887df97Mike Reed        }                                           \
4097627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    } while (0)
4107627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
413dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
414dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
415dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
416dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
417dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
418dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
41996fcdcc219d2a0d3579719b84b28bede76efba64halcanary *  colorfilter, else return nullptr.
420dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
421d053ce9c54d4e5937a142278359e5a4cde18095ereedstatic sk_sp<SkColorFilter> image_to_color_filter(const SkPaint& paint) {
422dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
423dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
42496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
425dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
426dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
427d053ce9c54d4e5937a142278359e5a4cde18095ereed    SkColorFilter* imgCFPtr;
428d053ce9c54d4e5937a142278359e5a4cde18095ereed    if (!imgf->asAColorFilter(&imgCFPtr)) {
42996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
430dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
431d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> imgCF(imgCFPtr);
432dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
433dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
43496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paintCF) {
435dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
436dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
437dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
438dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
439dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
440dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
441d053ce9c54d4e5937a142278359e5a4cde18095ereed    return SkColorFilter::MakeComposeFilter(std::move(imgCF), sk_ref_sp(paintCF));
442dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
443dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
44487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco/**
44587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * There are many bounds in skia. A circle's bounds is just its center extended by its radius.
44687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * However, if we stroke a circle, then the "bounds" of that is larger, since it will now draw
44787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * outside of its raw-bounds by 1/2 the stroke width.  SkPaint has lots of optional
44887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * effects/attributes that can modify the effective bounds of a given primitive -- maskfilters,
44987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * patheffects, stroking, etc.  This function takes a raw bounds and a paint, and returns the
45087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * conservative "effective" bounds based on the settings in the paint... with one exception. This
45187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * function does *not* look at the imagefilter, which can also modify the effective bounds. It is
45287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * deliberately ignored.
45387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco */
45487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblancostatic const SkRect& apply_paint_to_bounds_sans_imagefilter(const SkPaint& paint,
45587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            const SkRect& rawBounds,
45687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            SkRect* storage) {
45787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    SkPaint tmpUnfiltered(paint);
45887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    tmpUnfiltered.setImageFilter(nullptr);
45987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    if (tmpUnfiltered.canComputeFastBounds()) {
46087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return tmpUnfiltered.computeFastBounds(rawBounds, storage);
46187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    } else {
46287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return rawBounds;
46387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    }
46487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco}
46587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
46887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the
46987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // paint. It's used to determine the size of the offscreen layer for filters.
47087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // If null, the clip will be used instead.
4713aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, bool skipLayerForImageFilter = false,
47287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                   const SkRect* rawBounds = nullptr) : fOrigPaint(paint) {
4734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
47453d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
4767765000709dc64eb23be7df47d1f995d1f787115fmalita#else
4777765000709dc64eb23be7df47d1f995d1f787115fmalita        fFilter = nullptr;
4787765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
4794a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
4804e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
4815c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
4824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
484d053ce9c54d4e5937a142278359e5a4cde18095ereed        auto simplifiedCF = image_to_color_filter(fOrigPaint);
485dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
486dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
487d053ce9c54d4e5937a142278359e5a4cde18095ereed            paint->setColorFilter(std::move(simplifiedCF));
48896fcdcc219d2a0d3579719b84b28bede76efba64halcanary            paint->setImageFilter(nullptr);
489dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
490dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
491dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
492dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
4935c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
4945c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
4955c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
4965c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
4975c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
4985c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
4995c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
5005c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
5015c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
5025c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
5035c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
5045c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
5055c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
5065c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
5075c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
5088926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
509693fdbd6b81a860657612e7604430dd55d6e721bMike Reed            tmp.setImageFilter(fPaint->refImageFilter());
510374772bd61951f01bf84fe17bf53d8867681c9aereed            tmp.setBlendMode(fPaint->getBlendMode());
51187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            SkRect storage;
51287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            if (rawBounds) {
51387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                // Make rawBounds include all paint outsets except for those due to image filters.
51487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage);
51587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            }
516bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed            (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp),
51776033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
5185c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
5195c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
5208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
5218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
52279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
52373fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby            fLooperContext = looper->makeContext(canvas, &fAlloc);
524129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
525129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
52696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fLooperContext = nullptr;
527129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
5285c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
53174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5324e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
5335c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
5348926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
5358926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
5364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
53874b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5394e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
5404e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
5414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
5424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
54374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
544129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
545129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
546129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
547129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
548129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
549129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
550129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
551129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
552129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
553fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
55474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
55673fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    SkLazyPaint     fLazyPaintInit;       // base paint storage in case we need to modify it
557dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
5582c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
5592c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
5602c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
5612c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
5622c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
5635c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
5642c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
565129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
56679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
56773fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    char            fStorage[48];
56873fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    SkArenaAlloc    fAlloc {fStorage};
569129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
570129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
573129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
57496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fPaint = nullptr;
575129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5765c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
577632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
578dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
579dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5808926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5815c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
58296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setImageFilter(nullptr);
583374772bd61951f01bf84fe17bf53d8867681c9aereed        paint->setBlendMode(SkBlendMode::kSrcOver);
584129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
58679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
587129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
588129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
589129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
590129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
591971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
592971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
593971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
594971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
59596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fLooperContext) {
596129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
597632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
598632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
599129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
600129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
6018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
602129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
60379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
6044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
6054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
6064e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
607632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
608632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
60996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = nullptr;
6104e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
6114e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
6124e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
6134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
6144e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6173aafe111b6cc388400092851cc53bbbdfcb8a81creed#define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds)  \
6183aafe111b6cc388400092851cc53bbbdfcb8a81creed    this->predrawNotify();                                          \
6193aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper looper(this, paint, skipLayerForFilter, bounds); \
6203aafe111b6cc388400092851cc53bbbdfcb8a81creed    while (looper.next(SkDrawFilter::kBitmap_Type)) {               \
621262a71b7f95ce98ff3dd8dba845afbd724470903reed        SkDrawIter iter(this);
622262a71b7f95ce98ff3dd8dba845afbd724470903reed
623262a71b7f95ce98ff3dd8dba845afbd724470903reed
6248926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
62597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
6263aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, true);                      \
6278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
6288926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
6298926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
63078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
63197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
6323aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
6334e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
6354b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
636c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
637c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
6383aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
639c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
640c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
641c83a29759a5c2966da5ab973e4fd90763e4c962breed
6424e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
646fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline SkRect qr_clip_bounds(const SkIRect& bounds) {
647fbfa25802709139c2f14e304319c9541da65ca27msarett    if (bounds.isEmpty()) {
648fbfa25802709139c2f14e304319c9541da65ca27msarett        return SkRect::MakeEmpty();
649fbfa25802709139c2f14e304319c9541da65ca27msarett    }
650fbfa25802709139c2f14e304319c9541da65ca27msarett
651fbfa25802709139c2f14e304319c9541da65ca27msarett    // Expand bounds out by 1 in case we are anti-aliasing.  We store the
652fbfa25802709139c2f14e304319c9541da65ca27msarett    // bounds as floats to enable a faster quick reject implementation.
653fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect dst;
654fbfa25802709139c2f14e304319c9541da65ca27msarett    SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&dst.fLeft);
655fbfa25802709139c2f14e304319c9541da65ca27msarett    return dst;
656fbfa25802709139c2f14e304319c9541da65ca27msarett}
657fbfa25802709139c2f14e304319c9541da65ca27msarett
658feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
659feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
660feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fClipStack->reset();
661feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
662feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
663feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
664feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
665feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
666fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(bounds);
6679637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
668feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
669feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
670d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
67142b73eb00367c8315974b1c374308d20efa78897reed    if (device && device->forceConservativeRasterClip()) {
67242b73eb00367c8315974b1c374308d20efa78897reed        flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
67342b73eb00367c8315974b1c374308d20efa78897reed    }
67442b73eb00367c8315974b1c374308d20efa78897reed    // Since init() is only called once by our constructors, it is safe to perform this
67542b73eb00367c8315974b1c374308d20efa78897reed    // const-cast.
67642b73eb00367c8315974b1c374308d20efa78897reed    *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativeRasterClip_InitFlag);
67742b73eb00367c8315974b1c374308d20efa78897reed
67845a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
679f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
6802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
68196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMetaData = nullptr;
68295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
68395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    fLights = nullptr;
68495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
686385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    fClipStack.reset(new SkClipStack);
687687fa1c745febb57f42b0d5f03d7c1f4be2530careed
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
689d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
6905f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
6919637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
693a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
694a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
6957503d60847c4ad22df87458aecd917772b23d293reed    new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip,
6968c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                    fMCRec->fMatrix);
697b679ca8926a832274b14fdb512f88f64b61d32eareed
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
70096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fSurfaceBase = nullptr;
701f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
702f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
703efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
704efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
705f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
70678e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
707fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
708c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
709c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
710c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
711c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
712f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
713fbfa25802709139c2f14e304319c9541da65ca27msarett
714f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
717cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
718e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7194a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
72042b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
721e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
7228d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
723ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
72496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    this->init(nullptr, kDefault_InitFlags);
7258d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
7268d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
727d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
728d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
729d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
730d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
731d954498c01ccf0417feacf89e45d0c62a06a813breed}
732d954498c01ccf0417feacf89e45d0c62a06a813breed
733d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
734d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
735fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps)
736fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips        : INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps)
73778e276889795454891cbba48ab11927968114953reed    {
738c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        this->setOrigin(SkMatrix::I(), bounds.x(), bounds.y());
73978e276889795454891cbba48ab11927968114953reed    }
740d954498c01ccf0417feacf89e45d0c62a06a813breed
741d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
742b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
743d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
744d954498c01ccf0417feacf89e45d0c62a06a813breed};
745d954498c01ccf0417feacf89e45d0c62a06a813breed
74696a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
747e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
74896a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
74942b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
750e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
751e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
752b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
753385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    this->init(new SkNoPixelsBitmapDevice(SkIRect::MakeWH(width, height), fProps),
754385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary               kDefault_InitFlags)->unref();
755d954498c01ccf0417feacf89e45d0c62a06a813breed}
756e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
75778e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
758d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7594a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
76042b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
761d954498c01ccf0417feacf89e45d0c62a06a813breed{
762d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
763b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
764385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    this->init(new SkNoPixelsBitmapDevice(bounds, fProps), flags)->unref();
76527a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
767d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
768d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7697b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
77042b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
771d954498c01ccf0417feacf89e45d0c62a06a813breed{
772d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
773b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
774d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
777fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
778fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7797b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
78042b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
781fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
782fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
783fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
784fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
785fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
786fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
7874a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
7883716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7894a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
79042b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
7913716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7923716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
793b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
794704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
795704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    this->init(device.get(), kDefault_InitFlags);
7964a8126e7f81384526629b1e21bf89b632ea13cd9reed}
79729c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
798356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptr<SkRasterHandleAllocator> alloc,
799356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                   SkRasterHandleAllocator::Handle hndl)
8004a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
8014a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
802356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    , fAllocator(std::move(alloc))
80342b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
8044a8126e7f81384526629b1e21bf89b632ea13cd9reed{
8054a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
806b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
807356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, hndl));
808704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    this->init(device.get(), kDefault_InitFlags);
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
811356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkCanvas::SkCanvas(const SkBitmap& bitmap) : SkCanvas(bitmap, nullptr, nullptr) {}
812356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
8167c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
819385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete fMetaData;
820b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
82453d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
83051985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8347765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
83674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
83774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
83874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
83996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fMetaData) {
84074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
84174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
84274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
84374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
84474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
847bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
848ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    this->onFlush();
849ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
850ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
851ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedvoid SkCanvas::onFlush() {
8521f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
853bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
854bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
855bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
856bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
857bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
858afc7cce5d68663934128d76963cd501f771d71desenorblancoSkISize SkCanvas::getBaseLayerSize() const {
859afc7cce5d68663934128d76963cd501f771d71desenorblanco    SkBaseDevice* d = this->getDevice();
8604ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
8614ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
8624ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
863afc7cce5d68663934128d76963cd501f771d71desenorblancoSkIRect SkCanvas::getTopLayerBounds() const {
8644ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
865afc7cce5d68663934128d76963cd501f771d71desenorblanco    if (!d) {
866afc7cce5d68663934128d76963cd501f771d71desenorblanco        return SkIRect::MakeEmpty();
867afc7cce5d68663934128d76963cd501f771d71desenorblanco    }
868afc7cce5d68663934128d76963cd501f771d71desenorblanco    return SkIRect::MakeXYWH(d->getOrigin().x(), d->getOrigin().y(), d->width(), d->height());
869210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
870210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
8711f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
873c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8780ed3b640c9da71fbbd73c65a4ec1992f85596271Florin MalitaSkBaseDevice* SkCanvas::getTopDevice() const {
8799266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
8809266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
8819266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
882a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
883a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
88496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == bitmap->pixelRef()) {
885848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
886a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
887a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
888a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
889a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
890a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
891cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
892cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap->requestLock(&unlocker)) {
893cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
894cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
895cf01e31df6bbda270dca2ee3b4967caf51e465dcreed            return true;
896cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        }
897a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
898a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
899a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
9001b3387b5cfef150c3237c6a8700b2d6f3730e4ceHal Canary        bitmap->setPixelRef(nullptr, 0, 0);
901a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
902a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
903a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
90451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
905c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
906a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
907a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
908a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
909a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
910ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
911ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
91274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
913848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
914a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
915a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
916a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
917a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
918a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
919daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
920c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
921a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
922a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
923c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
92496472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
925a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
926a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
927a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
928a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
929db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
93003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    return device->readPixels(dstInfo, dstP, rowBytes, x, y);
93151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
93251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
934cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
935cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap.requestLock(&unlocker)) {
936cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
937cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
9384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9394cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
9404cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
9414cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
94203dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarettbool SkCanvas::writePixels(const SkImageInfo& srcInfo, const void* pixels, size_t rowBytes,
9434cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
9444cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
9454cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
9464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
94903dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This check gives us an early out and prevents generation ID churn on the surface.
95003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This is purely optional: it is a subset of the checks performed by SkWritePixelsRec.
95103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    SkIRect srcRect = SkIRect::MakeXYWH(x, y, srcInfo.width(), srcInfo.height());
95203dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    if (!srcRect.intersect(0, 0, device->width(), device->height())) {
95303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett        return false;
9544cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9554cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
95603dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // Tell our owning surface to bump its generation ID.
95703dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    const bool completeOverwrite =
95803dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett            srcRect.size() == SkISize::Make(device->width(), device->height());
959c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
9604af35f348b2e2f6c428819118eb7a2f2fff53a74reed
96103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This can still fail, most notably in the case of a invalid color type or alpha type
96203dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // conversion.  We could pull those checks into this function and avoid the unnecessary
96303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // generation ID bump.  But then we would be performing those checks twice, since they
96403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // are also necessary at the bitmap/pixmap entry points.
96503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    return device->writePixels(srcInfo, pixels, rowBytes, x, y);
9664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
96751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
9731f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
9754b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
97696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == layer->fNext) {   // only one layer
977de6c531e468197bb7746f1217a8ccb2ab175e0b8reed            layer->updateMC(totalMatrix, totalClip, nullptr);
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
979045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
981de6c531e468197bb7746f1217a8ccb2ab175e0b8reed                layer->updateMC(totalMatrix, clip, &clip);
98296fcdcc219d2a0d3579719b84b28bede76efba64halcanary            } while ((layer = layer->fNext) != nullptr);
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
9912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
9932ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
9942ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
996f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
9972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
9982ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
9992ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
10002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
10012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
10022ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
10032ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
10042ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
10052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
10062ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
10072ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
10082ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
10092ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
1010f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1011f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1012f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
10132ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
10142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
10152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
10162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
10172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
10182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
1019f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
1020a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
1021a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
1022a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
10232ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1024f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1025f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1026f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
10272ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
10282ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
10292ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
10302ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
10312ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
10322ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
10332ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
10342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
10352ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
1036a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
10372ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
10382ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
10392ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
1040f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1041f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1042f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1043f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
1044f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
1045f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
1046f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
1047f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1048f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
1049f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
1050f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
1051f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
1052f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1053f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1054f0090cb80ab10a49e511aa5450ae38917fa058d9reed
10552ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
1057d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
10594b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1060687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->save();
1061c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
1062c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    FOR_EACH_TOP_DEVICE(device->save());
1063c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10664960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
10674960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag);
10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10704960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
10719b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
1072918e144408ba218df919528f8b48c544f4767883Mike Reed    SkIRect clipBounds = this->getDeviceClipBounds();
1073918e144408ba218df919528f8b48c544f4767883Mike Reed    if (clipBounds.isEmpty()) {
1074a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
1075f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1076c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
107796e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
107896e657d0e103b8358a77ecd913f6086929f792b8reed
1079c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
1080e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco        clipBounds = imageFilter->filterBounds(clipBounds, ctm);
1081db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        if (bounds && !imageFilter->canComputeFastBounds()) {
1082db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco            bounds = nullptr;
1083db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        }
1084c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
1085bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
108649f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
10884b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
108996e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
10934960eeec4a1f2a772654883d7f3615d47bcd5dc3reed            if (BoundsAffectsClip(saveLayerFlags)) {
10941f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
1095fbfa25802709139c2f14e304319c9541da65ca27msarett                fDeviceClipBounds.setEmpty();
1096bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
1097a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1102180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11044960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (BoundsAffectsClip(saveLayerFlags)) {
1105180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
1106c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        fClipStack->clipDevRect(ir, kReplace_SkClipOp);
1107180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
1108fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(ir);
1109a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1110a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1111a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
1112a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
1113a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1114a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
1115a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
1116a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
11174960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11184960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
11194960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, 0));
1120d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1121d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
11224960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) {
11234960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag));
11244960eeec4a1f2a772654883d7f3615d47bcd5dc3reed}
11254960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11264960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SaveLayerRec& origRec) {
11274960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerRec rec(origRec);
1128d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
11294960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        rec.fBounds = nullptr;
1130d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
11314960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec);
1132a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
11334960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    this->internalSaveLayer(rec, strategy);
11342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
11358926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
11368926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
1137a2217ef965e57fdbbf989989e7ec1f2c04f62d39reedvoid SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1138c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed                                    SkBaseDevice* dst, const SkIPoint& dstOrigin,
1139c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed                                    const SkMatrix& ctm, const SkClipStack* clipStack) {
1140a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkDraw draw;
1141a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkRasterClip rc;
1142a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
1143a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (!dst->accessPixels(&draw.fDst)) {
1144a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        draw.fDst.reset(dst->imageInfo(), nullptr, 0);
1145a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1146a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fMatrix = &SkMatrix::I();
1147a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fRC = &rc;
1148a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fClipStack = clipStack;
11497354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
11507354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    SkPaint p;
1151372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips    p.setImageFilter(filter->makeWithLocalMatrix(ctm));
1152a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1153c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    int x = src->getOrigin().x() - dstOrigin.x();
1154c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    int y = src->getOrigin().y() - dstOrigin.y();
1155a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    auto special = src->snapSpecial();
1156a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (special) {
1157a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        dst->drawSpecial(draw, special.get(), x, y, p);
1158a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
11597354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips}
116070ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed
1161129ed1cd6d792f3f6cf563aefa9756fc6308289dreedstatic SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque,
1162129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                   const SkPaint* paint) {
1163129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // need to force L32 for now if we have an image filter. Once filters support other colortypes
1164129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // e.g. sRGB or F16, we can remove this check
116552ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman    // SRGBTODO: Can we remove this check now?
1166129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    const bool hasImageFilter = paint && paint->getImageFilter();
1167129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1168129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
1169129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1170129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // force to L32
1171129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        return SkImageInfo::MakeN32(w, h, alphaType);
1172129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    } else {
1173129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // keep the same characteristics as the prev
1174693fdbd6b81a860657612e7604430dd55d6e721bMike Reed        return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.refColorSpace());
1175129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
1176129ed1cd6d792f3f6cf563aefa9756fc6308289dreed}
1177129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
11784960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
11794960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkRect* bounds = rec.fBounds;
11804960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkPaint* paint = rec.fPaint;
11814960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
11824960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11838c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkLazyPaint lazyP;
11848c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
11858c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix stashedMatrix = fMCRec->fMatrix;
11868c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix remainder;
11878c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkSize scale;
11888c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    /*
11898c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
11908c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  but they do handle scaling. To accommodate this, we do the following:
11918c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
11928c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  1. Stash off the current CTM
11938c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  2. Decompose the CTM into SCALE and REMAINDER
11948c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
11958c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     contains the REMAINDER
11968c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
11978c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
11988c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     of the original imagefilter, and draw that (via drawSprite)
11998c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
12008c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
12018c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
12028c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
12038c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     */
120496a04f329926099f0002f97883242793ff04f61creed    if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
12058c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        stashedMatrix.decomposeScale(&scale, &remainder))
12068c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    {
12078c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
12088c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
12098c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        SkPaint* p = lazyP.set(*paint);
12108c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
12118c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          SkFilterQuality::kLow_SkFilterQuality,
12128c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          sk_ref_sp(imageFilter)));
12138c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        imageFilter = p->getImageFilter();
12148c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        paint = p;
12158c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    }
12168c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
1217a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1218a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
12192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1220a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1221a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
1222a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1223a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
12248c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
12252ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1228e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1229e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1230e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
12312ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1232e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1233e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
12344960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
12358dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
12368dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
123776033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1238daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
123976033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
12408dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1241b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1242b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12445139e501c5ac3a511e35c78395c907a176113451robertphillips    SkBaseDevice* priorDevice = this->getTopDevice();
1245c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (nullptr == priorDevice) {   // Do we still need this check???
1246b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
12472ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1248b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1249b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
12505139e501c5ac3a511e35c78395c907a176113451robertphillips    SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), isOpaque,
1251129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                       paint);
1252129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1253704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    sk_sp<SkBaseDevice> newDevice;
125461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
125570ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
12564960eeec4a1f2a772654883d7f3615d47bcd5dc3reed                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1257daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
125870ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1259356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                             preserveLCDText,
1260356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                             fAllocator.get());
12615139e501c5ac3a511e35c78395c907a176113451robertphillips        newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
12625139e501c5ac3a511e35c78395c907a176113451robertphillips        if (!newDevice) {
12637503d60847c4ad22df87458aecd917772b23d293reed            return;
126461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
1265e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
1266c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifndef SK_USE_DEVICE_CLIPPING
1267c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
1268c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
12697354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
1270704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    DeviceCM* layer =
1271704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary            new DeviceCM(newDevice.get(), paint, this, fConservativeRasterClip, stashedMatrix);
12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1273b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed    // only have a "next" if this new layer doesn't affect the clip (rare)
1274b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed    layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1277a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1278a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (rec.fBackdrop) {
1279c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
1280a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                             fMCRec->fMatrix, this->getClipStack());
1281a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1282c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1283c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
1284c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
1285c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1286c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
1287c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (layer->fNext) {
1288c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // need to punch a hole in the previous device, so we don't draw there, given that
1289c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // the new top-layer will allow drawing to happen "below" it.
1290c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        SkRegion hole(ir);
1291c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        do {
1292c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            layer = layer->fNext;
1293c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
1294c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        } while (layer->fNext);
1295c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    }
1296c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1299d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1300bada1885da479d948f065182d6dfa85a1140bda5reed    if (0xFF == alpha) {
1301bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, nullptr);
1302bada1885da479d948f065182d6dfa85a1140bda5reed    } else {
1303bada1885da479d948f065182d6dfa85a1140bda5reed        SkPaint tmpPaint;
1304bada1885da479d948f065182d6dfa85a1140bda5reed        tmpPaint.setAlpha(alpha);
1305bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, &tmpPaint);
1306bada1885da479d948f065182d6dfa85a1140bda5reed    }
1307d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1308d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1314687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->restore();
13156c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
131688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
131996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fLayer = nullptr;
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1326c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
1327c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (fMCRec) {
1328c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
1329c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    }
1330c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
1331c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
133649f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
1337b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed        if (fMCRec) {
13386f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
13397503d60847c4ad22df87458aecd917772b23d293reed            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), layer->fPaint);
13408c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // restore what we smashed in internalSaveLayer
13418c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            fMCRec->fMatrix = layer->fStashedMatrix;
13428926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
1344385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete layer;
1345b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1346b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1347a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1348b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
13498c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // no need to update fMCRec, 'cause we're killing the canvas
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
135188edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1352fbfa25802709139c2f14e304319c9541da65ca27msarett
1353fbfa25802709139c2f14e304319c9541da65ca27msarett    if (fMCRec) {
13549637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett        fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1355fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1356fbfa25802709139c2f14e304319c9541da65ca27msarett    }
13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1359e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
136096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == props) {
13614a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
13624a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
13634a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
136476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
136576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1366e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
136776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
1368e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    return dev ? dev->makeSurface(info, props) : nullptr;
136976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
137076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1371c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1372ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onImageInfo();
1373ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1374ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1375ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedSkImageInfo SkCanvas::onImageInfo() const {
1376c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1377c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1378c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1379c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1380900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1381c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1382c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1383c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1384898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosmanbool SkCanvas::getProps(SkSurfaceProps* props) const {
1385ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onGetProps(props);
1386ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1387ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1388ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedbool SkCanvas::onGetProps(SkSurfaceProps* props) const {
1389898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    SkBaseDevice* dev = this->getDevice();
1390898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    if (dev) {
1391898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        if (props) {
1392898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman            *props = fProps;
1393898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        }
1394898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return true;
1395898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    } else {
1396898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return false;
1397898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    }
1398898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman}
1399898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman
14006ceeebd37a43d879c120b6ba100ae1febdd67a18reedbool SkCanvas::peekPixels(SkPixmap* pmap) {
14016ceeebd37a43d879c120b6ba100ae1febdd67a18reed    return this->onPeekPixels(pmap);
1402c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1403c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1404884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1405c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1406884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1407c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1408c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
14096b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1410884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1411884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
141296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1413884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1414884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1415884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1416884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1417884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1418884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1419884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1420884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
14210ed3b640c9da71fbbd73c65a4ec1992f85596271Florin Malita        *origin = this->getTopDevice()->getOrigin();
14226b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1423884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
14249c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
14259c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1426884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
14279c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1428884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
14299c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
14309c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1431520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14337503d60847c4ad22df87458aecd917772b23d293reedvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint) {
14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
143596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14384b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14398926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1440a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
14421f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
144376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
144476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
144576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1446833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips        if (filter) {
1447833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
1448833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            if (specialImage) {
1449833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips                dstDev->drawSpecial(iter, specialImage.get(), pos.x(), pos.y(), *paint);
1450833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            }
145176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1452b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
145376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1455a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
14564e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
145932704674f64cb6a14356dfebe060cd3484c06cc7reed/////////////////////////////////////////////////////////////////////////////
1460da420b976e61071cfe5de10556b4b23e519091d6reed
146192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1462fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    if (dx || dy) {
1463fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->checkForDeferredSave();
1464fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        fDeviceCMDirty = true;
1465fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        fMCRec->fMatrix.preTranslate(dx,dy);
1466cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1467fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        // Translate shouldn't affect the is-scale-translateness of the matrix.
1468fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1469cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1470c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
1471c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1472c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
1473c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1474fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->didTranslate(dx,dy);
1475fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    }
14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
147892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1479d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1480d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1481d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
148492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1485d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1486d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1487d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14907438bfc0804d021aa92cdd5ea644994a4248f3dbbungemanvoid SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
14917438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    SkMatrix m;
14927438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    m.setRotate(degrees, px, py);
14937438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    this->concat(m);
14947438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman}
14957438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman
149692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1497d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1498d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1499d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
150044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
150144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
150292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1503d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1504d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1505d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1506d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
15072ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
15091f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
15109637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
15117627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
15127627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
15137627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
15147627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#endif
15157627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
151644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
151744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
151844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
15198c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
15208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
15211f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
15229da5a5a198e5dc9148f7f30a6089377590eee55bmsarett    fIsScaleTranslate = matrix.isScaleTranslate();
1523c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1524c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
1525c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1526c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
15278c30a8196dd5903d2d23b4d0a5dc888e802bf698reed}
15288c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
15298c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
15308c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->checkForDeferredSave();
15318c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->internalSetMatrix(matrix);
153244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
15338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
15368c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->setMatrix(SkMatrix::I());
15378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
153995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
1540e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblackvoid SkCanvas::translateZ(SkScalar z) {
1541e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->checkForDeferredSave();
1542e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->fMCRec->fCurDrawDepth += z;
1543e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->didTranslateZ(z);
1544e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack}
1545e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
1546e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblackSkScalar SkCanvas::getZ() const {
1547e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    return this->fMCRec->fCurDrawDepth;
1548e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack}
1549e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
155095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::setLights(sk_sp<SkLights> lights) {
155195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    this->fLights = lights;
155295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
155395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
155495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblacksk_sp<SkLights> SkCanvas::getLights() const {
155595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    return this->fLights;
155695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
155795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
155895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
15608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1561c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
15622ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15648f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
15658f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15668f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1567c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1568a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
15697627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
15707627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
15717627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
15727627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#endif
15737627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
1574c64eff55049b1192052b791549a32a03be1c43e3reed    AutoValidateClip avc(this);
1575a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fClipStack->clipRect(rect, fMCRec->fMatrix, op, isAA);
1576a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1577a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1578c64eff55049b1192052b791549a32a03be1c43e3reed    fDeviceCMDirty = true;
1579fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
15808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15825f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Ilievvoid SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
15835f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fClipRestrictionRect = rect;
15845f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fClipStack->setDeviceClipRestriction(fClipRestrictionRect);
1585d519d484949161df6d4b2ecadc282427cab532cfMike Reed    if (fClipRestrictionRect.isEmpty()) {
1586d519d484949161df6d4b2ecadc282427cab532cfMike Reed        // we notify the device, but we *dont* resolve deferred saves (since we're just
1587d519d484949161df6d4b2ecadc282427cab532cfMike Reed        // removing the restriction if the rect is empty. how I hate this api.
1588d519d484949161df6d4b2ecadc282427cab532cfMike Reed#ifdef SK_USE_DEVICE_CLIPPING
1589d519d484949161df6d4b2ecadc282427cab532cfMike Reed        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1590d519d484949161df6d4b2ecadc282427cab532cfMike Reed#endif
1591d519d484949161df6d4b2ecadc282427cab532cfMike Reed    } else {
15925f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        this->checkForDeferredSave();
1593c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
1594d519d484949161df6d4b2ecadc282427cab532cfMike Reed        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1595c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed#endif
15965f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        AutoValidateClip avc(this);
15975f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fClipStack->clipDevRect(fClipRestrictionRect, kIntersect_SkClipOp);
15985f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op);
15995f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fDeviceCMDirty = true;
16005f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
16015f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    }
16025f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev}
16035f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev
1604c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
16052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16068f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
16074ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
16088f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
16098f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
16108f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
16114ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
16128f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
161314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1614c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1615a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    AutoValidateClip avc(this);
161614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1617a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fDeviceCMDirty = true;
161814e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1619a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
16207627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
16217627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
16227627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
16237627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#endif
16247627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
1625a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fClipStack->clipRRect(rrect, fMCRec->fMatrix, op, isAA);
1626a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1627a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1628a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1629a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    return;
16304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
16314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1632c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
16332ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16348f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
163539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
163639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
163739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRect r;
163839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRect(&r)) {
163939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRect(r, op, edgeStyle);
164039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
164139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
164239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRRect rrect;
164339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isOval(&r)) {
164439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            rrect.setOval(r);
164539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
164639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
164739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
164839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRRect(&rrect)) {
164939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
165039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
165139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
16528f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
165339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
165439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    this->onClipPath(path, op, edgeStyle);
16558f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1657c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
16585c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16595c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
1661a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
16627627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
16637627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
16647627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
16657627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#endif
16667627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
1667a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fClipStack->clipPath(path, fMCRec->fMatrix, op, isAA);
16685c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1669a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const SkPath* rasterClipPath = &path;
1670a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const SkMatrix* matrix = &fMCRec->fMatrix;
1671a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    SkPath tempPath;
167245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
1673a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon        isAA = getClipStack()->asPath(&tempPath);
1674a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon        rasterClipPath = &tempPath;
1675a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon        matrix = &SkMatrix::I();
1676c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reed        op = kReplace_SkClipOp;
167745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
1678a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(*rasterClipPath, *matrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1679a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1680fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
16818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1683c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
16842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16858f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
16868f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16878f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1688c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
16897627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#ifdef SK_USE_DEVICE_CLIPPING
16907627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
16917627fa51044e35dc21251f925b56f6dd6887df97Mike Reed#endif
16927627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
16935c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
16945c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16975c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
16985c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1699687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevRect(rgn.getBounds(), op);
17005c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
170173603f3c52ffd89fe9d035be827b566a0e7d3b79reed    fMCRec->fRasterClip.op(rgn, (SkRegion::Op)op);
1702fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
17038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1705819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1706819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1707819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
17081f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1709ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
17105c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1711ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1712ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1713ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1714819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1715819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1716d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1717819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1718687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
17198182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
172096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    while ((element = iter.next()) != nullptr) {
17218182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
17228182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
17238182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
172473603f3c52ffd89fe9d035be827b566a0e7d3b79reed                tmpClip.op(ir, (SkRegion::Op)element->getOp());
17258182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
17268182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
17278182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
17288182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
17299cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
17309cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
17319cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
1732a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                tmpClip.op(path, SkMatrix::I(), this->getTopLayerBounds(),
1733a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           (SkRegion::Op)element->getOp(), element->isAA());
17349cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
17359cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1736819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1737819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1738819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1739819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1740819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
174190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
1742687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
17438182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
17448182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
174596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    while ((element = iter.next()) != nullptr) {
1746c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
174790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
174890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
174990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
17505c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
17515c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1752754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
17531f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1754754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1755754de5f65b466f721d952a379194cc94de376f42reed@google.com
17565c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
17571f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
17585c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
17595c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
1760fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1761fbfa25802709139c2f14e304319c9541da65ca27msarett#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1762fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1763fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1764fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1765fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xF != _mm_movemask_ps(mask);
1766fbfa25802709139c2f14e304319c9541da65ca27msarett#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1767fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1768fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1769fbfa25802709139c2f14e304319c9541da65ca27msarett    uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1770fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1771fbfa25802709139c2f14e304319c9541da65ca27msarett#else
1772fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devRectAsRect;
1773fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devClipAsRect;
1774fbfa25802709139c2f14e304319c9541da65ca27msarett    devRect.store(&devRectAsRect.fLeft);
1775fbfa25802709139c2f14e304319c9541da65ca27msarett    devClip.store(&devClipAsRect.fLeft);
1776fbfa25802709139c2f14e304319c9541da65ca27msarett    return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1777fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1778fbfa25802709139c2f14e304319c9541da65ca27msarett}
1779fbfa25802709139c2f14e304319c9541da65ca27msarett
1780fbfa25802709139c2f14e304319c9541da65ca27msarett// It's important for this function to not be inlined.  Otherwise the compiler will share code
1781fbfa25802709139c2f14e304319c9541da65ca27msarett// between the fast path and the slow path, resulting in two slow paths.
1782fbfa25802709139c2f14e304319c9541da65ca27msarettstatic SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1783fbfa25802709139c2f14e304319c9541da65ca27msarett                                                   const SkMatrix& matrix) {
1784fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect deviceRect;
1785fbfa25802709139c2f14e304319c9541da65ca27msarett    matrix.mapRect(&deviceRect, src);
1786fbfa25802709139c2f14e304319c9541da65ca27msarett    return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1787fbfa25802709139c2f14e304319c9541da65ca27msarett}
1788d22a817ff57986407facd16af36320fc86ce02damsarett
1789fbfa25802709139c2f14e304319c9541da65ca27msarettbool SkCanvas::quickReject(const SkRect& src) const {
1790fbfa25802709139c2f14e304319c9541da65ca27msarett#ifdef SK_DEBUG
1791fbfa25802709139c2f14e304319c9541da65ca27msarett    // Verify that fDeviceClipBounds are set properly.
1792fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
17931f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
17940c685ee188a5e500df25a34fa6edfceb4cbb795cmsarett        SkASSERT(fDeviceClipBounds.isEmpty());
1795fbfa25802709139c2f14e304319c9541da65ca27msarett    } else {
1796fbfa25802709139c2f14e304319c9541da65ca27msarett        SkASSERT(tmp == fDeviceClipBounds);
17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17999637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    // Verify that fIsScaleTranslate is set properly.
18009637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1801fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1802d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
18039637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    if (!fIsScaleTranslate) {
1804fbfa25802709139c2f14e304319c9541da65ca27msarett        return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1806fbfa25802709139c2f14e304319c9541da65ca27msarett
1807fbfa25802709139c2f14e304319c9541da65ca27msarett    // We inline the implementation of mapScaleTranslate() for the fast path.
1808fbfa25802709139c2f14e304319c9541da65ca27msarett    float sx = fMCRec->fMatrix.getScaleX();
1809fbfa25802709139c2f14e304319c9541da65ca27msarett    float sy = fMCRec->fMatrix.getScaleY();
1810fbfa25802709139c2f14e304319c9541da65ca27msarett    float tx = fMCRec->fMatrix.getTranslateX();
1811fbfa25802709139c2f14e304319c9541da65ca27msarett    float ty = fMCRec->fMatrix.getTranslateY();
1812fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f scale(sx, sy, sx, sy);
1813fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f trans(tx, ty, tx, ty);
1814fbfa25802709139c2f14e304319c9541da65ca27msarett
1815fbfa25802709139c2f14e304319c9541da65ca27msarett    // Apply matrix.
1816fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1817fbfa25802709139c2f14e304319c9541da65ca27msarett
1818fbfa25802709139c2f14e304319c9541da65ca27msarett    // Make sure left < right, top < bottom.
1819fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1820fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f min = Sk4f::Min(ltrb, rblt);
1821fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f max = Sk4f::Max(ltrb, rblt);
1822fbfa25802709139c2f14e304319c9541da65ca27msarett    // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1823fbfa25802709139c2f14e304319c9541da65ca27msarett    // ARM this sequence generates the fastest (a single instruction).
1824fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1825fbfa25802709139c2f14e304319c9541da65ca27msarett
1826fbfa25802709139c2f14e304319c9541da65ca27msarett    // Check if the device rect is NaN or outside the clip.
1827fbfa25802709139c2f14e304319c9541da65ca27msarett    return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
18288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18303b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
18313b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
183442e8c53b3ef58f887a623b410d9783b4d4ab4921Mike ReedSkRect SkCanvas::onGetLocalClipBounds() const {
183542e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkIRect ibounds = this->onGetDeviceClipBounds();
1836918e144408ba218df919528f8b48c544f4767883Mike Reed    if (ibounds.isEmpty()) {
183742e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkRect::MakeEmpty();
18388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1840d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1841d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
18421f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
184342e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkRect::MakeEmpty();
1844d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1845d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
184642e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkRect bounds;
184742e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkRect r;
184842e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    // adjust it outwards in case we are antialiasing
184942e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    const int inset = 1;
1850fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
185142e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
185242e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed           ibounds.fRight + inset, ibounds.fBottom + inset);
185342e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    inverse.mapRect(&bounds, r);
185442e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    return bounds;
18558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
185742e8c53b3ef58f887a623b410d9783b4d4ab4921Mike ReedSkIRect SkCanvas::onGetDeviceClipBounds() const {
18581f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1859bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
186042e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkIRect::MakeEmpty();
1861bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
186242e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    return clip.getBounds();
1863bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1864bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
18658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
18661f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18693726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reedvoid SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
18703726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reed    // we know that ganesh doesn't track the rgn, so ask for its clipstack
18713726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reed    if (this->getGrContext()) {
18724eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev        const SkClipStack* cs = this->getClipStack();
18734eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev        SkClipStack::BoundsType boundType;
18744eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev        bool isIntersectionOfRects;
18754eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev        SkRect bounds;
18764eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev        cs->getBounds(&bounds, &boundType, &isIntersectionOfRects);
18774eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev        if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) {
18784eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev            rgn->setRect(bounds.round());
18794eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev            return;
18804eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev        }
18813726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reed        SkPath path;
18824eabd5d88aec712f5d0643a2f814aea7403d2119Stan Iliev        cs->asPath(&path);
18833726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reed        SkISize size = this->getBaseLayerSize();
18843726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reed        rgn->setPath(path, SkRegion(SkIRect::MakeWH(size.width(), size.height())));
18853726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reed    } else {
18863726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reed        *rgn = fMCRec->fRasterClip.forceGetBW();
18873726a4ac68821deea7ef4d5472a42f7d35ec4b4eMike Reed    }
18885c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
18895c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
18901105224f9701e57ec5ce0354d6a380b664f5c638Brian OsmanGrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
18919c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
18921105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    return dev ? dev->accessRenderTargetContext() : nullptr;
18939c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
18949c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1895644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1896644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
189786ae3d161412961c27a406465b0ec5749cc2e753reed    return device ? device->context() : nullptr;
1898644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1899e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1900ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1901ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
19029881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1903ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1904ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1905ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1906ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1907ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1908ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1909ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1910ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1911ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1912ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1913ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1914ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1915ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1916ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1917ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1918ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1919ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1920ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
192141af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
192241af966ab338e95eee81ab618ab28195075338f7reed
192341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
192441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
192541af966ab338e95eee81ab618ab28195075338f7reed}
192641af966ab338e95eee81ab618ab28195075338f7reed
192741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
192841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
192941af966ab338e95eee81ab618ab28195075338f7reed}
193041af966ab338e95eee81ab618ab28195075338f7reed
1931dca352e2d42cfe698573947b3d11abc1eaade160msarettvoid SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1932dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isEmpty()) {
1933dca352e2d42cfe698573947b3d11abc1eaade160msarett        return;
1934dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1935dca352e2d42cfe698573947b3d11abc1eaade160msarett
1936dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isRect()) {
1937dca352e2d42cfe698573947b3d11abc1eaade160msarett        return this->drawIRect(region.getBounds(), paint);
1938dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1939dca352e2d42cfe698573947b3d11abc1eaade160msarett
1940dca352e2d42cfe698573947b3d11abc1eaade160msarett    this->onDrawRegion(region, paint);
1941dca352e2d42cfe698573947b3d11abc1eaade160msarett}
1942dca352e2d42cfe698573947b3d11abc1eaade160msarett
194341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
194441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
194541af966ab338e95eee81ab618ab28195075338f7reed}
194641af966ab338e95eee81ab618ab28195075338f7reed
194741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
194841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
194941af966ab338e95eee81ab618ab28195075338f7reed}
195041af966ab338e95eee81ab618ab28195075338f7reed
195141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
195241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
195341af966ab338e95eee81ab618ab28195075338f7reed}
195441af966ab338e95eee81ab618ab28195075338f7reed
195541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
19567d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                            const SkPoint texs[], const SkColor colors[], SkBlendMode bmode,
195741af966ab338e95eee81ab618ab28195075338f7reed                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
1958199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    this->onDrawVertices(vmode, vertexCount, std::move(vertices), texs, colors, bmode, indices,
1959199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon                         indexCount, paint);
1960199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon}
1961199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
1962199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomonvoid SkCanvas::drawVertices(sk_sp<SkVertices> vertices, SkBlendMode mode, const SkPaint& paint,
1963199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon                            uint32_t flags) {
1964199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    RETURN_ON_NULL(vertices);
1965199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    this->onDrawVerticesObject(std::move(vertices), mode, paint, flags);
196641af966ab338e95eee81ab618ab28195075338f7reed}
196741af966ab338e95eee81ab618ab28195075338f7reed
196841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
196941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
197041af966ab338e95eee81ab618ab28195075338f7reed}
197141af966ab338e95eee81ab618ab28195075338f7reed
1972a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1973e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1974a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
197541af966ab338e95eee81ab618ab28195075338f7reed}
197641af966ab338e95eee81ab618ab28195075338f7reed
1977e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1978e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             const SkPaint* paint, SrcRectConstraint constraint) {
1979e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1980e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (dst.isEmpty() || src.isEmpty()) {
1981e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
1982e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1983e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawImageRect(image, &src, dst, paint, constraint);
1984e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
198541af966ab338e95eee81ab618ab28195075338f7reed
198684984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
198784984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1988e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1989e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
199084984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
199184984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
1992e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1993e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             SrcRectConstraint constraint) {
1994e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1995e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1996e47829b6b1eeb6b0c97ccb3df3016d197046824creed                        constraint);
1997e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1998e47829b6b1eeb6b0c97ccb3df3016d197046824creed
19994c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
20004c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
2001e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
20024c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
20034c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
20044c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
2005552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
2006552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawImageNine(image, center, dst, paint);
2007552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
2008e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, dst, paint);
20094c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
20104c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
20114c21dc5ddf3b482293ed34eead876d8d61a662c3reed
2012168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2013168820625c35a8c19f66c661efcbce7a5e334837msarett                                const SkPaint* paint) {
2014168820625c35a8c19f66c661efcbce7a5e334837msarett    RETURN_ON_NULL(image);
2015168820625c35a8c19f66c661efcbce7a5e334837msarett    if (dst.isEmpty()) {
2016168820625c35a8c19f66c661efcbce7a5e334837msarett        return;
2017168820625c35a8c19f66c661efcbce7a5e334837msarett    }
201871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
201971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkIRect bounds;
202071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    Lattice latticePlusBounds = lattice;
202171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (!latticePlusBounds.fBounds) {
202271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        bounds = SkIRect::MakeWH(image->width(), image->height());
202371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        latticePlusBounds.fBounds = &bounds;
202471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    }
202571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
202671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
202771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
2028168820625c35a8c19f66c661efcbce7a5e334837msarett    } else {
2029168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawImageRect(image, dst, paint);
2030168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2031168820625c35a8c19f66c661efcbce7a5e334837msarett}
2032168820625c35a8c19f66c661efcbce7a5e334837msarett
203341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
20344c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
20352df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
20362df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
203741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
203841af966ab338e95eee81ab618ab28195075338f7reed}
203941af966ab338e95eee81ab618ab28195075338f7reed
2040e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
2041a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
2042e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
2043a5517e2b190a8083b38964972b031c13e99f1012reed        return;
2044a5517e2b190a8083b38964972b031c13e99f1012reed    }
2045e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
204641af966ab338e95eee81ab618ab28195075338f7reed}
204741af966ab338e95eee81ab618ab28195075338f7reed
204884984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
204984984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                              const SkPaint* paint, SrcRectConstraint constraint) {
2050e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
2051e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2052e47829b6b1eeb6b0c97ccb3df3016d197046824creed
2053e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
2054e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              SrcRectConstraint constraint) {
2055e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
2056e47829b6b1eeb6b0c97ccb3df3016d197046824creed                         constraint);
205784984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
205884984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
205941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
206041af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
20614c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
20622df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
20632df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
2064552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
2065552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawBitmapNine(bitmap, center, dst, paint);
2066552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
2067a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
20684c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
206941af966ab338e95eee81ab618ab28195075338f7reed}
207041af966ab338e95eee81ab618ab28195075338f7reed
2071c573a40ed5024b463e47088d307e3164a486dba5msarettvoid SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
2072c573a40ed5024b463e47088d307e3164a486dba5msarett                                 const SkPaint* paint) {
2073168820625c35a8c19f66c661efcbce7a5e334837msarett    if (bitmap.drawsNothing() || dst.isEmpty()) {
2074c573a40ed5024b463e47088d307e3164a486dba5msarett        return;
2075c573a40ed5024b463e47088d307e3164a486dba5msarett    }
207671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
207771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkIRect bounds;
207871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    Lattice latticePlusBounds = lattice;
207971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (!latticePlusBounds.fBounds) {
208071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
208171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        latticePlusBounds.fBounds = &bounds;
208271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    }
208371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
208471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
208571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
2086552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
2087168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawBitmapRect(bitmap, dst, paint);
2088c573a40ed5024b463e47088d307e3164a486dba5msarett    }
2089c573a40ed5024b463e47088d307e3164a486dba5msarett}
2090c573a40ed5024b463e47088d307e3164a486dba5msarett
209171c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
20927d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkColor colors[], int count, SkBlendMode mode,
209371c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
2094e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(atlas);
209571c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
209671c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
209771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
2098c485907f0420e5f9cf8223e9ba53812cd8dd5368Joe Gregorio    SkASSERT(atlas);
209971c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
2100faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
210171c3c760a83123ee0b3127b8c65c6394ce541c50reed}
210271c3c760a83123ee0b3127b8c65c6394ce541c50reed
2103f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2104f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    if (key) {
2105f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        this->onDrawAnnotation(rect, key, value);
2106f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
2107f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
2108f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
2109e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2110e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                    const SkPaint* paint, SrcRectConstraint constraint) {
2111e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
2112e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, *src, dst, paint, constraint);
2113e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
2114e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
2115e47829b6b1eeb6b0c97ccb3df3016d197046824creed                            dst, paint, constraint);
2116e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
2117e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2118e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2119e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                     const SkPaint* paint, SrcRectConstraint constraint) {
2120e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
2121e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
2122e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
2123e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
2124e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             dst, paint, constraint);
2125e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
2126e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2127e47829b6b1eeb6b0c97ccb3df3016d197046824creed
2128cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudsonvoid SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) {
2129cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    SkIRect layer_bounds = this->getTopLayerBounds();
2130cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    if (matrix) {
2131cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        *matrix = this->getTotalMatrix();
2132cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top());
2133cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    }
2134cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    if (clip_bounds) {
2135918e144408ba218df919528f8b48c544f4767883Mike Reed        *clip_bounds = this->getDeviceClipBounds();
2136cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top());
2137cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    }
2138cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson}
2139cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson
21408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
21418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
21428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
21438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
214428361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
214549f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
214628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
214728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
214828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
214928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
215041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
21519881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
2152fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
2153fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
2154fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
2155fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
215696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
21578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21594e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
21608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21624e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
216541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
216641af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
21679881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
21688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
217278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
217396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2174a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
2175a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
2176a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
2177a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
2178a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
2179a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
2180a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
218187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
218287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
218387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
218487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
2185fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
2186a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
218796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(pts != nullptr);
21888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
218978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
21904b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
21924e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
21938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21944b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
21954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21984a16717bc7aa471fad10ec3157774771a76e5106reedstatic bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
21994a16717bc7aa471fad10ec3157774771a76e5106reed    return ((intptr_t)paint.getImageFilter()    |
22004a16717bc7aa471fad10ec3157774771a76e5106reed#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
22014a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)canvas->getDrawFilter()   |
22024a16717bc7aa471fad10ec3157774771a76e5106reed#endif
22034a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)paint.getLooper()         ) != 0;
22044a16717bc7aa471fad10ec3157774771a76e5106reed}
22054a16717bc7aa471fad10ec3157774771a76e5106reed
220641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
22079881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
220878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
220996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
22118432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
22128432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
22138432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
22148432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
22158432808ad8898ac7137bc7ce1d9df6005e866401reed
221687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
221787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
221887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
221987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
22208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22214b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22224a16717bc7aa471fad10ec3157774771a76e5106reed    if (needs_autodrawlooper(this, paint)) {
22234a16717bc7aa471fad10ec3157774771a76e5106reed        LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false)
22248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22254a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
22264a16717bc7aa471fad10ec3157774771a76e5106reed            iter.fDevice->drawRect(iter, r, looper.paint());
22274a16717bc7aa471fad10ec3157774771a76e5106reed        }
22288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22294a16717bc7aa471fad10ec3157774771a76e5106reed        LOOPER_END
22304a16717bc7aa471fad10ec3157774771a76e5106reed    } else {
22314a16717bc7aa471fad10ec3157774771a76e5106reed        this->predrawNotify(bounds, &paint, false);
22324a16717bc7aa471fad10ec3157774771a76e5106reed        SkDrawIter iter(this);
22334a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
22344a16717bc7aa471fad10ec3157774771a76e5106reed            iter.fDevice->drawRect(iter, r, paint);
22354a16717bc7aa471fad10ec3157774771a76e5106reed        }
22364a16717bc7aa471fad10ec3157774771a76e5106reed    }
22378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
223944df651ebefc284acc2f66425dff3ea0b0e14b36msarettvoid SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
224044df651ebefc284acc2f66425dff3ea0b0e14b36msarett    SkRect storage;
224144df651ebefc284acc2f66425dff3ea0b0e14b36msarett    SkRect regionRect = SkRect::Make(region.getBounds());
224244df651ebefc284acc2f66425dff3ea0b0e14b36msarett    const SkRect* bounds = nullptr;
224344df651ebefc284acc2f66425dff3ea0b0e14b36msarett    if (paint.canComputeFastBounds()) {
224444df651ebefc284acc2f66425dff3ea0b0e14b36msarett        if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
224544df651ebefc284acc2f66425dff3ea0b0e14b36msarett            return;
224644df651ebefc284acc2f66425dff3ea0b0e14b36msarett        }
224744df651ebefc284acc2f66425dff3ea0b0e14b36msarett        bounds = &regionRect;
224844df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
224944df651ebefc284acc2f66425dff3ea0b0e14b36msarett
225044df651ebefc284acc2f66425dff3ea0b0e14b36msarett    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
225144df651ebefc284acc2f66425dff3ea0b0e14b36msarett
225244df651ebefc284acc2f66425dff3ea0b0e14b36msarett    while (iter.next()) {
225344df651ebefc284acc2f66425dff3ea0b0e14b36msarett        iter.fDevice->drawRegion(iter, region, looper.paint());
225444df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
225544df651ebefc284acc2f66425dff3ea0b0e14b36msarett
225644df651ebefc284acc2f66425dff3ea0b0e14b36msarett    LOOPER_END
225744df651ebefc284acc2f66425dff3ea0b0e14b36msarett}
225844df651ebefc284acc2f66425dff3ea0b0e14b36msarett
225941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
22609881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
226178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
226296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
22634ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
226487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
226587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
226687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
226787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &oval;
22684ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2269306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
227078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
227146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
227246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
227346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
227446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
227546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
227646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
22774ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
22784ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2279ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomonvoid SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2280ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         SkScalar sweepAngle, bool useCenter,
2281ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         const SkPaint& paint) {
2282ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2283ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    const SkRect* bounds = nullptr;
2284ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    if (paint.canComputeFastBounds()) {
2285ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        SkRect storage;
2286ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        // Note we're using the entire oval as the bounds.
2287ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2288ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon            return;
2289ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        }
2290ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        bounds = &oval;
2291ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2292ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2293ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
2294ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2295ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    while (iter.next()) {
2296ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        iter.fDevice->drawArc(iter, oval, startAngle, sweepAngle, useCenter, looper.paint());
2297ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2298ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2299ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    LOOPER_END
2300ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon}
2301ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
230241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
23039881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
230478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
230596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
23064ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
230787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
230887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
230987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
231087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &rrect.getBounds();
23114ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
23124ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
23134ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
23144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
23154ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2316f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2317f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
23184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2319f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2320f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
23214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2322f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
232378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2324f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2325f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2326f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2327f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2328f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2329f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
23304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
23314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2332ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2333ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
2334ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
233596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2336ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
233787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
233887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
233987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
234087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &outer.getBounds();
2341ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
234225c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2343ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
234425c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2345ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2346ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2347ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
234825c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2349ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2350ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
23514ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
235241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
23539881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
23549364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
23559364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
23569364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
23579364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
235878cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
235996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2360fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
236178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
236287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
236387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
236487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
236587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &pathBounds;
23668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23670b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
23680b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
23690b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
23706803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2371fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
23726651a3238dd6affa4276ada42ab613abf1d42d1dcaryclark            return;
2373fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2374fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
23758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
237678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
23778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
23794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
23808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
23838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2385262a71b7f95ce98ff3dd8dba845afbd724470903reedbool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2386262a71b7f95ce98ff3dd8dba845afbd724470903reed    if (!paint.getImageFilter()) {
2387262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2388262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2389262a71b7f95ce98ff3dd8dba845afbd724470903reed
2390262a71b7f95ce98ff3dd8dba845afbd724470903reed    const SkMatrix& ctm = this->getTotalMatrix();
2391c7e211acd0c9201688de7ff0c9a2271c67440adffmalita    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2392262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2393262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2394262a71b7f95ce98ff3dd8dba845afbd724470903reed
2395262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2396262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Once we can filter and the filter will return a result larger than itself, we should be
2397262a71b7f95ce98ff3dd8dba845afbd724470903reed    // able to remove this constraint.
2398262a71b7f95ce98ff3dd8dba845afbd724470903reed    // skbug.com/4526
2399262a71b7f95ce98ff3dd8dba845afbd724470903reed    //
2400262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkPoint pt;
2401262a71b7f95ce98ff3dd8dba845afbd724470903reed    ctm.mapXY(x, y, &pt);
2402262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2403262a71b7f95ce98ff3dd8dba845afbd724470903reed    return ir.contains(fMCRec->fRasterClip.getBounds());
2404262a71b7f95ce98ff3dd8dba845afbd724470903reed}
2405262a71b7f95ce98ff3dd8dba845afbd724470903reed
2406a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
24079881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2408a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2409a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
241096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
241187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = bounds;
241287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
241387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(tmp, &tmp);
241487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
241587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(tmp)) {
241687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
241787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2418a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
24199d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2420a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
242196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2422a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2423a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2424262a71b7f95ce98ff3dd8dba845afbd724470903reed
2425a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2426129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2427129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                                    *paint);
2428129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2429a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(image);
2430a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2431129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2432129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2433129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2434129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2435262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2436262a71b7f95ce98ff3dd8dba845afbd724470903reed
2437a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2438262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2439a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2440a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            SkPoint pt;
2441a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            iter.fMatrix->mapXY(x, y, &pt);
2442a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            iter.fDevice->drawSpecial(iter, special.get(),
2443a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
2444a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fY), pnt);
2445262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2446262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fDevice->drawImage(iter, image, x, y, pnt);
2447262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
2448a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
24499d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2450a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2451b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2452b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
245341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2454562fe4767cc73e08a4e039362bc0336aea66ecfbreed                               const SkPaint* paint, SrcRectConstraint constraint) {
24559881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
245696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2457c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage = dst;
245887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
245987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(dst, &storage);
246087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
246187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(storage)) {
246287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
246387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2464a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2465a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
246696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2467a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2468a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
24699d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2470c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2471c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
24729d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2473a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2474a5517e2b190a8083b38964972b031c13e99f1012reed        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
2475a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
24769d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2477a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2478b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2479b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
248041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
24819881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
24828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
24838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248433366974d43eae80e22284a2e445225c343859dareed    if (bitmap.drawsNothing()) {
248533366974d43eae80e22284a2e445225c343859dareed        return;
248633366974d43eae80e22284a2e445225c343859dareed    }
248733366974d43eae80e22284a2e445225c343859dareed
248833366974d43eae80e22284a2e445225c343859dareed    SkLazyPaint lazy;
248933366974d43eae80e22284a2e445225c343859dareed    if (nullptr == paint) {
249033366974d43eae80e22284a2e445225c343859dareed        paint = lazy.init();
249133366974d43eae80e22284a2e445225c343859dareed    }
249233366974d43eae80e22284a2e445225c343859dareed
249333366974d43eae80e22284a2e445225c343859dareed    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
249433366974d43eae80e22284a2e445225c343859dareed
249533366974d43eae80e22284a2e445225c343859dareed    SkRect storage;
249633366974d43eae80e22284a2e445225c343859dareed    const SkRect* bounds = nullptr;
249733366974d43eae80e22284a2e445225c343859dareed    if (paint->canComputeFastBounds()) {
249833366974d43eae80e22284a2e445225c343859dareed        bitmap.getBounds(&storage);
249933366974d43eae80e22284a2e445225c343859dareed        matrix.mapRect(&storage);
250087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = storage;
250187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) {
250287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
250387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
250487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
25058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25064b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2507a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2508129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), bitmap.height(),
2509129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                                              *paint);
2510129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2511a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(bitmap);
2512a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2513129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2514129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2515129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2516129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2517262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds)
251833366974d43eae80e22284a2e445225c343859dareed
251933366974d43eae80e22284a2e445225c343859dareed    while (iter.next()) {
2520262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2521a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2522262a71b7f95ce98ff3dd8dba845afbd724470903reed            SkPoint pt;
2523262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fMatrix->mapXY(x, y, &pt);
2524a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            iter.fDevice->drawSpecial(iter, special.get(),
2525a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
2526a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fY), pnt);
2527262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2528262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
2529262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
253033366974d43eae80e22284a2e445225c343859dareed    }
2531fbfa25802709139c2f14e304319c9541da65ca27msarett
253233366974d43eae80e22284a2e445225c343859dareed    LOOPER_END
25338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25359987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
25367112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2537eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2538a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
253950b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
25408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
25418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
254274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
254396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2544c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
254587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
254687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
254787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
25488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25493d60812865bb034851da777a91413ab584929887reed@google.com
255033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
255196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
255233535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
25538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25547064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2555c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2556c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
25577064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
255833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2559562fe4767cc73e08a4e039362bc0336aea66ecfbreed        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
2560f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
25617064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
256233535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
25638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
256541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2566562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                const SkPaint* paint, SrcRectConstraint constraint) {
25679881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
25689987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2569562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
25709987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
25719987ec3791336bad6af5cbe513564786b2df55aareed@google.com
25724c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
25734c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
25744c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
25759d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
257696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2577c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
257887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
257987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
258087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
25813d60812865bb034851da777a91413ab584929887reed@google.com    }
25829d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
25834c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
258496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
25854c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
25864c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
25879d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2588c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
25899d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
25904c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
25914c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
25929987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
25939d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
25944c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
25959987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
25969987ec3791336bad6af5cbe513564786b2df55aareed@google.com
259741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
259841af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
25999881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
26009987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
26019987ec3791336bad6af5cbe513564786b2df55aareed@google.com
260296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2603c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
260487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
260587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
260687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
26074c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
26089d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26094c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
261096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
26114c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
26124c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
26139d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2614c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
26159d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26164c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
26174c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
26184c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
26199d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26204c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
26219987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
26229987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2623168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2624168820625c35a8c19f66c661efcbce7a5e334837msarett                                  const SkPaint* paint) {
2625168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2626168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2627168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2628168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2629168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2630168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2631168820625c35a8c19f66c661efcbce7a5e334837msarett
2632168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2633168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2634168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2635168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2636168820625c35a8c19f66c661efcbce7a5e334837msarett
2637168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2638168820625c35a8c19f66c661efcbce7a5e334837msarett
2639168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2640168820625c35a8c19f66c661efcbce7a5e334837msarett        iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint());
2641168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2642168820625c35a8c19f66c661efcbce7a5e334837msarett
2643168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2644168820625c35a8c19f66c661efcbce7a5e334837msarett}
2645168820625c35a8c19f66c661efcbce7a5e334837msarett
2646168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2647168820625c35a8c19f66c661efcbce7a5e334837msarett                                   const SkRect& dst, const SkPaint* paint) {
2648168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2649168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2650168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2651168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2652168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2653168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2654168820625c35a8c19f66c661efcbce7a5e334837msarett
2655168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2656168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2657168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2658168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2659168820625c35a8c19f66c661efcbce7a5e334837msarett
2660168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2661168820625c35a8c19f66c661efcbce7a5e334837msarett
2662168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2663168820625c35a8c19f66c661efcbce7a5e334837msarett        iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint());
2664168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2665168820625c35a8c19f66c661efcbce7a5e334837msarett
2666168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2667168820625c35a8c19f66c661efcbce7a5e334837msarett}
2668168820625c35a8c19f66c661efcbce7a5e334837msarett
2669f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2670f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
26711f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2672112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2673112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2674a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2675112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2676f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2677f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2678f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2679f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2680f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2681f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2682f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2683f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2684f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
26852c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
26862c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2687f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2688f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2689e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2690e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
269196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
26928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
26944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2695f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
26968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
26998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2701e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2702e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
270305c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
270405c4a4322e7d4f3417b7df33825bab8603d52051fmalita
270596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
270687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
27078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
27084e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
270905c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2710f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
27118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2712b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
27134e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
27148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2716e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2717e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
271805c4a4322e7d4f3417b7df33825bab8603d52051fmalita
271905c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
272005c4a4322e7d4f3417b7df33825bab8603d52051fmalita
272196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
272287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
27238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
27244e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
272505c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2726f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
27278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2728b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
27294e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
27308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2732e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2733e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
273496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
273587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
27368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
27378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
27384e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
27398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2740b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2741945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
27424325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
27434325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
274445561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
274545561a0b15fe045ba272c328684c3f7ae290785areed                                 const SkRect* cullRect, const SkPaint& paint) {
274645561a0b15fe045ba272c328684c3f7ae290785areed    if (cullRect && this->quickReject(*cullRect)) {
274745561a0b15fe045ba272c328684c3f7ae290785areed        return;
274845561a0b15fe045ba272c328684c3f7ae290785areed    }
274945561a0b15fe045ba272c328684c3f7ae290785areed
275045561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
275145561a0b15fe045ba272c328684c3f7ae290785areed
275245561a0b15fe045ba272c328684c3f7ae290785areed    while (iter.next()) {
275345561a0b15fe045ba272c328684c3f7ae290785areed        iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint());
275445561a0b15fe045ba272c328684c3f7ae290785areed    }
275545561a0b15fe045ba272c328684c3f7ae290785areed
275645561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_END
275745561a0b15fe045ba272c328684c3f7ae290785areed}
275845561a0b15fe045ba272c328684c3f7ae290785areed
275900d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
276000d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
27617ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
276285d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
276396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
276419653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
276585d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
276687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp;
276787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
276887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
276987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
277087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
27717ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
27727ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2773024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2774024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2775024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
277696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fFilter = nullptr;
2777024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
277885d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
277900d5c2c6523321d25b32905ff4822f083a4173eefmalita
2780aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2781aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2782024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
278300d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
278400d5c2c6523321d25b32905ff4822f083a4173eefmalita
2785aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2786024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2787024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
278800d5c2c6523321d25b32905ff4822f083a4173eefmalita}
278900d5c2c6523321d25b32905ff4822f083a4173eefmalita
2790e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2791e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2792e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
27939881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2794ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2795ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawText(text, byteLength, x, y, paint);
2796ac09554dce518e9d4496771f648f3ae17eca857creed    }
2797e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2798e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2799e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
28009881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2801ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2802ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosText(text, byteLength, pos, paint);
2803ac09554dce518e9d4496771f648f3ae17eca857creed    }
2804e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2805e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2806e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
28079881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2808ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2809ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2810ac09554dce518e9d4496771f648f3ae17eca857creed    }
2811e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2812e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2813e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
28149881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2815ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2816ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2817ac09554dce518e9d4496771f648f3ae17eca857creed    }
2818e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
281945561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
282045561a0b15fe045ba272c328684c3f7ae290785areed                               const SkRect* cullRect, const SkPaint& paint) {
282145561a0b15fe045ba272c328684c3f7ae290785areed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()");
282245561a0b15fe045ba272c328684c3f7ae290785areed    if (byteLength) {
282345561a0b15fe045ba272c328684c3f7ae290785areed        this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
282445561a0b15fe045ba272c328684c3f7ae290785areed    }
282545561a0b15fe045ba272c328684c3f7ae290785areed}
282600d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
282700d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
2828e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(blob);
28299881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2830e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawTextBlob(blob, x, y, paint);
283100d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2832e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
283341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
283441af966ab338e95eee81ab618ab28195075338f7reed                              const SkPoint verts[], const SkPoint texs[],
2835faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                              const SkColor colors[], SkBlendMode bmode,
283641af966ab338e95eee81ab618ab28195075338f7reed                              const uint16_t indices[], int indexCount,
283741af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint& paint) {
28389881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
283996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
28404b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
28418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
28428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2843faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                                   colors, bmode, indices, indexCount,
28444e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
28458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28464b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
28474e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
28488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2850199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomonvoid SkCanvas::onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode bmode,
2851199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon                                    const SkPaint& paint, uint32_t flags) {
2852199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2853199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2854199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2855199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    while (iter.next()) {
2856199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon        // In the common case of one iteration we could std::move vertices here.
2857199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon        iter.fDevice->drawVerticesObject(iter, vertices, bmode, looper.paint(), flags);
2858199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    }
2859199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2860199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    LOOPER_END
2861199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon}
2862199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2863199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomonvoid SkCanvas::onDrawVerticesObjectFallback(sk_sp<SkVertices> vertices, SkBlendMode mode,
2864199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon                                            const SkPaint& paint, uint32_t flags) {
2865199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    const SkPoint* texs =
2866199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon            (flags & SkCanvas::kIgnoreTexCoords_VerticesFlag) ? nullptr : vertices->texCoords();
2867199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    const SkColor* colors = (flags & kIgnoreColors_VerticesFlag) ? nullptr : vertices->colors();
2868199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    this->onDrawVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(), texs,
2869199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon                         colors, mode, vertices->indices(), vertices->indexCount(), paint);
2870199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon}
2871199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2872b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
28737d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkPoint texCoords[4], SkBlendMode bmode,
28747d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkPaint& paint) {
28759881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
287696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == cubics) {
2877b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2878b3c9d1c33caf325aada244204215eb790c228c12dandov    }
28796cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2880faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed    this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
28819340c2685c0bb0e1e70008acaaf3d1448f074c38msarett}
28829340c2685c0bb0e1e70008acaaf3d1448f074c38msarett
28839340c2685c0bb0e1e70008acaaf3d1448f074c38msarettvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2884faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                           const SkPoint texCoords[4], SkBlendMode bmode,
28857d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                           const SkPaint& paint) {
2886ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2887ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2888ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2889b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2890ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2891ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2892ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
28936cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
289496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
28956cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2896ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2897faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, bmode, paint);
2898ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
28996cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2900ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2901ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2902ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2903a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2904e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2905e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (x || y) {
2906e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2907e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, &matrix);
2908e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2909e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, nullptr);
2910a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2911a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
2912a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
2913a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2914e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2915e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2916e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
29176a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
2918e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawDrawable(dr, matrix);
29196a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
29206a070dc06af4e9f305f9d08a69e34d18ade473cbreed
2921a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
29222a62e853c27cfacafd5c15ac1077cc13140589bareed    // drawable bounds are no longer reliable (e.g. android displaylist)
29232a62e853c27cfacafd5c15ac1077cc13140589bareed    // so don't use them for quick-reject
2924a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
29256a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
29266a070dc06af4e9f305f9d08a69e34d18ade473cbreed
292771c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2928faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                           const SkColor colors[], int count, SkBlendMode bmode,
292971c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
293071c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
293171c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
293271c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
293371c3c760a83123ee0b3127b8c65c6394ce541c50reed
293471c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
293571c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
293671c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
293771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
29389d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
293996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
294071c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
2941faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, bmode, pnt);
294271c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
294371c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
294471c3c760a83123ee0b3127b8c65c6394ce541c50reed}
294571c3c760a83123ee0b3127b8c65c6394ce541c50reed
2946f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2947f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkASSERT(key);
2948f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
2949f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkPaint paint;
2950f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2951f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    while (iter.next()) {
2952f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        iter.fDevice->drawAnnotation(iter, rect, key, value);
2953f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
2954f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_END
2955f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
2956f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
29578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
29588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
29598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
29608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
29618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29623661bc997620899695041010a750d11dbe8a972dMike Reed#ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS
2963374772bd61951f01bf84fe17bf53d8867681c9aereedvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkBlendMode mode) {
29649881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
29658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
29668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
2968374772bd61951f01bf84fe17bf53d8867681c9aereed    paint.setBlendMode(mode);
29698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
29708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29713661bc997620899695041010a750d11dbe8a972dMike Reed#endif
29728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2973374772bd61951f01bf84fe17bf53d8867681c9aereedvoid SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
29749881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
29758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
29768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2978374772bd61951f01bf84fe17bf53d8867681c9aereed    paint.setBlendMode(mode);
29798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
29808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
29839881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
29843661bc997620899695041010a750d11dbe8a972dMike Reed    const SkPoint pt = { x, y };
29858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
29868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29883661bc997620899695041010a750d11dbe8a972dMike Reed#ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS
29898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
29909881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
29918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
29928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
29934b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
29948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
29958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
29968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
29978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29983661bc997620899695041010a750d11dbe8a972dMike Reed#endif
29998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30003661bc997620899695041010a750d11dbe8a972dMike Reedvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
30019881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
30028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
30034b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
30048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
30058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
30068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
30078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30093661bc997620899695041010a750d11dbe8a972dMike Reed#ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS
30108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
30118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
30128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
30139881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
30148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
30158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
30178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
30188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30193661bc997620899695041010a750d11dbe8a972dMike Reed#endif
30208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30213661bc997620899695041010a750d11dbe8a972dMike Reedvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
30229881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
30238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
30248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
30258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
30268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
30288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
30294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
30308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
30338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
30349881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
30358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
30364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
30374ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
30384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
30398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
30408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
30418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
30428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
30458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
30468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
30479881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
304821af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    if (oval.isEmpty() || !sweepAngle) {
304921af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon        return;
30508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
305121af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
30528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
30558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
30568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
30579881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
30588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
30594b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
30608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
30618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
30628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3064f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
30651c2c441fede0ae9573afc098017011e3439624a9reed
30661c2c441fede0ae9573afc098017011e3439624a9reed/**
30671c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
30681c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
30691c2c441fede0ae9573afc098017011e3439624a9reed *
30701c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
30711c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
30721c2c441fede0ae9573afc098017011e3439624a9reed */
30731c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
30749b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
3075d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
3076e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(picture);
3077e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
30781c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
3079e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
3080e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
3081e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    }
3082e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
3083e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
3084e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        picture->playback(this);
3085e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
3086e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawPicture(picture, matrix, paint);
3087d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
3088d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
30899b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
3090d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
3091d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
3092d028180f0310cf2b23f9744256a41697b0683e67fmalita    if (!paint || paint->canComputeFastBounds()) {
3093d028180f0310cf2b23f9744256a41697b0683e67fmalita        SkRect bounds = picture->cullRect();
3094d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (paint) {
3095d028180f0310cf2b23f9744256a41697b0683e67fmalita            paint->computeFastBounds(bounds, &bounds);
3096d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
3097d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (matrix) {
3098d028180f0310cf2b23f9744256a41697b0683e67fmalita            matrix->mapRect(&bounds);
3099d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
3100d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (this->quickReject(bounds)) {
3101d028180f0310cf2b23f9744256a41697b0683e67fmalita            return;
3102d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
3103d028180f0310cf2b23f9744256a41697b0683e67fmalita    }
3104d028180f0310cf2b23f9744256a41697b0683e67fmalita
3105a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
3106c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
31078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
31088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
310995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
311095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::drawShadowedPicture(const SkPicture* picture,
311195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack                                   const SkMatrix* matrix,
3112e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                   const SkPaint* paint,
3113e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                   const SkShadowParams& params) {
311495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    RETURN_ON_NULL(picture);
311595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
311695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()");
311795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
3118e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    this->onDrawShadowedPicture(picture, matrix, paint, params);
311995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
312095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
312195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
312295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack                                     const SkMatrix* matrix,
3123e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                     const SkPaint* paint,
3124e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                     const SkShadowParams& params) {
3125904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    if (!paint || paint->canComputeFastBounds()) {
3126904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkRect bounds = picture->cullRect();
3127904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (paint) {
3128904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            paint->computeFastBounds(bounds, &bounds);
3129904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
3130904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (matrix) {
3131904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            matrix->mapRect(&bounds);
3132904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
3133904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (this->quickReject(bounds)) {
3134904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            return;
3135904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
3136904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
3137904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3138904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
3139904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3140e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    sk_sp<SkImage> povDepthMap;
3141e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    sk_sp<SkImage> diffuseMap;
3142e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack
3143904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    // povDepthMap
3144904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    {
3145904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkLights::Builder builder;
3146772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
3147772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack                                                     SkVector3::Make(0.0f, 0.0f, 1.0f)));
3148904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkLights> povLight = builder.finish();
3149904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3150904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
3151904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             picture->cullRect().height(),
3152904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kBGRA_8888_SkColorType,
3153904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kOpaque_SkAlphaType);
3154904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3155904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // Create a new surface (that matches the backend of canvas)
3156904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // to create the povDepthMap
3157904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkSurface> surf(this->makeSurface(info));
3158904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3159904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // Wrap another SPFCanvas around the surface
3160904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
3161904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
3162904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3163904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // set the depth map canvas to have the light as the user's POV
3164904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        depthMapCanvas->setLights(std::move(povLight));
3165904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3166904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        depthMapCanvas->drawPicture(picture);
3167904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        povDepthMap = surf->makeImageSnapshot();
3168904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
3169904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3170904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    // diffuseMap
3171904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    {
3172904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
3173904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             picture->cullRect().height(),
3174904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kBGRA_8888_SkColorType,
3175904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kOpaque_SkAlphaType);
3176904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3177904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkSurface> surf(this->makeSurface(info));
3178904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        surf->getCanvas()->drawPicture(picture);
3179904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3180904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        diffuseMap = surf->makeImageSnapshot();
3181904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
3182904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3183904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode,
3184904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                             SkShader::kClamp_TileMode);
3185904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode,
3186904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                           SkShader::kClamp_TileMode);
3187b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3188b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    // TODO: pass the depth to the shader in vertices, or uniforms
3189b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    //       so we don't have to render depth and color separately
3190b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    for (int i = 0; i < fLights->numLights(); ++i) {
3191b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        // skip over ambient lights; they don't cast shadows
3192b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        // lights that have shadow maps do not need updating (because lights are immutable)
3193b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        sk_sp<SkImage> depthMap;
3194b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        SkISize shMapSize;
3195b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3196b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (fLights->light(i).getShadowMap() != nullptr) {
3197b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            continue;
3198b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
3199b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3200b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (fLights->light(i).isRadial()) {
3201b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize.fHeight = 1;
3202b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize.fWidth = (int) picture->cullRect().width();
3203b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3204b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo info = SkImageInfo::Make(diffuseMap->width(), 1,
3205b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kBGRA_8888_SkColorType,
3206b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kOpaque_SkAlphaType);
3207b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3208b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Create new surface (that matches the backend of canvas)
3209b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // for each shadow map
3210b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> surf(this->makeSurface(info));
3211b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3212b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Wrap another SPFCanvas around the surface
3213b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkCanvas* depthMapCanvas = surf->getCanvas();
3214b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3215b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkLights::Builder builder;
3216b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            builder.add(fLights->light(i));
3217b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkLights> curLight = builder.finish();
3218b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3219b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkShader> shadowMapShader;
3220b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shadowMapShader = SkRadialShadowMapShader::Make(
3221b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    povDepthShader, curLight,
3222b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().width(),
3223b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().height());
3224b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3225b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkPaint shadowMapPaint;
3226b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shadowMapPaint.setShader(std::move(shadowMapShader));
3227b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3228b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setLights(curLight);
3229b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3230b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->drawRect(SkRect::MakeIWH(diffuseMap->width(),
3231b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     diffuseMap->height()),
3232b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                     shadowMapPaint);
3233b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3234b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMap = surf->makeImageSnapshot();
3235b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3236b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        } else {
3237b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: compute the correct size of the depth map from the light properties
3238b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: maybe add a kDepth_8_SkColorType
3239b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: find actual max depth of picture
3240b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize = SkShadowPaintFilterCanvas::ComputeDepthMapSize(
3241b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    fLights->light(i), 255,
3242b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().width(),
3243b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().height());
3244b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3245b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo info = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3246b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kBGRA_8888_SkColorType,
3247b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kOpaque_SkAlphaType);
3248b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3249b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Create a new surface (that matches the backend of canvas)
3250b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // for each shadow map
3251b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> surf(this->makeSurface(info));
3252b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3253b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Wrap another SPFCanvas around the surface
3254b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
3255b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
3256b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setShadowParams(params);
3257b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3258b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // set the depth map canvas to have the light we're drawing.
3259b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkLights::Builder builder;
3260b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            builder.add(fLights->light(i));
3261b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkLights> curLight = builder.finish();
3262b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setLights(std::move(curLight));
3263b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3264b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->drawPicture(picture);
3265b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMap = surf->makeImageSnapshot();
3266b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
3267b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3268b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (params.fType == SkShadowParams::kNoBlur_ShadowType) {
3269b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            fLights->light(i).setShadowMap(std::move(depthMap));
3270b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        } else if (params.fType == SkShadowParams::kVariance_ShadowType) {
3271b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // we blur the variance map
3272b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkPaint blurPaint;
3273b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            blurPaint.setImageFilter(SkImageFilter::MakeBlur(params.fShadowRadius,
3274b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                             params.fShadowRadius, nullptr));
3275b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3276b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo blurInfo = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3277b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     kBGRA_8888_SkColorType,
3278b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     kOpaque_SkAlphaType);
3279b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3280b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> blurSurf(this->makeSurface(blurInfo));
3281b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3282b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            blurSurf->getCanvas()->drawImage(std::move(depthMap), 0, 0, &blurPaint);
3283b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3284b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            fLights->light(i).setShadowMap(blurSurf->makeImageSnapshot());
3285b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
3286b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    }
3287b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3288b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    SkPaint shadowPaint;
3289904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader),
3290904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                        std::move(diffuseShader),
3291b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                        fLights,
3292904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                        diffuseMap->width(),
3293e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                                        diffuseMap->height(),
3294e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                                        params);
3295904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3296904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    shadowPaint.setShader(shadowShader);
3297904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3298904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    this->drawRect(SkRect::MakeIWH(diffuseMap->width(), diffuseMap->height()), shadowPaint);
329995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
330095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
330195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
33028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
33038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
33048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33053aafe111b6cc388400092851cc53bbbdfcb8a81creedSkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
330699fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
33078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
33098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33103aafe111b6cc388400092851cc53bbbdfcb8a81creed    fImpl = new (fStorage) SkDrawIter(canvas);
33118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
33128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
33138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
33158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
33168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
33178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
33198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
33208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
33218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33221f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
332399330ba6227137866a0dbd63478d36f335203ebdMike Reed    return fImpl->fDevice;
33248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
33258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
33278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
33288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
33298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
33318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
333296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
33338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
33348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
33358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
33368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
33378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33381e7f5e708e5daeb0c18ae49001c9e3cd5e3b13cbreedconst SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
33398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
33408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
334120a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
334220a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
334320a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
3344c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
33453107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
33463107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
33473107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
33483107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
33493107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
33503107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
33513107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
33523107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
33533107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
33543107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
33553107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
33563107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
33573107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
33583107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
33593107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
336028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
33619e3dbdff53f2d9957626a17a279730cda70f17bajunov        case kRGBA_F16_SkColorType:
33623107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
33633107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
33643107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
33653107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
33663107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
33673107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
33683107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
33693107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
33705df4934b3e40cdc378e225d1dda39f015cae9baeMike Reedstd::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
33715df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed                                                     size_t rowBytes) {
337242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
337396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
337442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
3375eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
337642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
337742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
337896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
337942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
33805df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed    return skstd::make_unique<SkCanvas>(bitmap);
338142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
3382d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3383d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
3384d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3385d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
3386a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
3387d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
3388d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
3389d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
339049f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
3391a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
3392d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
3393a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
3394d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
3395a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
339649f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
3397d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
3398d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
33996cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
340049f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
3401d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
3402d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
3403d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
3404d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3405d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3406d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
3407d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
3408e8f3062a36d3682f4019309a32b5b84dc9eddf8creed
3409ee424acbb87bf999be132a437527e656e37541d7Florin Malita///////////////////////////////////////////////////////////////////////////////
3410ee424acbb87bf999be132a437527e656e37541d7Florin Malita
3411ee424acbb87bf999be132a437527e656e37541d7Florin MalitaSkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
3412ee424acbb87bf999be132a437527e656e37541d7Florin Malita    : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
3413ee424acbb87bf999be132a437527e656e37541d7Florin Malita
3414439ace939b6aaa58408ece0e9e89b633353571aeFlorin MalitaSkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
3415439ace939b6aaa58408ece0e9e89b633353571aeFlorin Malita    : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
3416439ace939b6aaa58408ece0e9e89b633353571aeFlorin Malita
3417ee424acbb87bf999be132a437527e656e37541d7Florin MalitaSkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
3418ee424acbb87bf999be132a437527e656e37541d7Florin Malita    (void)this->INHERITED::getSaveLayerStrategy(rec);
3419ee424acbb87bf999be132a437527e656e37541d7Florin Malita    return kNoLayer_SaveLayerStrategy;
3420ee424acbb87bf999be132a437527e656e37541d7Florin Malita}
3421ee424acbb87bf999be132a437527e656e37541d7Florin Malita
3422ee424acbb87bf999be132a437527e656e37541d7Florin Malita///////////////////////////////////////////////////////////////////////////////
342373603f3c52ffd89fe9d035be827b566a0e7d3b79reed
342473603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
342573603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
342673603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
342773603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
342873603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
342973603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
3430356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3431356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed///////////////////////////////////////////////////////////////////////////////////////////////////
3432356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3433356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
3434356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (fAllocator && fMCRec->fTopLayer->fDevice) {
3435356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        const SkBaseDevice* dev = fMCRec->fTopLayer->fDevice;
3436356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
3437356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkIPoint origin = dev->getOrigin();
3438356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkMatrix ctm = this->getTotalMatrix();
3439356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
3440356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3441356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkIRect clip = fMCRec->fRasterClip.getBounds();
3442356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        clip.offset(-origin.x(), -origin.y());
3443108f55ed5d0b63baf653e4e443cc469df887c811Mike Reed        if (!clip.intersect(0, 0, dev->width(), dev->height())) {
3444356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            clip.setEmpty();
3445356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        }
3446356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3447356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        fAllocator->updateHandle(handle, ctm, clip);
3448356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return handle;
3449356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3450356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return nullptr;
3451356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3452356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3453356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedstatic bool install(SkBitmap* bm, const SkImageInfo& info,
3454356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                    const SkRasterHandleAllocator::Rec& rec) {
3455356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return bm->installPixels(info, rec.fPixels, rec.fRowBytes, nullptr,
3456356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                             rec.fReleaseProc, rec.fReleaseCtx);
3457356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3458356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3459356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
3460356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                     SkBitmap* bm) {
3461356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    SkRasterHandleAllocator::Rec rec;
3462356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
3463356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return nullptr;
3464356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3465356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return rec.fHandle;
3466356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3467356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3468356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedstd::unique_ptr<SkCanvas>
3469356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
3470356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                    const SkImageInfo& info, const Rec* rec) {
3471356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (!alloc || !supported_for_raster_canvas(info)) {
3472356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return nullptr;
3473356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3474356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3475356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    SkBitmap bm;
3476356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    Handle hndl;
3477356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3478356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (rec) {
3479356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
3480356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    } else {
3481356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        hndl = alloc->allocBitmap(info, &bm);
3482356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3483356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
3484356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3485