SkCanvas.cpp revision fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2c
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkBitmapDevice.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
10d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
11d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkClipStack.h"
12dbc3cefb0b624808ddb86d444e6103f216e12fa5reed#include "SkColorFilter.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
143cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
175f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt#include "SkErrorInternals.h"
18b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
19262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkImage_Base.h"
20900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilter.h"
21900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilterCache.h"
22c573a40ed5024b463e47088d307e3164a486dba5msarett#include "SkLatticeIter.h"
23262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkMatrixUtils.h"
2474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
25fbfa25802709139c2f14e304319c9541da65ca27msarett#include "SkNx.h"
26c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
27b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
29b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack#include "SkRadialShadowMapShader.h"
300017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
3196472deea70169396b8e1f576e470138f55fdb1freed#include "SkReadPixelsRec.h"
324ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
33904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack#include "SkShadowPaintFilterCanvas.h"
34904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack#include "SkShadowShader.h"
3579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkSmallAllocator.h"
364418dbac3386f26c8da62ab242be9c178961eb18robertphillips#include "SkSpecialImage.h"
3797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
387ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
3952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
40a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
418f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
42d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include <new>
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
44644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
457354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#include "GrContext.h"
46644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
47614d8f9a3c44e22d77fa909e82119e8a6746e1b1bsalomon#include "SkGrPriv.h"
48e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack
49644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
50644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
51e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed#define RETURN_ON_NULL(ptr)     do { if (nullptr == (ptr)) return; } while (0)
52e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
532d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed//#define SK_SUPPORT_PRECHECK_CLIPRECT
542d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed
55c83a29759a5c2966da5ab973e4fd90763e4c962breed/*
56c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Return true if the drawing this rect would hit every pixels in the canvas.
57c83a29759a5c2966da5ab973e4fd90763e4c962breed *
58c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Returns false if
59c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - rect does not contain the canvas' bounds
60c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint is not fill
61c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint would blur or otherwise change the coverage of the rect
62c83a29759a5c2966da5ab973e4fd90763e4c962breed */
63c83a29759a5c2966da5ab973e4fd90763e4c962breedbool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
64c83a29759a5c2966da5ab973e4fd90763e4c962breed                                           ShaderOverrideOpacity overrideOpacity) const {
6599fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
6699fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNone_ShaderOverrideOpacity,
6799fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums0");
6899fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
6999fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kOpaque_ShaderOverrideOpacity,
7099fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums1");
7199fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
7299fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNotOpaque_ShaderOverrideOpacity,
7399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums2");
74c83a29759a5c2966da5ab973e4fd90763e4c962breed
75c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkISize size = this->getBaseLayerSize();
76c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
77c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (!this->getClipStack()->quickContains(bounds)) {
78c83a29759a5c2966da5ab973e4fd90763e4c962breed        return false;
79c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
80c83a29759a5c2966da5ab973e4fd90763e4c962breed
81c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (rect) {
82c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        if (!this->getTotalMatrix().isScaleTranslate()) {
83c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
84c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
85c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary
86c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        SkRect devRect;
87c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        this->getTotalMatrix().mapRectScaleTranslate(&devRect, *rect);
88c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        if (!devRect.contains(bounds)) {
89c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
90c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
91c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
92c83a29759a5c2966da5ab973e4fd90763e4c962breed
93c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (paint) {
94c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkPaint::Style paintStyle = paint->getStyle();
95c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!(paintStyle == SkPaint::kFill_Style ||
96c83a29759a5c2966da5ab973e4fd90763e4c962breed              paintStyle == SkPaint::kStrokeAndFill_Style)) {
97c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
98c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
99c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (paint->getMaskFilter() || paint->getLooper()
100c83a29759a5c2966da5ab973e4fd90763e4c962breed            || paint->getPathEffect() || paint->getImageFilter()) {
101c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
102c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
103c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
104c83a29759a5c2966da5ab973e4fd90763e4c962breed    return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
105c83a29759a5c2966da5ab973e4fd90763e4c962breed}
106c83a29759a5c2966da5ab973e4fd90763e4c962breed
107c83a29759a5c2966da5ab973e4fd90763e4c962breed///////////////////////////////////////////////////////////////////////////////////////////////////
108c83a29759a5c2966da5ab973e4fd90763e4c962breed
109d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
110d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
111d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
112d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
113d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
114d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
115d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
116d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
1170acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
1180acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
1190acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
1200acf1b4b3645772d220c720313821bac389751b5reed}
1210acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
1220acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
1230acf1b4b3645772d220c720313821bac389751b5reed}
1240acf1b4b3645772d220c720313821bac389751b5reed
125da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
126da17f758442f16747af39f8fbaed9c097048519creed@google.com//#define SK_ENABLE_CLIP_QUICKREJECT
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;
2334b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            totalClip.translate(-x, -y, &fClip);
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
237045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // intersect clip, but don't translate it (yet)
2404b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (updateClip) {
242045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           SkRegion::kDifference_Op);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2454b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!fClip.isEmpty()) {
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkIRect deviceR;
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            deviceR.set(0, 0, width, height);
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(deviceR.contains(fClip.getBounds()));
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
253f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2651f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
266d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    DeviceCM*       fTopLayer;
2742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkRasterClip    fRasterClip;
2752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkMatrix        fMatrix;
2762ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int             fDeferredSaveCount;
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
278e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    // This is the current cumulative depth (aggregate of all done translateZ calls)
279e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    SkScalar        fCurDrawDepth;
280e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
281d954498c01ccf0417feacf89e45d0c62a06a813breed    MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
28296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fFilter     = nullptr;
28396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer      = nullptr;
28496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fTopLayer   = nullptr;
2852ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
2862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
287e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack        fCurDrawDepth      = 0;
288b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
289d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
290d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
291d954498c01ccf0417feacf89e45d0c62a06a813breed    }
292e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix),
293e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack                               fCurDrawDepth(prev.fCurDrawDepth) {
294d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
29596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer = nullptr;
296d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
2972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
298b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
30382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
304385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fLayer;
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
307feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
308feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
309feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
310feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
311feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
312feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
313feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
314feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
315feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31802f9ed74ead11fcb01a24faa7d93f853e869f1abreedstatic SkIRect compute_device_bounds(SkBaseDevice* device) {
31902f9ed74ead11fcb01a24faa7d93f853e869f1abreed    return SkIRect::MakeXYWH(device->getOrigin().x(), device->getOrigin().y(),
32002f9ed74ead11fcb01a24faa7d93f853e869f1abreed                             device->width(), device->height());
32102f9ed74ead11fcb01a24faa7d93f853e869f1abreed}
32202f9ed74ead11fcb01a24faa7d93f853e869f1abreed
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDrawIter : public SkDraw {
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3253aafe111b6cc388400092851cc53bbbdfcb8a81creed    SkDrawIter(SkCanvas* canvas) {
3264370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com        canvas = canvas->canvasForDrawIter();
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        canvas->updateDeviceCMCache();
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
329687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack = canvas->fClipStack;
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurrLayer = canvas->fMCRec->fTopLayer;
33102f9ed74ead11fcb01a24faa7d93f853e869f1abreed
33202f9ed74ead11fcb01a24faa7d93f853e869f1abreed        fMultiDeviceCS = nullptr;
33302f9ed74ead11fcb01a24faa7d93f853e869f1abreed        if (fCurrLayer->fNext) {
33402f9ed74ead11fcb01a24faa7d93f853e869f1abreed            fMultiDeviceCS = canvas->fClipStack;
33502f9ed74ead11fcb01a24faa7d93f853e869f1abreed            fMultiDeviceCS->save();
33602f9ed74ead11fcb01a24faa7d93f853e869f1abreed        }
33702f9ed74ead11fcb01a24faa7d93f853e869f1abreed    }
33802f9ed74ead11fcb01a24faa7d93f853e869f1abreed
33902f9ed74ead11fcb01a24faa7d93f853e869f1abreed    ~SkDrawIter() {
34002f9ed74ead11fcb01a24faa7d93f853e869f1abreed        if (fMultiDeviceCS) {
34102f9ed74ead11fcb01a24faa7d93f853e869f1abreed            fMultiDeviceCS->restore();
34202f9ed74ead11fcb01a24faa7d93f853e869f1abreed        }
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3444b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
34602f9ed74ead11fcb01a24faa7d93f853e869f1abreed        if (fMultiDeviceCS && fDevice) {
34702f9ed74ead11fcb01a24faa7d93f853e869f1abreed            // remove the previous device's bounds
34802f9ed74ead11fcb01a24faa7d93f853e869f1abreed            fMultiDeviceCS->clipDevRect(compute_device_bounds(fDevice),
34902f9ed74ead11fcb01a24faa7d93f853e869f1abreed                                        SkRegion::kDifference_Op);
35002f9ed74ead11fcb01a24faa7d93f853e869f1abreed        }
35102f9ed74ead11fcb01a24faa7d93f853e869f1abreed
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // skip over recs with empty clips
3533aafe111b6cc388400092851cc53bbbdfcb8a81creed        while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
3543aafe111b6cc388400092851cc53bbbdfcb8a81creed            fCurrLayer = fCurrLayer->fNext;
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
357f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
358f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fMatrix = rec->fMatrix;
361045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            fRC     = &rec->fClip;
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDevice = rec->fDevice;
36341e010cb901c0da9066c4df562030808c9ccd7f8reed            if (!fDevice->accessPixels(&fDst)) {
36496fcdcc219d2a0d3579719b84b28bede76efba64halcanary                fDst.reset(fDevice->imageInfo(), nullptr, 0);
36541e010cb901c0da9066c4df562030808c9ccd7f8reed            }
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPaint  = rec->fPaint;
367f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com            SkDEBUGCODE(this->validate();)
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
37096fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // fCurrLayer may be nullptr now
371199f108f14a5f60a9c2205ffa79b26102a206ad0reed@android.com
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3764b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3771f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* getDevice() const { return fDevice; }
3781e7f5e708e5daeb0c18ae49001c9e3cd5e3b13cbreed    const SkRasterClip& getClip() const { return *fRC; }
3796f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3806f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& getMatrix() const { return *fMatrix; }
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3836f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
38702f9ed74ead11fcb01a24faa7d93f853e869f1abreed    SkClipStack*    fMultiDeviceCS;
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkDraw INHERITED;
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
394dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
395dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
396dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
397dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
398dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
399dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
40096fcdcc219d2a0d3579719b84b28bede76efba64halcanary *  colorfilter, else return nullptr.
401dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
402d053ce9c54d4e5937a142278359e5a4cde18095ereedstatic sk_sp<SkColorFilter> image_to_color_filter(const SkPaint& paint) {
403dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
404dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
40596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
406dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
407dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
408d053ce9c54d4e5937a142278359e5a4cde18095ereed    SkColorFilter* imgCFPtr;
409d053ce9c54d4e5937a142278359e5a4cde18095ereed    if (!imgf->asAColorFilter(&imgCFPtr)) {
41096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
411dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
412d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> imgCF(imgCFPtr);
413dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
414dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
41596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paintCF) {
416dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
417dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
418dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
419dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
420dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
421dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
422d053ce9c54d4e5937a142278359e5a4cde18095ereed    return SkColorFilter::MakeComposeFilter(std::move(imgCF), sk_ref_sp(paintCF));
423dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
424dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
42587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco/**
42687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * There are many bounds in skia. A circle's bounds is just its center extended by its radius.
42787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * However, if we stroke a circle, then the "bounds" of that is larger, since it will now draw
42887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * outside of its raw-bounds by 1/2 the stroke width.  SkPaint has lots of optional
42987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * effects/attributes that can modify the effective bounds of a given primitive -- maskfilters,
43087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * patheffects, stroking, etc.  This function takes a raw bounds and a paint, and returns the
43187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * conservative "effective" bounds based on the settings in the paint... with one exception. This
43287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * function does *not* look at the imagefilter, which can also modify the effective bounds. It is
43387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * deliberately ignored.
43487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco */
43587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblancostatic const SkRect& apply_paint_to_bounds_sans_imagefilter(const SkPaint& paint,
43687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            const SkRect& rawBounds,
43787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            SkRect* storage) {
43887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    SkPaint tmpUnfiltered(paint);
43987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    tmpUnfiltered.setImageFilter(nullptr);
44087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    if (tmpUnfiltered.canComputeFastBounds()) {
44187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return tmpUnfiltered.computeFastBounds(rawBounds, storage);
44287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    } else {
44387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return rawBounds;
44487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    }
44587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco}
44687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
44987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the
45087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // paint. It's used to determine the size of the offscreen layer for filters.
45187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // If null, the clip will be used instead.
4523aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, bool skipLayerForImageFilter = false,
45387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                   const SkRect* rawBounds = nullptr) : fOrigPaint(paint) {
4544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
45553d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
4577765000709dc64eb23be7df47d1f995d1f787115fmalita#else
4587765000709dc64eb23be7df47d1f995d1f787115fmalita        fFilter = nullptr;
4597765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
4604a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
4614e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
4625c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
4634e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
465d053ce9c54d4e5937a142278359e5a4cde18095ereed        auto simplifiedCF = image_to_color_filter(fOrigPaint);
466dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
467dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
468d053ce9c54d4e5937a142278359e5a4cde18095ereed            paint->setColorFilter(std::move(simplifiedCF));
46996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            paint->setImageFilter(nullptr);
470dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
471dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
472dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
473dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
4745c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
4755c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
4765c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
4775c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
4785c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
4795c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
4805c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
4815c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
4825c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
4835c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
4845c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
4855c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
4865c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
4875c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
4885c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
4898926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
490dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            tmp.setImageFilter(fPaint->getImageFilter());
491cfb6bdf767796c950f89985445738d2d8e7f12b0reed            tmp.setXfermode(sk_ref_sp(fPaint->getXfermode()));
49287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            SkRect storage;
49387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            if (rawBounds) {
49487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                // Make rawBounds include all paint outsets except for those due to image filters.
49587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage);
49687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            }
497bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed            (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp),
49876033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
4995c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
5005c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
5018926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
5028926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
50379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
50479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
50579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                    looper->contextSize());
50679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            fLooperContext = looper->createContext(canvas, buffer);
507129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
508129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
50996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fLooperContext = nullptr;
510129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
5115c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
51474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
5165c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
5178926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
5188926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
5194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
52174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5224e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
5234e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
5244e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
5254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
52674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
527129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
528129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
529129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
530129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
531129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
532129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
533129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
534129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
535129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
536fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
53774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
539dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintInit; // base paint storage in case we need to modify it
540dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
5412c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
5422c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
5432c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
5442c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
5452c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
5465c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
5472c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
548129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
54979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
55079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkSmallAllocator<1, 32> fLooperContextAllocator;
551129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
552129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
555129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
55696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fPaint = nullptr;
557129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5585c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
559632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
560dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
561dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5628926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5635c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
56496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setImageFilter(nullptr);
56596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setXfermode(nullptr);
566129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5678926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
56879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
569129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
570129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
571129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
572129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
573971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
574971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
575971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
576971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
57796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fLooperContext) {
578129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
579632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
580632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
581129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
582129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
5838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
584129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
58579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
5864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
5874e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5884e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
589632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
590632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
59196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = nullptr;
5924e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
5934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
5954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
5964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5993aafe111b6cc388400092851cc53bbbdfcb8a81creed#define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds)  \
6003aafe111b6cc388400092851cc53bbbdfcb8a81creed    this->predrawNotify();                                          \
6013aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper looper(this, paint, skipLayerForFilter, bounds); \
6023aafe111b6cc388400092851cc53bbbdfcb8a81creed    while (looper.next(SkDrawFilter::kBitmap_Type)) {               \
603262a71b7f95ce98ff3dd8dba845afbd724470903reed        SkDrawIter iter(this);
604262a71b7f95ce98ff3dd8dba845afbd724470903reed
605262a71b7f95ce98ff3dd8dba845afbd724470903reed
6068926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
60797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
6083aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, true);                      \
6098926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
6108926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
6118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
61278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
61397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
6143aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
6154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
6174b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
618c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
619c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
6203aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
621c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
622c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
623c83a29759a5c2966da5ab973e4fd90763e4c962breed
6244e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
628fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline SkRect qr_clip_bounds(const SkIRect& bounds) {
629fbfa25802709139c2f14e304319c9541da65ca27msarett    if (bounds.isEmpty()) {
630fbfa25802709139c2f14e304319c9541da65ca27msarett        return SkRect::MakeEmpty();
631fbfa25802709139c2f14e304319c9541da65ca27msarett    }
632fbfa25802709139c2f14e304319c9541da65ca27msarett
633fbfa25802709139c2f14e304319c9541da65ca27msarett    // Expand bounds out by 1 in case we are anti-aliasing.  We store the
634fbfa25802709139c2f14e304319c9541da65ca27msarett    // bounds as floats to enable a faster quick reject implementation.
635fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect dst;
636fbfa25802709139c2f14e304319c9541da65ca27msarett    SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&dst.fLeft);
637fbfa25802709139c2f14e304319c9541da65ca27msarett    return dst;
638fbfa25802709139c2f14e304319c9541da65ca27msarett}
639fbfa25802709139c2f14e304319c9541da65ca27msarett
640feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
641feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
642feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fClipStack->reset();
643feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
644feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
645feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
646feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice).
647feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
648fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(bounds);
6499637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
650feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
651feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
652d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
65342b73eb00367c8315974b1c374308d20efa78897reed    if (device && device->forceConservativeRasterClip()) {
65442b73eb00367c8315974b1c374308d20efa78897reed        flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
65542b73eb00367c8315974b1c374308d20efa78897reed    }
65642b73eb00367c8315974b1c374308d20efa78897reed    // Since init() is only called once by our constructors, it is safe to perform this
65742b73eb00367c8315974b1c374308d20efa78897reed    // const-cast.
65842b73eb00367c8315974b1c374308d20efa78897reed    *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativeRasterClip_InitFlag);
65942b73eb00367c8315974b1c374308d20efa78897reed
6608f0a7b8e7334187a5d7d5ab7fde5a3c3009555f5caryclark@google.com    fAllowSoftClip = true;
66145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
662f92c86642a1875da54d54b447f006cb9dfbbb35creed    fDeviceCMDirty = true;
6632ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
66496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMetaData = nullptr;
66595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
66695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    fLights = nullptr;
66795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
669385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    fClipStack.reset(new SkClipStack);
670687fa1c745febb57f42b0d5f03d7c1f4be2530careed
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
672d954498c01ccf0417feacf89e45d0c62a06a813breed    new (fMCRec) MCRec(fConservativeRasterClip);
6739637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
675a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
676a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
6777503d60847c4ad22df87458aecd917772b23d293reed    new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip,
6788c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                    fMCRec->fMatrix);
679b679ca8926a832274b14fdb512f88f64b61d32eareed
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
68296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fSurfaceBase = nullptr;
683f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
684f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
685efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
686efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
687f92c86642a1875da54d54b447f006cb9dfbbb35creed        fMCRec->fLayer->fDevice = SkRef(device);
68878e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
689fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
690f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
691fbfa25802709139c2f14e304319c9541da65ca27msarett
692f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
695cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
696e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6974a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
69842b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
699e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
7008d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
701ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
70296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    this->init(nullptr, kDefault_InitFlags);
7038d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
7048d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
705d954498c01ccf0417feacf89e45d0c62a06a813breedstatic SkBitmap make_nopixels(int width, int height) {
706d954498c01ccf0417feacf89e45d0c62a06a813breed    SkBitmap bitmap;
707d954498c01ccf0417feacf89e45d0c62a06a813breed    bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
708d954498c01ccf0417feacf89e45d0c62a06a813breed    return bitmap;
709d954498c01ccf0417feacf89e45d0c62a06a813breed}
710d954498c01ccf0417feacf89e45d0c62a06a813breed
711d954498c01ccf0417feacf89e45d0c62a06a813breedclass SkNoPixelsBitmapDevice : public SkBitmapDevice {
712d954498c01ccf0417feacf89e45d0c62a06a813breedpublic:
713fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps)
714fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips        : INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps)
71578e276889795454891cbba48ab11927968114953reed    {
71678e276889795454891cbba48ab11927968114953reed        this->setOrigin(bounds.x(), bounds.y());
71778e276889795454891cbba48ab11927968114953reed    }
718d954498c01ccf0417feacf89e45d0c62a06a813breed
719d954498c01ccf0417feacf89e45d0c62a06a813breedprivate:
720b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
721d954498c01ccf0417feacf89e45d0c62a06a813breed    typedef SkBitmapDevice INHERITED;
722d954498c01ccf0417feacf89e45d0c62a06a813breed};
723d954498c01ccf0417feacf89e45d0c62a06a813breed
72496a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
725e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
72696a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
72742b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
728e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
729e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
730b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
731385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    this->init(new SkNoPixelsBitmapDevice(SkIRect::MakeWH(width, height), fProps),
732385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary               kDefault_InitFlags)->unref();
733d954498c01ccf0417feacf89e45d0c62a06a813breed}
734e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
73578e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
736d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7374a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
73842b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
739d954498c01ccf0417feacf89e45d0c62a06a813breed{
740d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
741b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
742385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    this->init(new SkNoPixelsBitmapDevice(bounds, fProps), flags)->unref();
74327a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
745d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
746d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7477b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
74842b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
749d954498c01ccf0417feacf89e45d0c62a06a813breed{
750d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
751b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
752d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
755fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
756fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7577b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
75842b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
759fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
760fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
761fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
762fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
763fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
764fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
7654a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
7663716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7674a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
76842b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
7693716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7703716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
771b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
772385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
7734a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7744a8126e7f81384526629b1e21bf89b632ea13cd9reed}
77529c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
7764a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap)
7774a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7784a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
77942b73eb00367c8315974b1c374308d20efa78897reed    , fConservativeRasterClip(false)
7804a8126e7f81384526629b1e21bf89b632ea13cd9reed{
7814a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
782b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
783385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
7844a8126e7f81384526629b1e21bf89b632ea13cd9reed    this->init(device, kDefault_InitFlags);
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
7907c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
793385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete fMetaData;
794b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
79853d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
80451985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8087765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
81074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
81174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
81274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
81396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fMetaData) {
81474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
81574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
81674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
81774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
81874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
821bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
822ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    this->onFlush();
823ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
824ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
825ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedvoid SkCanvas::onFlush() {
8261f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
827bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
828bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
829bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
830bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
831bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
832afc7cce5d68663934128d76963cd501f771d71desenorblancoSkISize SkCanvas::getBaseLayerSize() const {
833afc7cce5d68663934128d76963cd501f771d71desenorblanco    SkBaseDevice* d = this->getDevice();
8344ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
8354ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
8364ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
837afc7cce5d68663934128d76963cd501f771d71desenorblancoSkIRect SkCanvas::getTopLayerBounds() const {
8384ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
839afc7cce5d68663934128d76963cd501f771d71desenorblanco    if (!d) {
840afc7cce5d68663934128d76963cd501f771d71desenorblanco        return SkIRect::MakeEmpty();
841afc7cce5d68663934128d76963cd501f771d71desenorblanco    }
842afc7cce5d68663934128d76963cd501f771d71desenorblanco    return SkIRect::MakeXYWH(d->getOrigin().x(), d->getOrigin().y(), d->width(), d->height());
843210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
844210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
8451f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
847c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec->fLayer->fDevice;
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8521f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
8530b53d59a24f667350b4282f88470713902409030reed@google.com    if (updateMatrixClip) {
8540b53d59a24f667350b4282f88470713902409030reed@google.com        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
8550b53d59a24f667350b4282f88470713902409030reed@google.com    }
8569266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com    return fMCRec->fTopLayer->fDevice;
8579266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
8589266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
859a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
860c7ec7c9cabf5c8ad08beb617b99831ece25dacddreed    if (kUnknown_SkColorType == bitmap->colorType()) {
861a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
862a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
863a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
864a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    bool weAllocated = false;
86596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == bitmap->pixelRef()) {
866848250415eddc54075f7eb8795e8db79e749c6abreed        if (!bitmap->tryAllocPixels()) {
867a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org            return false;
868a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        }
869a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        weAllocated = true;
870a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
871a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
872cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
873cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap->requestLock(&unlocker)) {
874cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
875cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
876cf01e31df6bbda270dca2ee3b4967caf51e465dcreed            return true;
877cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        }
878a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
879a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org
880a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (weAllocated) {
88196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        bitmap->setPixelRef(nullptr);
882a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
883a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return false;
884a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
88551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
886c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.combool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
887a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkIRect r = srcRect;
888a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
889a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!r.intersect(0, 0, size.width(), size.height())) {
890a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
891ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return false;
892ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
89374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
894848250415eddc54075f7eb8795e8db79e749c6abreed    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
895a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        // bitmap will already be reset.
896a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
897a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
898a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
899a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        bitmap->reset();
900daba14b7d4fc96b915c45d82713b22729c0d0f37bsalomon@google.com        return false;
901c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    }
902a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    return true;
903a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org}
904c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com
90596472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
906a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
907a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
908a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
909a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
910a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
911f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
91296472deea70169396b8e1f576e470138f55fdb1freed    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
91396472deea70169396b8e1f576e470138f55fdb1freed    if (!rec.trim(size.width(), size.height())) {
914a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
915a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
916db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
917a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
91896472deea70169396b8e1f576e470138f55fdb1freed    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
91951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
92051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9214cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
922cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    SkAutoPixmapUnlock unlocker;
923cf01e31df6bbda270dca2ee3b4967caf51e465dcreed    if (bitmap.requestLock(&unlocker)) {
924cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        const SkPixmap& pm = unlocker.pixmap();
925cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
9264cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9274cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
9284cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
9294cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9304cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
9314cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
9324cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    switch (origInfo.colorType()) {
9334cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kUnknown_SkColorType:
9344cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        case kIndex_8_SkColorType:
9354cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            return false;
9364cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        default:
9374cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org            break;
9384cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
93996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == pixels || rowBytes < origInfo.minRowBytes()) {
9404cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9414cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9424cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9434cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    const SkISize size = this->getBaseLayerSize();
9444cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
9454cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!target.intersect(0, 0, size.width(), size.height())) {
9464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
9504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
9514cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
9524cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9534cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9544cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // the intersect may have shrunk info's logical size
955e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
9564cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9574cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // if x or y are negative, then we have to adjust pixels
9584cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (x > 0) {
9594cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        x = 0;
9604cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9614cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (y > 0) {
9624cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        y = 0;
9634cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
9644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // here x,y are either 0 or negative
9654cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
9664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
9674af35f348b2e2f6c428819118eb7a2f2fff53a74reed    // Tell our owning surface to bump its generation ID
968c83a29759a5c2966da5ab973e4fd90763e4c962breed    const bool completeOverwrite = info.dimensions() == size;
969c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
9704af35f348b2e2f6c428819118eb7a2f2fff53a74reed
9714cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    // The device can assert that the requested area is always contained in its bounds
9724ef54f8d72420a521d4aae04ff5cd438810eca7fcommit-bot@chromium.org    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
9734cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
97451df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
9754370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.comSkCanvas* SkCanvas::canvasForDrawIter() {
9764370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com    return this;
9774370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com}
9784370aedf7f55af74e9ebb4ad1c2e010c08236dfajunov@google.com
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::updateDeviceCMCache() {
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDeviceCMDirty) {
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkMatrix& totalMatrix = this->getTotalMatrix();
9841f836ee096bb988adef4b9757b2629c7afeda36dreed        const SkRasterClip& totalClip = fMCRec->fRasterClip;
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DeviceCM*       layer = fMCRec->fTopLayer;
9864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
98796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == layer->fNext) {   // only one layer
988de6c531e468197bb7746f1217a8ccb2ab175e0b8reed            layer->updateMC(totalMatrix, totalClip, nullptr);
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
990045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com            SkRasterClip clip(totalClip);
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
992de6c531e468197bb7746f1217a8ccb2ab175e0b8reed                layer->updateMC(totalMatrix, clip, &clip);
99396fcdcc219d2a0d3579719b84b28bede76efba64halcanary            } while ((layer = layer->fNext) != nullptr);
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDeviceCMDirty = false;
9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
10022ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
10032ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
10042ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
10052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
10062ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
1007f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
10082ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
10092ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
10102ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
10112ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
10122ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
10132ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
10142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
10152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
10162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
10172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
10182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
10192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
10202ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
1021f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1022f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1023f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
10242ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
10252ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
10262ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
10272ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
10282ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
10292ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
1030f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
1031a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
1032a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
1033a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
10342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1035f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1036f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1037f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
10382ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
10392ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
10402ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
10412ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
10422ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
10432ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
10442ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
10452ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
10462ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
1047a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
10482ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
10492ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
10502ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
1051f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1052f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1053f0090cb80ab10a49e511aa5450ae38917fa058d9reed
1054f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
1055f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
1056f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
1057f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
1058f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1059f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
1060f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
1061f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
1062f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
1063f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
1064f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
1065f0090cb80ab10a49e511aa5450ae38917fa058d9reed
10662ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
1068d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
10704b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
1071687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->save();
10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10744960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
10754960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag);
10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10784960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
10799b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
1080bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect clipBounds;
1081bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (!this->getClipDeviceBounds(&clipBounds)) {
1082a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
1083f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
1084c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
108596e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
108696e657d0e103b8358a77ecd913f6086929f792b8reed
1087c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
1088e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco        clipBounds = imageFilter->filterBounds(clipBounds, ctm);
1089db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        if (bounds && !imageFilter->canComputeFastBounds()) {
1090db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco            bounds = nullptr;
1091db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        }
1092c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
1093bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
109449f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
10964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
109796e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
11014960eeec4a1f2a772654883d7f3615d47bcd5dc3reed            if (BoundsAffectsClip(saveLayerFlags)) {
11021f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
1103fbfa25802709139c2f14e304319c9541da65ca27msarett                fDeviceClipBounds.setEmpty();
1104bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
1105a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1110180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11124960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (BoundsAffectsClip(saveLayerFlags)) {
1113180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
1114687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
1115180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
1116fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(ir);
1117a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1118a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1119a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
1120a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
1121a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
1122a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
1123a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
1124a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
11254960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11264960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
11274960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, 0));
1128d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1129d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
11304960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) {
11314960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag));
11324960eeec4a1f2a772654883d7f3615d47bcd5dc3reed}
11334960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11344960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SaveLayerRec& origRec) {
11354960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerRec rec(origRec);
1136d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
11374960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        rec.fBounds = nullptr;
1138d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
11394960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec);
1140a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
11414960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    this->internalSaveLayer(rec, strategy);
11422ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
11438926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
11448926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
1145a2217ef965e57fdbbf989989e7ec1f2c04f62d39reedvoid SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1146a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                    SkBaseDevice* dst, const SkMatrix& ctm,
1147a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                    const SkClipStack* clipStack) {
1148a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkDraw draw;
1149a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkRasterClip rc;
1150a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
1151a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (!dst->accessPixels(&draw.fDst)) {
1152a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        draw.fDst.reset(dst->imageInfo(), nullptr, 0);
1153a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1154a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fMatrix = &SkMatrix::I();
1155a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fRC = &rc;
1156a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fClipStack = clipStack;
1157a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fDevice = dst;
11587354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
11597354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    SkPaint p;
1160372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips    p.setImageFilter(filter->makeWithLocalMatrix(ctm));
1161a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1162a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    int x = src->getOrigin().x() - dst->getOrigin().x();
1163a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    int y = src->getOrigin().y() - dst->getOrigin().y();
1164a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    auto special = src->snapSpecial();
1165a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (special) {
1166a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        dst->drawSpecial(draw, special.get(), x, y, p);
1167a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
11687354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips}
116970ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed
1170129ed1cd6d792f3f6cf563aefa9756fc6308289dreedstatic SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque,
1171129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                   const SkPaint* paint) {
1172129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // need to force L32 for now if we have an image filter. Once filters support other colortypes
1173129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // e.g. sRGB or F16, we can remove this check
117452ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman    // SRGBTODO: Can we remove this check now?
1175129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    const bool hasImageFilter = paint && paint->getImageFilter();
1176129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1177129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
1178129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1179129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // force to L32
1180129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        return SkImageInfo::MakeN32(w, h, alphaType);
1181129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    } else {
1182129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // keep the same characteristics as the prev
118352ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman        return SkImageInfo::Make(w, h, prev.colorType(), alphaType, sk_ref_sp(prev.colorSpace()));
1184129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
1185129ed1cd6d792f3f6cf563aefa9756fc6308289dreed}
1186129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
11874960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
11884960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkRect* bounds = rec.fBounds;
11894960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkPaint* paint = rec.fPaint;
11904960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
11914960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
11928c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkLazyPaint lazyP;
11938c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
11948c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix stashedMatrix = fMCRec->fMatrix;
11958c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix remainder;
11968c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkSize scale;
11978c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    /*
11988c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
11998c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  but they do handle scaling. To accommodate this, we do the following:
12008c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
12018c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  1. Stash off the current CTM
12028c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  2. Decompose the CTM into SCALE and REMAINDER
12038c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
12048c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     contains the REMAINDER
12058c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
12068c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
12078c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     of the original imagefilter, and draw that (via drawSprite)
12088c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
12098c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
12108c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
12118c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
12128c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     */
121396a04f329926099f0002f97883242793ff04f61creed    if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
12148c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        stashedMatrix.decomposeScale(&scale, &remainder))
12158c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    {
12168c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
12178c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
12188c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        SkPaint* p = lazyP.set(*paint);
12198c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
12208c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          SkFilterQuality::kLow_SkFilterQuality,
12218c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          sk_ref_sp(imageFilter)));
12228c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        imageFilter = p->getImageFilter();
12238c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        paint = p;
12248c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    }
12258c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
1226a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1227a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
12282ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1229a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1230a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    fDeviceCMDirty = true;
1231a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1232a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
12338c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
12342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1237e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1238e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1239e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
12402ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1241e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1242e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
12434960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
12448dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
12458dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
124676033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1247daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
124876033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
12498dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1250b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1251b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12535139e501c5ac3a511e35c78395c907a176113451robertphillips    SkBaseDevice* priorDevice = this->getTopDevice();
1254a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (nullptr == priorDevice) {
1255b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
12562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1257b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1258b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
12595139e501c5ac3a511e35c78395c907a176113451robertphillips    SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), isOpaque,
1260129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                       paint);
1261129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
12625139e501c5ac3a511e35c78395c907a176113451robertphillips    SkAutoTUnref<SkBaseDevice> newDevice;
126361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
126470ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
12654960eeec4a1f2a772654883d7f3615d47bcd5dc3reed                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1266daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
126770ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1268cd4051e1c4770edc03b27663c6c96ec8987122bdreed                                                                             preserveLCDText);
12695139e501c5ac3a511e35c78395c907a176113451robertphillips        newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
12705139e501c5ac3a511e35c78395c907a176113451robertphillips        if (!newDevice) {
12717503d60847c4ad22df87458aecd917772b23d293reed            SkErrorInternals::SetError(kInternalError_SkError,
12727503d60847c4ad22df87458aecd917772b23d293reed                                       "Unable to create device for layer.");
12737503d60847c4ad22df87458aecd917772b23d293reed            return;
127461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
1275e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
12765139e501c5ac3a511e35c78395c907a176113451robertphillips    newDevice->setOrigin(ir.fLeft, ir.fTop);
12777354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
12785139e501c5ac3a511e35c78395c907a176113451robertphillips    DeviceCM* layer = new DeviceCM(newDevice, paint, this, fConservativeRasterClip, stashedMatrix);
12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    layer->fNext = fMCRec->fTopLayer;
12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1283a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1284a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (rec.fBackdrop) {
1285a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice,
1286a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                             fMCRec->fMatrix, this->getClipStack());
1287a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1290d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1291bada1885da479d948f065182d6dfa85a1140bda5reed    if (0xFF == alpha) {
1292bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, nullptr);
1293bada1885da479d948f065182d6dfa85a1140bda5reed    } else {
1294bada1885da479d948f065182d6dfa85a1140bda5reed        SkPaint tmpPaint;
1295bada1885da479d948f065182d6dfa85a1140bda5reed        tmpPaint.setAlpha(alpha);
1296bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, &tmpPaint);
1297bada1885da479d948f065182d6dfa85a1140bda5reed    }
1298d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1299d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1305687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->restore();
13066c157640c27ee2ed6f9a484d21691b7b19dfecdecommit-bot@chromium.org
130788edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
131096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fLayer = nullptr;
13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
132149f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (layer->fNext) {
13236f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
13247503d60847c4ad22df87458aecd917772b23d293reed            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), layer->fPaint);
13258c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // restore what we smashed in internalSaveLayer
13268c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            fMCRec->fMatrix = layer->fStashedMatrix;
13278926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDeviceCMDirty = true;
1329385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete layer;
1330b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1331b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1332a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1333b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
13348c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // no need to update fMCRec, 'cause we're killing the canvas
13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
133688edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1337fbfa25802709139c2f14e304319c9541da65ca27msarett
1338fbfa25802709139c2f14e304319c9541da65ca27msarett    if (fMCRec) {
13399637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett        fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1340fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1341fbfa25802709139c2f14e304319c9541da65ca27msarett    }
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1344e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
134596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == props) {
13464a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
13474a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
13484a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
134976f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
135076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1351e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
135276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
1353e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    return dev ? dev->makeSurface(info, props) : nullptr;
135476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
135576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1356c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1357ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onImageInfo();
1358ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1359ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1360ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedSkImageInfo SkCanvas::onImageInfo() const {
1361c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1362c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1363c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1364c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1365900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1366c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1367c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1368c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1369898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosmanbool SkCanvas::getProps(SkSurfaceProps* props) const {
1370ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onGetProps(props);
1371ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1372ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1373ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedbool SkCanvas::onGetProps(SkSurfaceProps* props) const {
1374898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    SkBaseDevice* dev = this->getDevice();
1375898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    if (dev) {
1376898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        if (props) {
1377898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman            *props = fProps;
1378898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        }
1379898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return true;
1380898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    } else {
1381898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return false;
1382898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    }
1383898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman}
1384898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman
13856ceeebd37a43d879c120b6ba100ae1febdd67a18reed#ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS
1386c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1387884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
13886ceeebd37a43d879c120b6ba100ae1febdd67a18reed    if (this->peekPixels(&pmap)) {
13896ceeebd37a43d879c120b6ba100ae1febdd67a18reed        if (info) {
13906ceeebd37a43d879c120b6ba100ae1febdd67a18reed            *info = pmap.info();
13916ceeebd37a43d879c120b6ba100ae1febdd67a18reed        }
13926ceeebd37a43d879c120b6ba100ae1febdd67a18reed        if (rowBytes) {
13936ceeebd37a43d879c120b6ba100ae1febdd67a18reed            *rowBytes = pmap.rowBytes();
13946ceeebd37a43d879c120b6ba100ae1febdd67a18reed        }
13956ceeebd37a43d879c120b6ba100ae1febdd67a18reed        return pmap.addr();
1396884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
13976ceeebd37a43d879c120b6ba100ae1febdd67a18reed    return nullptr;
13986ceeebd37a43d879c120b6ba100ae1febdd67a18reed}
13996ceeebd37a43d879c120b6ba100ae1febdd67a18reed#endif
14006ceeebd37a43d879c120b6ba100ae1febdd67a18reed
14016ceeebd37a43d879c120b6ba100ae1febdd67a18reedbool SkCanvas::peekPixels(SkPixmap* pmap) {
14026ceeebd37a43d879c120b6ba100ae1febdd67a18reed    return this->onPeekPixels(pmap);
1403c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1404c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1405884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1406c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1407884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1408c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1409c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
14106b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1411884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1412884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
141396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1414884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1415884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1416884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1417884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1418884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1419884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1420884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1421884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
14226b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org        *origin = this->getTopDevice(false)->getOrigin();
14236b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1424884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
14259c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
14269c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1427884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
14289c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1429884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
14309c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
14319c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1432520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14347503d60847c4ad22df87458aecd917772b23d293reedvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint) {
14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
143696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14394b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
14408926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1441a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
14431f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
144476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
144576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
144676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1447f35566e8a2497cd7c7bcfeee00c507b3e8ba1587senorblanco        if (filter) {
1448a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            dstDev->drawSpecial(iter, srcDev->snapSpecial().get(), pos.x(), pos.y(), *paint);
144976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1450b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
145176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1453a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
14544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
145732704674f64cb6a14356dfebe060cd3484c06cc7reed/////////////////////////////////////////////////////////////////////////////
1458da420b976e61071cfe5de10556b4b23e519091d6reed
145992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1460fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    if (dx || dy) {
1461fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->checkForDeferredSave();
1462fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        fDeviceCMDirty = true;
1463fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        fMCRec->fMatrix.preTranslate(dx,dy);
1464cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1465fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        // Translate shouldn't affect the is-scale-translateness of the matrix.
1466fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1467cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1468fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->didTranslate(dx,dy);
1469fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    }
14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
147292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1473d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1474d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1475d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
147892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1479d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1480d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1481d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14847438bfc0804d021aa92cdd5ea644994a4248f3dbbungemanvoid SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
14857438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    SkMatrix m;
14867438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    m.setRotate(degrees, px, py);
14877438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    this->concat(m);
14887438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman}
14897438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman
149092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1491d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1492d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1493d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
149444c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
149544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
149692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1497d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1498d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1499d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1500d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
15012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
15031f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
15049637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
150544c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
150644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
150744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
15088c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
15098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
15101f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
15119da5a5a198e5dc9148f7f30a6089377590eee55bmsarett    fIsScaleTranslate = matrix.isScaleTranslate();
15128c30a8196dd5903d2d23b4d0a5dc888e802bf698reed}
15138c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
15148c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
15158c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->checkForDeferredSave();
15168c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->internalSetMatrix(matrix);
151744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
15218c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->setMatrix(SkMatrix::I());
15228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
152495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
1525e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblackvoid SkCanvas::translateZ(SkScalar z) {
1526e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->checkForDeferredSave();
1527e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->fMCRec->fCurDrawDepth += z;
1528e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->didTranslateZ(z);
1529e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack}
1530e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
1531e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblackSkScalar SkCanvas::getZ() const {
1532e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    return this->fMCRec->fCurDrawDepth;
1533e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack}
1534e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
153595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::setLights(sk_sp<SkLights> lights) {
153695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    this->fLights = lights;
153795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
153895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
153995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblacksk_sp<SkLights> SkCanvas::getLights() const {
154095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    return this->fLights;
154195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
154295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
154395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
15448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
15458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1546759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
15472d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed    if (!fAllowSoftClip) {
15482d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed        doAA = false;
15492d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed    }
15502d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed
15512d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed#ifdef SK_SUPPORT_PRECHECK_CLIPRECT
15522d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed    // Check if we can quick-accept the clip call (and do nothing)
15532d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed    //
1554744671639dae1d5589181856d54cf0dfdb59272dreed    if (SkRegion::kIntersect_Op == op && !doAA && fMCRec->fMatrix.isScaleTranslate()) {
1555c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        SkRect devR;
1556c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        fMCRec->fMatrix.mapRectScaleTranslate(&devR, rect);
15572d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed        // NOTE: this check is CTM specific, since we might round differently with a different
15582d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed        //       CTM. Thus this is only 100% reliable if there is not global CTM scale to be
15592d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed        //       applied later (i.e. if this is going into a picture).
15602d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed        if (devR.round().contains(fMCRec->fRasterClip.getBounds())) {
15612d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed#if 0
15622d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed            SkDebugf("ignored clipRect [%g %g %g %g]\n",
15632d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed                     rect.left(), rect.top(), rect.right(), rect.bottom());
15642d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed#endif
15652d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed            return;
15662d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed        }
15672d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed    }
15682d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed#endif
15692d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed
15702ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15718f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
15728f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
15738f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15748f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
15758f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1576da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1577da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op) {
15781f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
15792d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed            return;
1580da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1581da17f758442f16747af39f8fbaed9c097048519creed@google.com
15823b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(rect)) {
1583da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1584c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1585da17f758442f16747af39f8fbaed9c097048519creed@google.com
1586687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
15872d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed            (void)fMCRec->fRasterClip.setEmpty();
1588fbfa25802709139c2f14e304319c9541da65ca27msarett            fDeviceClipBounds.setEmpty();
15892d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed            return;
1590da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1591da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1592da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1593da17f758442f16747af39f8fbaed9c097048519creed@google.com
1594744671639dae1d5589181856d54cf0dfdb59272dreed    const bool isScaleTrans = fMCRec->fMatrix.isScaleTranslate();
1595c64eff55049b1192052b791549a32a03be1c43e3reed    SkRect devR;
1596744671639dae1d5589181856d54cf0dfdb59272dreed    if (isScaleTrans) {
1597c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        fMCRec->fMatrix.mapRectScaleTranslate(&devR, rect);
1598c64eff55049b1192052b791549a32a03be1c43e3reed    }
1599c64eff55049b1192052b791549a32a03be1c43e3reed
16002d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed#ifndef SK_SUPPORT_PRECHECK_CLIPRECT
1601c64eff55049b1192052b791549a32a03be1c43e3reed    if (SkRegion::kIntersect_Op == op &&
1602c64eff55049b1192052b791549a32a03be1c43e3reed        kHard_ClipEdgeStyle == edgeStyle
1603744671639dae1d5589181856d54cf0dfdb59272dreed        && isScaleTrans)
1604c64eff55049b1192052b791549a32a03be1c43e3reed    {
1605c64eff55049b1192052b791549a32a03be1c43e3reed        if (devR.round().contains(fMCRec->fRasterClip.getBounds())) {
1606c64eff55049b1192052b791549a32a03be1c43e3reed#if 0
1607c64eff55049b1192052b791549a32a03be1c43e3reed            SkDebugf("------- ignored clipRect [%g %g %g %g]\n",
1608c64eff55049b1192052b791549a32a03be1c43e3reed                     rect.left(), rect.top(), rect.right(), rect.bottom());
1609c64eff55049b1192052b791549a32a03be1c43e3reed#endif
1610c64eff55049b1192052b791549a32a03be1c43e3reed            return;
1611c64eff55049b1192052b791549a32a03be1c43e3reed        }
1612c64eff55049b1192052b791549a32a03be1c43e3reed    }
16132d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed#endif
1614c64eff55049b1192052b791549a32a03be1c43e3reed
1615c64eff55049b1192052b791549a32a03be1c43e3reed    AutoValidateClip avc(this);
1616c64eff55049b1192052b791549a32a03be1c43e3reed
1617c64eff55049b1192052b791549a32a03be1c43e3reed    fDeviceCMDirty = true;
16188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1619744671639dae1d5589181856d54cf0dfdb59272dreed    if (isScaleTrans) {
1620c64eff55049b1192052b791549a32a03be1c43e3reed        const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1621c64eff55049b1192052b791549a32a03be1c43e3reed        fClipStack->clipDevRect(devR, op, isAA);
1622afc7cce5d68663934128d76963cd501f771d71desenorblanco        fMCRec->fRasterClip.op(devR, this->getTopLayerBounds(), op, isAA);
16238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
1624123671901abfa595d09ca789b487c4bc7c1f7cbcrobertphillips@google.com        // since we're rotated or some such thing, we convert the rect to a path
162598de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // and clip against that, since it can handle any matrix. However, to
162698de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // avoid recursion in the case where we are subclassed (e.g. Pictures)
162798de2bdbd12a01aaf347ca2549801b5940613f3freed@android.com        // we explicitly call "our" version of clipPath.
16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPath  path;
16298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        path.addRect(rect);
1631bdc335f9b9fb8d2eb1b4a00f88b34288b06112fabsalomon        path.setIsVolatile(true);
16328f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->SkCanvas::onClipPath(path, op, edgeStyle);
16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1634fbfa25802709139c2f14e304319c9541da65ca27msarett
1635fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
16368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1638759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
16392ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
16414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
16428f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
16438f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
16448f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
16454ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
16468f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
164714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
16488f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
164914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkRRect transformedRRect;
16501f836ee096bb988adef4b9757b2629c7afeda36dreed    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
165114e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        AutoValidateClip avc(this);
165214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
165314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org        fDeviceCMDirty = true;
16548f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        if (!fAllowSoftClip) {
16558f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com            edgeStyle = kHard_ClipEdgeStyle;
16568f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        }
165714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1658687fa1c745febb57f42b0d5f03d7c1f4be2530careed        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
165914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1660afc7cce5d68663934128d76963cd501f771d71desenorblanco        fMCRec->fRasterClip.op(transformedRRect, this->getTopLayerBounds(), op,
1661125f19a2964c31a660256132acbce60e8a3e6752robertphillips                               kSoft_ClipEdgeStyle == edgeStyle);
1662fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
16638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        return;
166414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    }
166514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
166614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    SkPath path;
166714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    path.addRRect(rrect);
1668bdc335f9b9fb8d2eb1b4a00f88b34288b06112fabsalomon    path.setIsVolatile(true);
166914e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org    // call the non-virtual version
16708f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->SkCanvas::onClipPath(path, op, edgeStyle);
16714ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
16724ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1673759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
16742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
16758f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
167639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
167739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
167839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRect r;
167939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRect(&r)) {
168039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRect(r, op, edgeStyle);
168139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
168239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
168339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRRect rrect;
168439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isOval(&r)) {
168539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            rrect.setOval(r);
168639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
168739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
168839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
168939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRRect(&rrect)) {
169039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
169139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
169239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
16938f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
169439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
169539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    this->onClipPath(path, op, edgeStyle);
16968f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
16978f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
16988f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1699da17f758442f16747af39f8fbaed9c097048519creed@google.com#ifdef SK_ENABLE_CLIP_QUICKREJECT
1700da17f758442f16747af39f8fbaed9c097048519creed@google.com    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
17011f836ee096bb988adef4b9757b2629c7afeda36dreed        if (fMCRec->fRasterClip.isEmpty()) {
17022d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed            return;
1703da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1704fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
17053b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        if (this->quickReject(path.getBounds())) {
1706da17f758442f16747af39f8fbaed9c097048519creed@google.com            fDeviceCMDirty = true;
1707c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com            fCachedLocalClipBoundsDirty = true;
1708fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1709687fa1c745febb57f42b0d5f03d7c1f4be2530careed            fClipStack->clipEmpty();
17102d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed            (void)fMCRec->fRasterClip.setEmpty();
1711fbfa25802709139c2f14e304319c9541da65ca27msarett            fDeviceClipBounds.setEmpty();
17122d1afab8ef2db8b4f0bdab387b0e42ccee1db64freed            return;
1713da17f758442f16747af39f8fbaed9c097048519creed@google.com        }
1714da17f758442f16747af39f8fbaed9c097048519creed@google.com    }
1715da17f758442f16747af39f8fbaed9c097048519creed@google.com#endif
1716da17f758442f16747af39f8fbaed9c097048519creed@google.com
17175c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
17185c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
17208f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!fAllowSoftClip) {
17218f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        edgeStyle = kHard_ClipEdgeStyle;
17228f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath devPath;
1725bdc335f9b9fb8d2eb1b4a00f88b34288b06112fabsalomon    if (fMCRec->fMatrix.isIdentity()) {
1726bdc335f9b9fb8d2eb1b4a00f88b34288b06112fabsalomon        devPath = path;
1727bdc335f9b9fb8d2eb1b4a00f88b34288b06112fabsalomon    } else {
1728bdc335f9b9fb8d2eb1b4a00f88b34288b06112fabsalomon        path.transform(fMCRec->fMatrix, &devPath);
1729bdc335f9b9fb8d2eb1b4a00f88b34288b06112fabsalomon        devPath.setIsVolatile(true);
1730bdc335f9b9fb8d2eb1b4a00f88b34288b06112fabsalomon    }
17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1732fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // Check if the transfomation, or the original path itself
1733fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // made us empty. Note this can also happen if we contained NaN
1734fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // values. computing the bounds detects this, and will set our
1735fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1736fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    if (devPath.getBounds().isEmpty()) {
1737fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // resetting the path will remove any NaN or other wanky values
1738fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        // that might upset our scan converter.
1739fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com        devPath.reset();
1740fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com    }
1741fe701129857924f76a0d752d4c964b3c5e4b49fereed@google.com
17425c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // if we called path.swap() we could avoid a deep copy of this path
1743687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
17445c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
174545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    if (fAllowSimplifyClip) {
17461a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        bool clipIsAA = getClipStack()->asPath(&devPath);
17471a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita        if (clipIsAA) {
17481a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita            edgeStyle = kSoft_ClipEdgeStyle;
174945a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        }
17501a481fe4bf632ed4f76cb337691236fabfd4ab03fmalita
175145a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com        op = SkRegion::kReplace_Op;
175245a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    }
175345a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com
1754afc7cce5d68663934128d76963cd501f771d71desenorblanco    fMCRec->fRasterClip.op(devPath, this->getTopLayerBounds(), op, edgeStyle);
1755fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
17568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1758759cf4846804be137229393e04925752423de2d0commit-bot@chromium.orgvoid SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
17592ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
17608f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
17618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
17628f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
17638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.comvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
17645c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
17655c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDeviceCMDirty = true;
17678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17685c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // todo: signal fClipStack that we have a region, and therefore (I guess)
17695c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    // we have to ignore it, and use the region directly?
1770687fa1c745febb57f42b0d5f03d7c1f4be2530careed    fClipStack->clipDevRect(rgn.getBounds(), op);
17715c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
17721f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fRasterClip.op(rgn, op);
1773fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
17748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1776819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1777819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1778819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
17791f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1780ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
17815c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1782ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1783ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1784ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com
1785819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    SkIRect ir;
1786819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    ir.set(0, 0, device->width(), device->height());
1787d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1788819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1789687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
17908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element;
179196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    while ((element = iter.next()) != nullptr) {
17928182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        switch (element->getType()) {
17938182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kRect_Type:
17948182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                element->getRect().round(&ir);
17958182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.op(ir, element->getOp());
17968182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
17978182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            case SkClipStack::Element::kEmpty_Type:
17988182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                tmpClip.setEmpty();
17998182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                break;
18009cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            default: {
18019cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                SkPath path;
18029cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                element->asPath(&path);
1803afc7cce5d68663934128d76963cd501f771d71desenorblanco                tmpClip.op(path, this->getTopLayerBounds(), element->getOp(), element->isAA());
18049cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org                break;
18059cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org            }
1806819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com        }
1807819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    }
1808819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1809819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1810819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
181190c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.comvoid SkCanvas::replayClips(ClipVisitor* visitor) const {
1812687fa1c745febb57f42b0d5f03d7c1f4be2530careed    SkClipStack::B2TIter                iter(*fClipStack);
18138182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element*         element;
18148182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com
181596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    while ((element = iter.next()) != nullptr) {
1816c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        element->replay(visitor);
181790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com    }
181890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
181990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
18205c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
18215c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1822754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
18231f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isEmpty();
1824754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1825754de5f65b466f721d952a379194cc94de376f42reed@google.com
18265c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
18271f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.isRect();
18285c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
18295c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
1830fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1831fbfa25802709139c2f14e304319c9541da65ca27msarett#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1832fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1833fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1834fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1835fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xF != _mm_movemask_ps(mask);
1836fbfa25802709139c2f14e304319c9541da65ca27msarett#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1837fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1838fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1839fbfa25802709139c2f14e304319c9541da65ca27msarett    uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1840fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1841fbfa25802709139c2f14e304319c9541da65ca27msarett#else
1842fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devRectAsRect;
1843fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devClipAsRect;
1844fbfa25802709139c2f14e304319c9541da65ca27msarett    devRect.store(&devRectAsRect.fLeft);
1845fbfa25802709139c2f14e304319c9541da65ca27msarett    devClip.store(&devClipAsRect.fLeft);
1846fbfa25802709139c2f14e304319c9541da65ca27msarett    return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1847fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1848fbfa25802709139c2f14e304319c9541da65ca27msarett}
1849fbfa25802709139c2f14e304319c9541da65ca27msarett
1850fbfa25802709139c2f14e304319c9541da65ca27msarett// It's important for this function to not be inlined.  Otherwise the compiler will share code
1851fbfa25802709139c2f14e304319c9541da65ca27msarett// between the fast path and the slow path, resulting in two slow paths.
1852fbfa25802709139c2f14e304319c9541da65ca27msarettstatic SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1853fbfa25802709139c2f14e304319c9541da65ca27msarett                                                   const SkMatrix& matrix) {
1854fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect deviceRect;
1855fbfa25802709139c2f14e304319c9541da65ca27msarett    matrix.mapRect(&deviceRect, src);
1856fbfa25802709139c2f14e304319c9541da65ca27msarett    return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1857fbfa25802709139c2f14e304319c9541da65ca27msarett}
1858d22a817ff57986407facd16af36320fc86ce02damsarett
1859fbfa25802709139c2f14e304319c9541da65ca27msarettbool SkCanvas::quickReject(const SkRect& src) const {
1860fbfa25802709139c2f14e304319c9541da65ca27msarett#ifdef SK_DEBUG
1861fbfa25802709139c2f14e304319c9541da65ca27msarett    // Verify that fDeviceClipBounds are set properly.
1862fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
18631f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
18640c685ee188a5e500df25a34fa6edfceb4cbb795cmsarett        SkASSERT(fDeviceClipBounds.isEmpty());
1865fbfa25802709139c2f14e304319c9541da65ca27msarett    } else {
1866fbfa25802709139c2f14e304319c9541da65ca27msarett        SkASSERT(tmp == fDeviceClipBounds);
18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18699637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    // Verify that fIsScaleTranslate is set properly.
18709637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1871fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1872d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
18739637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    if (!fIsScaleTranslate) {
1874fbfa25802709139c2f14e304319c9541da65ca27msarett        return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1876fbfa25802709139c2f14e304319c9541da65ca27msarett
1877fbfa25802709139c2f14e304319c9541da65ca27msarett    // We inline the implementation of mapScaleTranslate() for the fast path.
1878fbfa25802709139c2f14e304319c9541da65ca27msarett    float sx = fMCRec->fMatrix.getScaleX();
1879fbfa25802709139c2f14e304319c9541da65ca27msarett    float sy = fMCRec->fMatrix.getScaleY();
1880fbfa25802709139c2f14e304319c9541da65ca27msarett    float tx = fMCRec->fMatrix.getTranslateX();
1881fbfa25802709139c2f14e304319c9541da65ca27msarett    float ty = fMCRec->fMatrix.getTranslateY();
1882fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f scale(sx, sy, sx, sy);
1883fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f trans(tx, ty, tx, ty);
1884fbfa25802709139c2f14e304319c9541da65ca27msarett
1885fbfa25802709139c2f14e304319c9541da65ca27msarett    // Apply matrix.
1886fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1887fbfa25802709139c2f14e304319c9541da65ca27msarett
1888fbfa25802709139c2f14e304319c9541da65ca27msarett    // Make sure left < right, top < bottom.
1889fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1890fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f min = Sk4f::Min(ltrb, rblt);
1891fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f max = Sk4f::Max(ltrb, rblt);
1892fbfa25802709139c2f14e304319c9541da65ca27msarett    // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1893fbfa25802709139c2f14e304319c9541da65ca27msarett    // ARM this sequence generates the fastest (a single instruction).
1894fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1895fbfa25802709139c2f14e304319c9541da65ca27msarett
1896fbfa25802709139c2f14e304319c9541da65ca27msarett    // Check if the device rect is NaN or outside the clip.
1897fbfa25802709139c2f14e304319c9541da65ca27msarett    return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
18988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19003b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
19013b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
19028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19043b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::getClipBounds(SkRect* bounds) const {
1905bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ibounds;
19068f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    if (!this->getClipDeviceBounds(&ibounds)) {
19078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
19088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1910d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1911d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
19121f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
191372dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        if (bounds) {
191472dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com            bounds->setEmpty();
191572dcd3a3c16a68f98bc345a4263678d43bc3daebreed@android.com        }
1916d9c0f0b57affec7a472879c5919acac6637d926areed@android.com        return false;
1917d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1918d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
191949f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1920bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        SkRect r;
19213b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        // adjust it outwards in case we are antialiasing
19223b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com        const int inset = 1;
1923fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
19248f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
19258f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com               ibounds.fRight + inset, ibounds.fBottom + inset);
19268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inverse.mapRect(bounds, r);
19278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
19298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1931bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.combool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
19321f836ee096bb988adef4b9757b2629c7afeda36dreed    const SkRasterClip& clip = fMCRec->fRasterClip;
1933bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    if (clip.isEmpty()) {
1934bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        if (bounds) {
1935bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            bounds->setEmpty();
1936bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        }
1937bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        return false;
1938bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1939bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
194049f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
1941bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com        *bounds = clip.getBounds();
1942bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    }
1943bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    return true;
1944bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1945bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
19471f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
19488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19505c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgconst SkRegion& SkCanvas::internal_private_getTotalClip() const {
19511f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fRasterClip.forceGetBW();
19525c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
19535c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
1954175dd9b5e3d7d749738dac743d2ac360b5340187robertphillipsGrDrawContext* SkCanvas::internal_private_accessTopLayerDrawContext() {
19559c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1956175dd9b5e3d7d749738dac743d2ac360b5340187robertphillips    return dev ? dev->accessDrawContext() : nullptr;
19579c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
19589c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1959644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1960644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
196186ae3d161412961c27a406465b0ec5749cc2e753reed    return device ? device->context() : nullptr;
1962644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1963e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1964ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1965ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
19669881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1967ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1968ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1969ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1970ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1971ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1972ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1973ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1974ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1975ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1976ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // be able to assert...
1977ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // SkASSERT(outer.contains(inner));
1978ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1979ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1980ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1981ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1982ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1983ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1984ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
198541af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
198641af966ab338e95eee81ab618ab28195075338f7reed
198741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
198841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
198941af966ab338e95eee81ab618ab28195075338f7reed}
199041af966ab338e95eee81ab618ab28195075338f7reed
199141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
199241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
199341af966ab338e95eee81ab618ab28195075338f7reed}
199441af966ab338e95eee81ab618ab28195075338f7reed
1995dca352e2d42cfe698573947b3d11abc1eaade160msarettvoid SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1996dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isEmpty()) {
1997dca352e2d42cfe698573947b3d11abc1eaade160msarett        return;
1998dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1999dca352e2d42cfe698573947b3d11abc1eaade160msarett
2000dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isRect()) {
2001dca352e2d42cfe698573947b3d11abc1eaade160msarett        return this->drawIRect(region.getBounds(), paint);
2002dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
2003dca352e2d42cfe698573947b3d11abc1eaade160msarett
2004dca352e2d42cfe698573947b3d11abc1eaade160msarett    this->onDrawRegion(region, paint);
2005dca352e2d42cfe698573947b3d11abc1eaade160msarett}
2006dca352e2d42cfe698573947b3d11abc1eaade160msarett
200741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
200841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
200941af966ab338e95eee81ab618ab28195075338f7reed}
201041af966ab338e95eee81ab618ab28195075338f7reed
201141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
201241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
201341af966ab338e95eee81ab618ab28195075338f7reed}
201441af966ab338e95eee81ab618ab28195075338f7reed
201541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
201641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
201741af966ab338e95eee81ab618ab28195075338f7reed}
201841af966ab338e95eee81ab618ab28195075338f7reed
201941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
202041af966ab338e95eee81ab618ab28195075338f7reed                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
202141af966ab338e95eee81ab618ab28195075338f7reed                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
202241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
202341af966ab338e95eee81ab618ab28195075338f7reed                         indices, indexCount, paint);
202441af966ab338e95eee81ab618ab28195075338f7reed}
202541af966ab338e95eee81ab618ab28195075338f7reed
202641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
202741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
202841af966ab338e95eee81ab618ab28195075338f7reed}
202941af966ab338e95eee81ab618ab28195075338f7reed
2030a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
2031e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
2032a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
203341af966ab338e95eee81ab618ab28195075338f7reed}
203441af966ab338e95eee81ab618ab28195075338f7reed
2035e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
2036e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             const SkPaint* paint, SrcRectConstraint constraint) {
2037e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
2038e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (dst.isEmpty() || src.isEmpty()) {
2039e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
2040e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
2041e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawImageRect(image, &src, dst, paint, constraint);
2042e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
204341af966ab338e95eee81ab618ab28195075338f7reed
204484984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
204584984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                             const SkPaint* paint, SrcRectConstraint constraint) {
2046e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
2047e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
204884984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
204984984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
2050e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
2051e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             SrcRectConstraint constraint) {
2052e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
2053e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
2054e47829b6b1eeb6b0c97ccb3df3016d197046824creed                        constraint);
2055e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2056e47829b6b1eeb6b0c97ccb3df3016d197046824creed
20574c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
20584c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
2059e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
20604c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
20614c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
20624c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
2063552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
2064552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawImageNine(image, center, dst, paint);
2065552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
2066e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, dst, paint);
20674c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
20684c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
20694c21dc5ddf3b482293ed34eead876d8d61a662c3reed
2070168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2071168820625c35a8c19f66c661efcbce7a5e334837msarett                                const SkPaint* paint) {
2072168820625c35a8c19f66c661efcbce7a5e334837msarett    RETURN_ON_NULL(image);
2073168820625c35a8c19f66c661efcbce7a5e334837msarett    if (dst.isEmpty()) {
2074168820625c35a8c19f66c661efcbce7a5e334837msarett        return;
2075168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2076168820625c35a8c19f66c661efcbce7a5e334837msarett    if (SkLatticeIter::Valid(image->width(), image->height(), lattice)) {
2077168820625c35a8c19f66c661efcbce7a5e334837msarett        this->onDrawImageLattice(image, lattice, dst, paint);
2078168820625c35a8c19f66c661efcbce7a5e334837msarett    } else {
2079168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawImageRect(image, dst, paint);
2080168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2081168820625c35a8c19f66c661efcbce7a5e334837msarett}
2082168820625c35a8c19f66c661efcbce7a5e334837msarett
208341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
20844c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
20852df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
20862df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
208741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
208841af966ab338e95eee81ab618ab28195075338f7reed}
208941af966ab338e95eee81ab618ab28195075338f7reed
2090e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
2091a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
2092e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
2093a5517e2b190a8083b38964972b031c13e99f1012reed        return;
2094a5517e2b190a8083b38964972b031c13e99f1012reed    }
2095e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
209641af966ab338e95eee81ab618ab28195075338f7reed}
209741af966ab338e95eee81ab618ab28195075338f7reed
209884984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
209984984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                              const SkPaint* paint, SrcRectConstraint constraint) {
2100e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
2101e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2102e47829b6b1eeb6b0c97ccb3df3016d197046824creed
2103e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
2104e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              SrcRectConstraint constraint) {
2105e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
2106e47829b6b1eeb6b0c97ccb3df3016d197046824creed                         constraint);
210784984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
210884984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
210941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
211041af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
21114c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
21122df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
21132df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
2114552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
2115552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawBitmapNine(bitmap, center, dst, paint);
2116552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
2117a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
21184c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
211941af966ab338e95eee81ab618ab28195075338f7reed}
212041af966ab338e95eee81ab618ab28195075338f7reed
2121c573a40ed5024b463e47088d307e3164a486dba5msarettvoid SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
2122c573a40ed5024b463e47088d307e3164a486dba5msarett                                 const SkPaint* paint) {
2123168820625c35a8c19f66c661efcbce7a5e334837msarett    if (bitmap.drawsNothing() || dst.isEmpty()) {
2124c573a40ed5024b463e47088d307e3164a486dba5msarett        return;
2125c573a40ed5024b463e47088d307e3164a486dba5msarett    }
2126168820625c35a8c19f66c661efcbce7a5e334837msarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), lattice)) {
2127168820625c35a8c19f66c661efcbce7a5e334837msarett        this->onDrawBitmapLattice(bitmap, lattice, dst, paint);
2128552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
2129168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawBitmapRect(bitmap, dst, paint);
2130c573a40ed5024b463e47088d307e3164a486dba5msarett    }
2131c573a40ed5024b463e47088d307e3164a486dba5msarett}
2132c573a40ed5024b463e47088d307e3164a486dba5msarett
213371c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
213471c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkColor colors[], int count, SkXfermode::Mode mode,
213571c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
2136e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(atlas);
213771c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
213871c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
213971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
214071c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(atlas);
214171c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(xform);
214271c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
214371c3c760a83123ee0b3127b8c65c6394ce541c50reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
214471c3c760a83123ee0b3127b8c65c6394ce541c50reed}
214571c3c760a83123ee0b3127b8c65c6394ce541c50reed
2146f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2147f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    if (key) {
2148f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        this->onDrawAnnotation(rect, key, value);
2149f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
2150f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
2151f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
2152e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2153e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                    const SkPaint* paint, SrcRectConstraint constraint) {
2154e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
2155e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, *src, dst, paint, constraint);
2156e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
2157e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
2158e47829b6b1eeb6b0c97ccb3df3016d197046824creed                            dst, paint, constraint);
2159e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
2160e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2161e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2162e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                     const SkPaint* paint, SrcRectConstraint constraint) {
2163e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
2164e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
2165e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
2166e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
2167e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             dst, paint, constraint);
2168e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
2169e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
2170e47829b6b1eeb6b0c97ccb3df3016d197046824creed
2171cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudsonvoid SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) {
2172cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    SkIRect layer_bounds = this->getTopLayerBounds();
2173cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    if (matrix) {
2174cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        *matrix = this->getTotalMatrix();
2175cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top());
2176cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    }
2177cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    if (clip_bounds) {
2178cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        this->getClipDeviceBounds(clip_bounds);
2179cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top());
2180cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    }
2181cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson}
2182cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson
21838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
21848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
21858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
21868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
218728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
218849f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
218928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
219028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
219128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
219228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
219341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
21949881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
2195fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
2196fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
2197fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
2198fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
219996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
22008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPaint(iter, looper.paint());
22038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
22068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
220841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
220941af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
22109881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
22118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
22128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
22138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
221578cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect r, storage;
221696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2217a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
2218a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
2219a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
2220a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
2221a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
2222a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
2223a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
222487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
222587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
222687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
222787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
2228fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
2229a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
223096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(pts != nullptr);
22318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
223278cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
22334b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
22354e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
22368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22374b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22384e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22414a16717bc7aa471fad10ec3157774771a76e5106reedstatic bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
22424a16717bc7aa471fad10ec3157774771a76e5106reed    return ((intptr_t)paint.getImageFilter()    |
22434a16717bc7aa471fad10ec3157774771a76e5106reed#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
22444a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)canvas->getDrawFilter()   |
22454a16717bc7aa471fad10ec3157774771a76e5106reed#endif
22464a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)paint.getLooper()         ) != 0;
22474a16717bc7aa471fad10ec3157774771a76e5106reed}
22484a16717bc7aa471fad10ec3157774771a76e5106reed
224941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
22509881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
225178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
225296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
22548432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
22558432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
22568432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
22578432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
22588432808ad8898ac7137bc7ce1d9df6005e866401reed
225987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
226087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
226187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
226287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
22638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22644b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
22654a16717bc7aa471fad10ec3157774771a76e5106reed    if (needs_autodrawlooper(this, paint)) {
22664a16717bc7aa471fad10ec3157774771a76e5106reed        LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false)
22678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22684a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
22694a16717bc7aa471fad10ec3157774771a76e5106reed            iter.fDevice->drawRect(iter, r, looper.paint());
22704a16717bc7aa471fad10ec3157774771a76e5106reed        }
22718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22724a16717bc7aa471fad10ec3157774771a76e5106reed        LOOPER_END
22734a16717bc7aa471fad10ec3157774771a76e5106reed    } else {
22744a16717bc7aa471fad10ec3157774771a76e5106reed        this->predrawNotify(bounds, &paint, false);
22754a16717bc7aa471fad10ec3157774771a76e5106reed        SkDrawIter iter(this);
22764a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
22774a16717bc7aa471fad10ec3157774771a76e5106reed            iter.fDevice->drawRect(iter, r, paint);
22784a16717bc7aa471fad10ec3157774771a76e5106reed        }
22794a16717bc7aa471fad10ec3157774771a76e5106reed    }
22808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228244df651ebefc284acc2f66425dff3ea0b0e14b36msarettvoid SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
228344df651ebefc284acc2f66425dff3ea0b0e14b36msarett    SkRect storage;
228444df651ebefc284acc2f66425dff3ea0b0e14b36msarett    SkRect regionRect = SkRect::Make(region.getBounds());
228544df651ebefc284acc2f66425dff3ea0b0e14b36msarett    const SkRect* bounds = nullptr;
228644df651ebefc284acc2f66425dff3ea0b0e14b36msarett    if (paint.canComputeFastBounds()) {
228744df651ebefc284acc2f66425dff3ea0b0e14b36msarett        if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
228844df651ebefc284acc2f66425dff3ea0b0e14b36msarett            return;
228944df651ebefc284acc2f66425dff3ea0b0e14b36msarett        }
229044df651ebefc284acc2f66425dff3ea0b0e14b36msarett        bounds = &regionRect;
229144df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
229244df651ebefc284acc2f66425dff3ea0b0e14b36msarett
229344df651ebefc284acc2f66425dff3ea0b0e14b36msarett    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
229444df651ebefc284acc2f66425dff3ea0b0e14b36msarett
229544df651ebefc284acc2f66425dff3ea0b0e14b36msarett    while (iter.next()) {
229644df651ebefc284acc2f66425dff3ea0b0e14b36msarett        iter.fDevice->drawRegion(iter, region, looper.paint());
229744df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
229844df651ebefc284acc2f66425dff3ea0b0e14b36msarett
229944df651ebefc284acc2f66425dff3ea0b0e14b36msarett    LOOPER_END
230044df651ebefc284acc2f66425dff3ea0b0e14b36msarett}
230144df651ebefc284acc2f66425dff3ea0b0e14b36msarett
230241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
23039881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
230478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
230596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
23064ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
230787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
230887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
230987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
231087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &oval;
23114ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2312306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
231378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
231446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
231546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
231646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        iter.fDevice->drawOval(iter, oval, looper.paint());
231746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
231846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
231946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
23204ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
23214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2322ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomonvoid SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2323ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         SkScalar sweepAngle, bool useCenter,
2324ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         const SkPaint& paint) {
2325ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2326ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    const SkRect* bounds = nullptr;
2327ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    if (paint.canComputeFastBounds()) {
2328ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        SkRect storage;
2329ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        // Note we're using the entire oval as the bounds.
2330ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2331ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon            return;
2332ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        }
2333ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        bounds = &oval;
2334ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2335ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2336ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
2337ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2338ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    while (iter.next()) {
2339ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        iter.fDevice->drawArc(iter, oval, startAngle, sweepAngle, useCenter, looper.paint());
2340ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2341ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2342ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    LOOPER_END
2343ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon}
2344ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
234541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
23469881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
234778cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
234896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
23494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
235087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
235187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
235287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
235387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &rrect.getBounds();
23544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
23554ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
23564ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
23574ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
23584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2359f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2360f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
23614ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2362f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2363f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
23644ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2365f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
236678cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2367f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2368f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2369f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2370f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2371f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2372f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
23734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
23744ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2375ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2376ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                            const SkPaint& paint) {
2377ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    SkRect storage;
237896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2379ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
238087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
238187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
238287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
238387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &outer.getBounds();
2384ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
238525c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2386ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
238725c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2388ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2389ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2390ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
239125c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2392ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2393ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
23944ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
239541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
23969881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
23979364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
23989364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
23999364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
24009364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
240178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    SkRect storage;
240296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
2403fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
240478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org        const SkRect& pathBounds = path.getBounds();
240587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
240687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
240787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
240887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &pathBounds;
24098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24100b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
24110b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    const SkRect& r = path.getBounds();
24120b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org    if (r.width() <= 0 && r.height() <= 0) {
24136803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2414fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
24156651a3238dd6affa4276ada42ab613abf1d42d1dcaryclark            return;
2416fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2417fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
24188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
241978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
24208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24224e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        iter.fDevice->drawPath(iter, path, looper.paint());
24238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2428262a71b7f95ce98ff3dd8dba845afbd724470903reedbool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2429262a71b7f95ce98ff3dd8dba845afbd724470903reed    if (!paint.getImageFilter()) {
2430262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2431262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2432262a71b7f95ce98ff3dd8dba845afbd724470903reed
2433262a71b7f95ce98ff3dd8dba845afbd724470903reed    const SkMatrix& ctm = this->getTotalMatrix();
2434c7e211acd0c9201688de7ff0c9a2271c67440adffmalita    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2435262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2436262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2437262a71b7f95ce98ff3dd8dba845afbd724470903reed
2438262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2439262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Once we can filter and the filter will return a result larger than itself, we should be
2440262a71b7f95ce98ff3dd8dba845afbd724470903reed    // able to remove this constraint.
2441262a71b7f95ce98ff3dd8dba845afbd724470903reed    // skbug.com/4526
2442262a71b7f95ce98ff3dd8dba845afbd724470903reed    //
2443262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkPoint pt;
2444262a71b7f95ce98ff3dd8dba845afbd724470903reed    ctm.mapXY(x, y, &pt);
2445262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2446262a71b7f95ce98ff3dd8dba845afbd724470903reed    return ir.contains(fMCRec->fRasterClip.getBounds());
2447262a71b7f95ce98ff3dd8dba845afbd724470903reed}
2448262a71b7f95ce98ff3dd8dba845afbd724470903reed
2449a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
24509881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2451a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2452a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
245396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
245487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = bounds;
245587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
245687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(tmp, &tmp);
245787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
245887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(tmp)) {
245987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
246087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2461a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
24629d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2463a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
246496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2465a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2466a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2467262a71b7f95ce98ff3dd8dba845afbd724470903reed
2468a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2469129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2470129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                                    *paint);
2471129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2472a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(image);
2473a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2474129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2475129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2476129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2477129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2478262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2479262a71b7f95ce98ff3dd8dba845afbd724470903reed
2480a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2481262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2482a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2483a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            SkPoint pt;
2484a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            iter.fMatrix->mapXY(x, y, &pt);
2485a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            iter.fDevice->drawSpecial(iter, special.get(),
2486a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
2487a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fY), pnt);
2488262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2489262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fDevice->drawImage(iter, image, x, y, pnt);
2490262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
2491a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
24929d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2493a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2494b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2495b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
249641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2497562fe4767cc73e08a4e039362bc0336aea66ecfbreed                               const SkPaint* paint, SrcRectConstraint constraint) {
24989881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
249996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2500c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage = dst;
250187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
250287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(dst, &storage);
250387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
250487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(storage)) {
250587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
250687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2507a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2508a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
250996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2510a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2511a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
25129d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2513c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2514c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
25159d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2516a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2517a5517e2b190a8083b38964972b031c13e99f1012reed        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
2518a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
25199d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2520a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2521b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2522b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
252341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
25249881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
25258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
25268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
252733366974d43eae80e22284a2e445225c343859dareed    if (bitmap.drawsNothing()) {
252833366974d43eae80e22284a2e445225c343859dareed        return;
252933366974d43eae80e22284a2e445225c343859dareed    }
253033366974d43eae80e22284a2e445225c343859dareed
253133366974d43eae80e22284a2e445225c343859dareed    SkLazyPaint lazy;
253233366974d43eae80e22284a2e445225c343859dareed    if (nullptr == paint) {
253333366974d43eae80e22284a2e445225c343859dareed        paint = lazy.init();
253433366974d43eae80e22284a2e445225c343859dareed    }
253533366974d43eae80e22284a2e445225c343859dareed
253633366974d43eae80e22284a2e445225c343859dareed    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
253733366974d43eae80e22284a2e445225c343859dareed
253833366974d43eae80e22284a2e445225c343859dareed    SkRect storage;
253933366974d43eae80e22284a2e445225c343859dareed    const SkRect* bounds = nullptr;
254033366974d43eae80e22284a2e445225c343859dareed    if (paint->canComputeFastBounds()) {
254133366974d43eae80e22284a2e445225c343859dareed        bitmap.getBounds(&storage);
254233366974d43eae80e22284a2e445225c343859dareed        matrix.mapRect(&storage);
254387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = storage;
254487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) {
254587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
254687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
254787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
25488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25494b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2550a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2551129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), bitmap.height(),
2552129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                                              *paint);
2553129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2554a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(bitmap);
2555a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2556129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2557129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2558129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2559129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2560262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds)
256133366974d43eae80e22284a2e445225c343859dareed
256233366974d43eae80e22284a2e445225c343859dareed    while (iter.next()) {
2563262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2564a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2565262a71b7f95ce98ff3dd8dba845afbd724470903reed            SkPoint pt;
2566262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fMatrix->mapXY(x, y, &pt);
2567a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            iter.fDevice->drawSpecial(iter, special.get(),
2568a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
2569a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fY), pnt);
2570262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2571262a71b7f95ce98ff3dd8dba845afbd724470903reed            iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
2572262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
257333366974d43eae80e22284a2e445225c343859dareed    }
2574fbfa25802709139c2f14e304319c9541da65ca27msarett
257533366974d43eae80e22284a2e445225c343859dareed    LOOPER_END
25768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25789987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
25797112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2580eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2581a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
258250b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
25838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
25848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
258574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
258696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2587c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
258887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
258987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
259087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
25918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25923d60812865bb034851da777a91413ab584929887reed@google.com
259333535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
259496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
259533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
25968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25977064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2598c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2599c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
26007064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
260133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2602562fe4767cc73e08a4e039362bc0336aea66ecfbreed        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
2603f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
26047064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
260533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
26068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
260841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2609562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                const SkPaint* paint, SrcRectConstraint constraint) {
26109881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
26119987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2612562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
26139987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
26149987ec3791336bad6af5cbe513564786b2df55aareed@google.com
26154c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
26164c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
26174c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
26189d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
261996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2620c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
262187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
262287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
262387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
26243d60812865bb034851da777a91413ab584929887reed@google.com    }
26259d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26264c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
262796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
26284c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
26294c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
26309d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2631c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
26329d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26334c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
26344c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
26359987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
26369d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26374c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
26389987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
26399987ec3791336bad6af5cbe513564786b2df55aareed@google.com
264041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
264141af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
26429881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
26439987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
26449987ec3791336bad6af5cbe513564786b2df55aareed@google.com
264596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2646c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
264787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
264887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
264987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
26504c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
26519d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26524c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
265396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
26544c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
26554c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
26569d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2657c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
26589d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26594c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
26604c21dc5ddf3b482293ed34eead876d8d61a662c3reed        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
26614c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
26629d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
26634c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
26649987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
26659987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2666168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2667168820625c35a8c19f66c661efcbce7a5e334837msarett                                  const SkPaint* paint) {
2668168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2669168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2670168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2671168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2672168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2673168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2674168820625c35a8c19f66c661efcbce7a5e334837msarett
2675168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2676168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2677168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2678168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2679168820625c35a8c19f66c661efcbce7a5e334837msarett
2680168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2681168820625c35a8c19f66c661efcbce7a5e334837msarett
2682168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2683168820625c35a8c19f66c661efcbce7a5e334837msarett        iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint());
2684168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2685168820625c35a8c19f66c661efcbce7a5e334837msarett
2686168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2687168820625c35a8c19f66c661efcbce7a5e334837msarett}
2688168820625c35a8c19f66c661efcbce7a5e334837msarett
2689168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2690168820625c35a8c19f66c661efcbce7a5e334837msarett                                   const SkRect& dst, const SkPaint* paint) {
2691168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2692168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2693168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2694168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2695168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2696168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2697168820625c35a8c19f66c661efcbce7a5e334837msarett
2698168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2699168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2700168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2701168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2702168820625c35a8c19f66c661efcbce7a5e334837msarett
2703168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2704168820625c35a8c19f66c661efcbce7a5e334837msarett
2705168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2706168820625c35a8c19f66c661efcbce7a5e334837msarett        iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint());
2707168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2708168820625c35a8c19f66c661efcbce7a5e334837msarett
2709168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2710168820625c35a8c19f66c661efcbce7a5e334837msarett}
2711168820625c35a8c19f66c661efcbce7a5e334837msarett
2712f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2713f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
27141f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2715112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2716112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2717a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2718112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2719f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2720f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2721f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2722f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2723f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2724f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2725f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2726f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2727f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
27282c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
27292c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2730f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2731f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
273252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
273352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                        const SkRect& r, SkScalar textSize) {
273417b78946096265d80215a6c946286ecaa35ea7edepoger@google.com    if (paint.getStyle() == SkPaint::kFill_Style) {
273552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, paint);
273652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    } else {
273752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkPaint p(paint);
273817b78946096265d80215a6c946286ecaa35ea7edepoger@google.com        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
273952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        draw.fDevice->drawRect(draw, r, p);
274052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
274152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
274252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
274352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.comvoid SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
274452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   const char text[], size_t byteLength,
274552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                   SkScalar x, SkScalar y) {
274696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(byteLength == 0 || text != nullptr);
274752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
274852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    // nothing to draw
274996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (text == nullptr || byteLength == 0 ||
27501e7f5e708e5daeb0c18ae49001c9e3cd5e3b13cbreed        draw.fRC->isEmpty() ||
275196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) {
275252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
275352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
275452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
275552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkScalar    width = 0;
275652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    SkPoint     start;
275752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
275852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    start.set(0, 0);    // to avoid warning
275952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
276052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            SkPaint::kStrikeThruText_Flag)) {
276152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        width = paint.measureText(text, byteLength);
276252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
276352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar offsetX = 0;
276452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
276552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = SkScalarHalf(width);
276652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
276752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            offsetX = width;
276852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
276952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        start.set(x - offsetX, y);
277052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
277152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
277252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (0 == width) {
277352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        return;
277452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
277552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
277652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    uint32_t flags = paint.getFlags();
277752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
277852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    if (flags & (SkPaint::kUnderlineText_Flag |
277952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                 SkPaint::kStrikeThruText_Flag)) {
278052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar textSize = paint.getTextSize();
278152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
278252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        SkRect   r;
278352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
278452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fLeft = start.fX;
278552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        r.fRight = start.fX + width;
278652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
278752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kUnderlineText_Flag) {
278852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
278952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
279052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
279152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
2792fb56218292d6c7b509d382f39994c3783b2483a0caryclark            DrawRect(draw, paint, r, 1);
279352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
279452c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        if (flags & SkPaint::kStrikeThruText_Flag) {
279552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
279652c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                                             start.fY);
279752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fTop = offset;
279852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com            r.fBottom = offset + height;
2799fb56218292d6c7b509d382f39994c3783b2483a0caryclark            DrawRect(draw, paint, r, 1);
280052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        }
280152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com    }
280252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com}
280352c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com
2804e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2805e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
280696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
28078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
28094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2810f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
281152c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com        DrawTextDecorations(iter, dfp.paint(),
281252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com                            static_cast<const char*>(text), byteLength, x, y);
28138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28154e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
28168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2818e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2819e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
282005c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
282105c4a4322e7d4f3417b7df33825bab8603d52051fmalita
282296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
282387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
28248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
28254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
282605c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2827f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
28288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2829b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
28304e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
28318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2833e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2834e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
283505c4a4322e7d4f3417b7df33825bab8603d52051fmalita
283605c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
283705c4a4322e7d4f3417b7df33825bab8603d52051fmalita
283896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
283987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
28408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
28414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
284205c4a4322e7d4f3417b7df33825bab8603d52051fmalita        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2843f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
28448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2845b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
28464e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
28478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2849e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2850e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
285196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
285287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
28538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
28548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
28554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
28568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2857b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2858945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
28594325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
28604325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
286145561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
286245561a0b15fe045ba272c328684c3f7ae290785areed                                 const SkRect* cullRect, const SkPaint& paint) {
286345561a0b15fe045ba272c328684c3f7ae290785areed    if (cullRect && this->quickReject(*cullRect)) {
286445561a0b15fe045ba272c328684c3f7ae290785areed        return;
286545561a0b15fe045ba272c328684c3f7ae290785areed    }
286645561a0b15fe045ba272c328684c3f7ae290785areed
286745561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
286845561a0b15fe045ba272c328684c3f7ae290785areed
286945561a0b15fe045ba272c328684c3f7ae290785areed    while (iter.next()) {
287045561a0b15fe045ba272c328684c3f7ae290785areed        iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint());
287145561a0b15fe045ba272c328684c3f7ae290785areed    }
287245561a0b15fe045ba272c328684c3f7ae290785areed
287345561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_END
287445561a0b15fe045ba272c328684c3f7ae290785areed}
287545561a0b15fe045ba272c328684c3f7ae290785areed
287600d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
287700d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
28787ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
287985d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
288096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
288119653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
288285d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
288387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp;
288487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
288587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
288687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
288787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
28887ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
28897ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2890024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2891024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2892024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
289396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fFilter = nullptr;
2894024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
289585d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
289600d5c2c6523321d25b32905ff4822f083a4173eefmalita
2897aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2898aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2899024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
290000d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
290100d5c2c6523321d25b32905ff4822f083a4173eefmalita
2902aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2903024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2904024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
290500d5c2c6523321d25b32905ff4822f083a4173eefmalita}
290600d5c2c6523321d25b32905ff4822f083a4173eefmalita
2907e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2908e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2909e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
29109881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2911ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2912ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawText(text, byteLength, x, y, paint);
2913ac09554dce518e9d4496771f648f3ae17eca857creed    }
2914e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2915e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2916e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
29179881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2918ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2919ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosText(text, byteLength, pos, paint);
2920ac09554dce518e9d4496771f648f3ae17eca857creed    }
2921e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2922e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2923e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
29249881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2925ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2926ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2927ac09554dce518e9d4496771f648f3ae17eca857creed    }
2928e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2929e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2930e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
29319881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2932ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2933ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2934ac09554dce518e9d4496771f648f3ae17eca857creed    }
2935e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
293645561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
293745561a0b15fe045ba272c328684c3f7ae290785areed                               const SkRect* cullRect, const SkPaint& paint) {
293845561a0b15fe045ba272c328684c3f7ae290785areed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()");
293945561a0b15fe045ba272c328684c3f7ae290785areed    if (byteLength) {
294045561a0b15fe045ba272c328684c3f7ae290785areed        this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
294145561a0b15fe045ba272c328684c3f7ae290785areed    }
294245561a0b15fe045ba272c328684c3f7ae290785areed}
294300d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
294400d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
2945e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(blob);
29469881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2947e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawTextBlob(blob, x, y, paint);
294800d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2949e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
295041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
295141af966ab338e95eee81ab618ab28195075338f7reed                              const SkPoint verts[], const SkPoint texs[],
295241af966ab338e95eee81ab618ab28195075338f7reed                              const SkColor colors[], SkXfermode* xmode,
295341af966ab338e95eee81ab618ab28195075338f7reed                              const uint16_t indices[], int indexCount,
295441af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint& paint) {
29559881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
295696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
29574b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
29588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
29598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
29604e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   colors, xmode, indices, indexCount,
29614e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                   looper.paint());
29628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
29634b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
29644e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
29658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
29668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2967b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2968b3c9d1c33caf325aada244204215eb790c228c12dandov                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
29699881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
297096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == cubics) {
2971b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2972b3c9d1c33caf325aada244204215eb790c228c12dandov    }
29736cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2974ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2975ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2976ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2977b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2978ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2979ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2980ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
29816cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2982b3c9d1c33caf325aada244204215eb790c228c12dandov    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2983b3c9d1c33caf325aada244204215eb790c228c12dandov}
2984b3c9d1c33caf325aada244204215eb790c228c12dandov
2985b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2986b3c9d1c33caf325aada244204215eb790c228c12dandov                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2987b3c9d1c33caf325aada244204215eb790c228c12dandov
298896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
29896cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2990ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2991b3c9d1c33caf325aada244204215eb790c228c12dandov        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2992ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
29936cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2994ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2995ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2996ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2997a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2998e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2999e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (x || y) {
3000e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
3001e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, &matrix);
3002e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
3003e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, nullptr);
3004a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
3005a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
3006a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
3007a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
3008e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
3009e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
3010e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
30116a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
3012e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawDrawable(dr, matrix);
30136a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
30146a070dc06af4e9f305f9d08a69e34d18ade473cbreed
3015a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
3016a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    SkRect bounds = dr->getBounds();
3017a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (matrix) {
3018a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        matrix->mapRect(&bounds);
3019a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
3020a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    if (this->quickReject(bounds)) {
3021a8db72864a43ad1fbba3c2892cf5cd88060a43efreed        return;
3022a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
3023a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
30246a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
30256a070dc06af4e9f305f9d08a69e34d18ade473cbreed
302671c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
302771c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkColor colors[], int count, SkXfermode::Mode mode,
302871c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
302971c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
303071c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
303171c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
303271c3c760a83123ee0b3127b8c65c6394ce541c50reed
303371c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
303471c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
303571c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
303671c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
30379d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
303896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
303971c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
304071c3c760a83123ee0b3127b8c65c6394ce541c50reed        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt);
304171c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
304271c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
304371c3c760a83123ee0b3127b8c65c6394ce541c50reed}
304471c3c760a83123ee0b3127b8c65c6394ce541c50reed
3045f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
3046f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkASSERT(key);
3047f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
3048f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkPaint paint;
3049f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
3050f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    while (iter.next()) {
3051f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        iter.fDevice->drawAnnotation(iter, rect, key, value);
3052f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
3053f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_END
3054f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
3055f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
30568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
30578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
30588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
30598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
30608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
3062845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::Mode mode) {
30639881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
30648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
30658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setARGB(a, r, g, b);
3067845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
30680baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
30698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
30708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
30718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3073845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comvoid SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
30749881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
30758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
30768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
3078845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kSrcOver_Mode != mode) {
30790baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com        paint.setXfermodeMode(mode);
30808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
30818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
30828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
30859881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
30868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
30874b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
30888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
30898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
30908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
30939881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
30948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pt;
30958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
30964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
30978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pt.set(x, y);
30988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(color);
30998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
31008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
31018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
31038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        const SkPaint& paint) {
31049881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
31058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
31064b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
31078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
31088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
31098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
31108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
31118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
31138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              SkScalar right, SkScalar bottom,
31148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPaint& paint) {
31159881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
31168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
31178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, top, right, bottom);
31198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawRect(r, paint);
31208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
31218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
31238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          const SkPaint& paint) {
31249881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
31258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
31268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
31278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
31288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
31308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
31314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
31328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
31338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
31358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
31369881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
31378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
31384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
31394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
31404ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
31418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
31428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
31438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
31448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
31458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
31478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
31488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
31499881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
315021af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    if (oval.isEmpty() || !sweepAngle) {
315121af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon        return;
31528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
315321af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
31548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
31558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
31578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
31588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
31599881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
31608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
31614b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
31628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
31638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
31648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
31658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3166f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
31671c2c441fede0ae9573afc098017011e3439624a9reed
31681c2c441fede0ae9573afc098017011e3439624a9reed/**
31691c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
31701c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
31711c2c441fede0ae9573afc098017011e3439624a9reed *
31721c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
31731c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
31741c2c441fede0ae9573afc098017011e3439624a9reed */
31751c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
31769b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
3177d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
3178e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(picture);
3179e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
31801c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
3181e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
3182e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
3183e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    }
3184e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
3185e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
3186e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        picture->playback(this);
3187e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
3188e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawPicture(picture, matrix, paint);
3189d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
3190d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
31919b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
3192d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
3193d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
3194d028180f0310cf2b23f9744256a41697b0683e67fmalita    if (!paint || paint->canComputeFastBounds()) {
3195d028180f0310cf2b23f9744256a41697b0683e67fmalita        SkRect bounds = picture->cullRect();
3196d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (paint) {
3197d028180f0310cf2b23f9744256a41697b0683e67fmalita            paint->computeFastBounds(bounds, &bounds);
3198d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
3199d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (matrix) {
3200d028180f0310cf2b23f9744256a41697b0683e67fmalita            matrix->mapRect(&bounds);
3201d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
3202d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (this->quickReject(bounds)) {
3203d028180f0310cf2b23f9744256a41697b0683e67fmalita            return;
3204d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
3205d028180f0310cf2b23f9744256a41697b0683e67fmalita    }
3206d028180f0310cf2b23f9744256a41697b0683e67fmalita
3207a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
3208c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
32098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
32108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
321195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
321295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::drawShadowedPicture(const SkPicture* picture,
321395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack                                   const SkMatrix* matrix,
3214e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                   const SkPaint* paint,
3215e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                   const SkShadowParams& params) {
321695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    RETURN_ON_NULL(picture);
321795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
321895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()");
321995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
3220e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    this->onDrawShadowedPicture(picture, matrix, paint, params);
322195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
322295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
322395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
322495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack                                     const SkMatrix* matrix,
3225e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                     const SkPaint* paint,
3226e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                     const SkShadowParams& params) {
3227904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    if (!paint || paint->canComputeFastBounds()) {
3228904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkRect bounds = picture->cullRect();
3229904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (paint) {
3230904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            paint->computeFastBounds(bounds, &bounds);
3231904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
3232904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (matrix) {
3233904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            matrix->mapRect(&bounds);
3234904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
3235904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (this->quickReject(bounds)) {
3236904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            return;
3237904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
3238904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
3239904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3240904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
3241904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3242e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    sk_sp<SkImage> povDepthMap;
3243e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    sk_sp<SkImage> diffuseMap;
3244e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack
3245904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    // povDepthMap
3246904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    {
3247904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkLights::Builder builder;
3248772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
3249772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack                                                     SkVector3::Make(0.0f, 0.0f, 1.0f)));
3250904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkLights> povLight = builder.finish();
3251904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3252904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
3253904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             picture->cullRect().height(),
3254904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kBGRA_8888_SkColorType,
3255904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kOpaque_SkAlphaType);
3256904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3257904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // Create a new surface (that matches the backend of canvas)
3258904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // to create the povDepthMap
3259904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkSurface> surf(this->makeSurface(info));
3260904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3261904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // Wrap another SPFCanvas around the surface
3262904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
3263904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
3264904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3265904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // set the depth map canvas to have the light as the user's POV
3266904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        depthMapCanvas->setLights(std::move(povLight));
3267904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3268904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        depthMapCanvas->drawPicture(picture);
3269904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        povDepthMap = surf->makeImageSnapshot();
3270904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
3271904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3272904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    // diffuseMap
3273904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    {
3274904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
3275904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             picture->cullRect().height(),
3276904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kBGRA_8888_SkColorType,
3277904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kOpaque_SkAlphaType);
3278904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3279904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkSurface> surf(this->makeSurface(info));
3280904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        surf->getCanvas()->drawPicture(picture);
3281904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3282904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        diffuseMap = surf->makeImageSnapshot();
3283904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
3284904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3285904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode,
3286904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                             SkShader::kClamp_TileMode);
3287904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode,
3288904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                           SkShader::kClamp_TileMode);
3289b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3290b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    // TODO: pass the depth to the shader in vertices, or uniforms
3291b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    //       so we don't have to render depth and color separately
3292b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    for (int i = 0; i < fLights->numLights(); ++i) {
3293b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        // skip over ambient lights; they don't cast shadows
3294b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        // lights that have shadow maps do not need updating (because lights are immutable)
3295b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        sk_sp<SkImage> depthMap;
3296b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        SkISize shMapSize;
3297b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3298b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (fLights->light(i).getShadowMap() != nullptr) {
3299b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            continue;
3300b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
3301b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3302b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (fLights->light(i).isRadial()) {
3303b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize.fHeight = 1;
3304b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize.fWidth = (int) picture->cullRect().width();
3305b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3306b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo info = SkImageInfo::Make(diffuseMap->width(), 1,
3307b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kBGRA_8888_SkColorType,
3308b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kOpaque_SkAlphaType);
3309b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3310b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Create new surface (that matches the backend of canvas)
3311b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // for each shadow map
3312b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> surf(this->makeSurface(info));
3313b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3314b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Wrap another SPFCanvas around the surface
3315b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkCanvas* depthMapCanvas = surf->getCanvas();
3316b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3317b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkLights::Builder builder;
3318b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            builder.add(fLights->light(i));
3319b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkLights> curLight = builder.finish();
3320b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3321b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkShader> shadowMapShader;
3322b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shadowMapShader = SkRadialShadowMapShader::Make(
3323b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    povDepthShader, curLight,
3324b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().width(),
3325b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().height());
3326b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3327b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkPaint shadowMapPaint;
3328b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shadowMapPaint.setShader(std::move(shadowMapShader));
3329b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3330b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setLights(curLight);
3331b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3332b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->drawRect(SkRect::MakeIWH(diffuseMap->width(),
3333b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     diffuseMap->height()),
3334b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                     shadowMapPaint);
3335b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3336b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMap = surf->makeImageSnapshot();
3337b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3338b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        } else {
3339b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: compute the correct size of the depth map from the light properties
3340b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: maybe add a kDepth_8_SkColorType
3341b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: find actual max depth of picture
3342b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize = SkShadowPaintFilterCanvas::ComputeDepthMapSize(
3343b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    fLights->light(i), 255,
3344b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().width(),
3345b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().height());
3346b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3347b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo info = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3348b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kBGRA_8888_SkColorType,
3349b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kOpaque_SkAlphaType);
3350b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3351b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Create a new surface (that matches the backend of canvas)
3352b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // for each shadow map
3353b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> surf(this->makeSurface(info));
3354b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3355b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Wrap another SPFCanvas around the surface
3356b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
3357b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
3358b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setShadowParams(params);
3359b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3360b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // set the depth map canvas to have the light we're drawing.
3361b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkLights::Builder builder;
3362b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            builder.add(fLights->light(i));
3363b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkLights> curLight = builder.finish();
3364b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setLights(std::move(curLight));
3365b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3366b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->drawPicture(picture);
3367b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMap = surf->makeImageSnapshot();
3368b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
3369b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3370b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (params.fType == SkShadowParams::kNoBlur_ShadowType) {
3371b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            fLights->light(i).setShadowMap(std::move(depthMap));
3372b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        } else if (params.fType == SkShadowParams::kVariance_ShadowType) {
3373b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // we blur the variance map
3374b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkPaint blurPaint;
3375b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            blurPaint.setImageFilter(SkImageFilter::MakeBlur(params.fShadowRadius,
3376b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                             params.fShadowRadius, nullptr));
3377b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3378b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo blurInfo = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3379b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     kBGRA_8888_SkColorType,
3380b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     kOpaque_SkAlphaType);
3381b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3382b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> blurSurf(this->makeSurface(blurInfo));
3383b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3384b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            blurSurf->getCanvas()->drawImage(std::move(depthMap), 0, 0, &blurPaint);
3385b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3386b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            fLights->light(i).setShadowMap(blurSurf->makeImageSnapshot());
3387b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
3388b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    }
3389b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3390b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    SkPaint shadowPaint;
3391904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader),
3392904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                        std::move(diffuseShader),
3393b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                        fLights,
3394904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                        diffuseMap->width(),
3395e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                                        diffuseMap->height(),
3396e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                                        params);
3397904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3398904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    shadowPaint.setShader(shadowShader);
3399904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3400904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    this->drawRect(SkRect::MakeIWH(diffuseMap->width(), diffuseMap->height()), shadowPaint);
340195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
340295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
340395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
34048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
34058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
34068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34073aafe111b6cc388400092851cc53bbbdfcb8a81creedSkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
340899fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
34098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
34118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34123aafe111b6cc388400092851cc53bbbdfcb8a81creed    fImpl = new (fStorage) SkDrawIter(canvas);
34138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
34148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
34158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
34178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
34188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
34198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
34218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
34228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
34238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34241f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
34258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getDevice();
34268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
34278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
34298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fImpl->getMatrix();
34308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
34318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
34338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
343496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
34358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
34368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
34378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
34388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
34398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34401e7f5e708e5daeb0c18ae49001c9e3cd5e3b13cbreedconst SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
34418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
34428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
344320a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
344420a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
344520a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
3446c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitaSkCanvasClipVisitor::~SkCanvasClipVisitor() { }
34473107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
34483107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
34493107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
34503107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
34513107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
34523107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
34533107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
34543107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
34553107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
34563107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
34573107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
34583107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
34593107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
34603107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
34613107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
346228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
34633107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
34643107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
34653107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
34663107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
34673107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
34683107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
34693107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
34703107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
347142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.orgSkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
347242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
347396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
347442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
3475eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
347642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
347742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
347896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
347942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
3480385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkCanvas(bitmap);
348142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
3482d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3483d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
3484d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3485d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
3486a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
3487d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
3488d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
3489d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
349049f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
3491a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
3492d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
3493a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
3494d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
3495a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
349649f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
3497d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
3498d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
34996cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
350049f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
3501d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
3502d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
3503d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
3504d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3505d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3506d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
3507d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
3508e8f3062a36d3682f4019309a32b5b84dc9eddf8creed
3509e8f3062a36d3682f4019309a32b5b84dc9eddf8creed#ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API
3510e8f3062a36d3682f4019309a32b5b84dc9eddf8creedSkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
3511e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    return this->makeSurface(info, props).release();
3512e8f3062a36d3682f4019309a32b5b84dc9eddf8creed}
3513e8f3062a36d3682f4019309a32b5b84dc9eddf8creed#endif
3514